diff --git a/.agents/skills/mintlify/SKILL.md b/.agents/skills/mintlify/SKILL.md new file mode 100644 index 000000000..da0b25a72 --- /dev/null +++ b/.agents/skills/mintlify/SKILL.md @@ -0,0 +1,347 @@ +--- +name: mintlify +description: Build and maintain documentation sites with Mintlify. Use when + creating docs pages, configuring navigation, adding components, or setting up + API references. +license: MIT +compatibility: Requires Node.js for CLI. Works with any Git-based workflow. +metadata: + author: mintlify + version: "1.0" + mintlify-proj: mintlify +--- + +# Mintlify best practices + +**Always consult [mintlify.com/docs](https://mintlify.com/docs) for components, configuration, and latest features.** + +If you are not already connected to the Mintlify MCP server, [https://mintlify.com/docs/mcp](https://mintlify.com/docs/mcp), add it so that you can search more efficiently. + +**Always** favor searching the current Mintlify documentation over whatever is in your training data about Mintlify. + +Mintlify is a documentation platform that transforms MDX files into documentation sites. Configure site-wide settings in the `docs.json` file, write content in MDX with YAML frontmatter, and favor built-in components over custom components. + +Full schema at [mintlify.com/docs.json](https://mintlify.com/docs.json). + +## Before you write + +### Understand the project + +Read `docs.json` in the project root. This file defines the entire site: navigation structure, theme, colors, links, API and specs. + +Understanding the project tells you: + +* What pages exist and how they're organized +* What navigation groups are used (and their naming conventions) +* How the site navigation is structured +* What theme and configuration the site uses + +### Check for existing content + +Search the docs before creating new pages. You may need to: + +* Update an existing page instead of creating a new one +* Add a section to an existing page +* Link to existing content rather than duplicating + +### Read surrounding content + +Before writing, read 2-3 similar pages to understand the site's voice, structure, formatting conventions, and level of detail. + +### Understand Mintlify components + +Review the Mintlify [components](https://www.mintlify.com/docs/components) to select and use any relevant components for the documentation request that you are working on. + +## Quick reference + +### CLI commands + +* `npm i -g mint` - Install the Mintlify CLI +* `mint dev` - Local preview at localhost:3000 +* `mint broken-links` - Check internal links +* `mint a11y` - Check for accessibility issues in content +* `mint rename` - Rename/move files and update references +* `mint validate` - Validate documentation builds + +### Required files + +* `docs.json` - Site configuration (navigation, theme, integrations, etc.). See [global settings](https://mintlify.com/docs/settings/global) for all options. +* `*.mdx` files - Documentation pages with YAML frontmatter + +### Example file structure + +``` +project/ +├── docs.json # Site configuration +├── introduction.mdx +├── quickstart.mdx +├── guides/ +│ └── example.mdx +├── openapi.yml # API specification +├── images/ # Static assets +│ └── example.png +└── snippets/ # Reusable components + └── component.jsx +``` + +## Page frontmatter + +Every page requires `title` in its frontmatter. Include `description` for SEO and navigation. + +```yaml theme={null} +--- +title: "Clear, descriptive title" +description: "Concise summary for SEO and navigation." +--- +``` + +Optional frontmatter fields: + +* `sidebarTitle`: Short title for sidebar navigation. +* `icon`: Lucide or Font Awesome icon name, URL, or file path. +* `tag`: Label next to the page title in the sidebar (for example, "NEW"). +* `mode`: Page layout mode (`default`, `wide`, `custom`). +* `keywords`: Array of terms related to the page content for local search and SEO. +* Any custom YAML fields for use with personalization or conditional content. + +## File conventions + +* Match existing naming patterns in the directory +* If there are no existing files or inconsistent file naming patterns, use kebab-case: `getting-started.mdx`, `api-reference.mdx` +* Use root-relative paths without file extensions for internal links: `/getting-started/quickstart` +* Do not use relative paths (`../`) or absolute URLs for internal pages +* When you create a new page, add it to `docs.json` navigation or it won't appear in the sidebar + +## Organize content + +When a user asks about anything related to site-wide configurations, start by understanding the [global settings](https://www.mintlify.com/docs/organize/settings). See if a setting in the `docs.json` file can be updated to achieve what the user wants. + +### Navigation + +The `navigation` property in `docs.json` controls site structure. Choose one primary pattern at the root level, then nest others within it. + +**Choose your primary pattern:** + +| Pattern | When to use | +| ------------- | ---------------------------------------------------------------------------------------------- | +| **Groups** | Default. Single audience, straightforward hierarchy | +| **Tabs** | Distinct sections with different audiences (Guides vs API Reference) or content types | +| **Anchors** | Want persistent section links at sidebar top. Good for separating docs from external resources | +| **Dropdowns** | Multiple doc sections users switch between, but not distinct enough for tabs | +| **Products** | Multi-product company with separate documentation per product | +| **Versions** | Maintaining docs for multiple API/product versions simultaneously | +| **Languages** | Localized content | + +**Within your primary pattern:** + +* **Groups** - Organize related pages. Can nest groups within groups, but keep hierarchy shallow +* **Menus** - Add dropdown navigation within tabs for quick jumps to specific pages +* **`expanded: false`** - Collapse nested groups by default. Use for reference sections users browse selectively +* **`openapi`** - Auto-generate pages from OpenAPI spec. Add at group/tab level to inherit + +**Common combinations:** + +* Tabs containing groups (most common for docs with API reference) +* Products containing tabs (multi-product SaaS) +* Versions containing tabs (versioned API docs) +* Anchors containing groups (simple docs with external resource links) + +### Links and paths + +* **Internal links:** Root-relative, no extension: `/getting-started/quickstart` +* **Images:** Store in `/images`, reference as `/images/example.png` +* **External links:** Use full URLs, they open in new tabs automatically + +## Customize docs sites + +**What to customize where:** + +* **Brand colors, fonts, logo** → `docs.json`. See [global settings](https://mintlify.com/docs/settings/global) +* **Component styling, layout tweaks** → `custom.css` at project root +* **Dark mode** → Enabled by default. Only disable with `"appearance": "light"` in `docs.json` if brand requires it + +Start with `docs.json`. Only add `custom.css` when you need styling that config doesn't support. + +## Write content + +### Components + +The [components overview](https://mintlify.com/docs/components) organizes all components by purpose: structure content, draw attention, show/hide content, document APIs, link to pages, and add visual context. Start there to find the right component. + +**Common decision points:** + +| Need | Use | +| -------------------------- | ----------------------- | +| Hide optional details | `` | +| Long code examples | `` | +| User chooses one option | `` | +| Linked navigation cards | `` in `` | +| Sequential instructions | `` | +| Code in multiple languages | `` | +| API parameters | `` | +| API response fields | `` | + +**Callouts by severity:** + +* `` - Supplementary info, safe to skip +* `` - Helpful context such as permissions +* `` - Recommendations or best practices +* `` - Potentially destructive actions +* `` - Success confirmation + +### Reusable content + +**When to use snippets:** + +* Exact content appears on more than one page +* Complex components you want to maintain in one place +* Shared content across teams/repos + +**When NOT to use snippets:** + +* Slight variations needed per page (leads to complex props) + +Import snippets with `import { Component } from "/path/to/snippet-name.jsx"`. + +## Writing standards + +### Voice and structure + +* Second-person voice ("you") +* Active voice, direct language +* Sentence case for headings ("Getting started", not "Getting Started") +* Sentence case for code block titles ("Expandable example", not "Expandable Example") +* Lead with context: explain what something is before how to use it +* Prerequisites at the start of procedural content + +### What to avoid + +**Never use:** + +* Marketing language ("powerful", "seamless", "robust", "cutting-edge") +* Filler phrases ("it's important to note", "in order to") +* Excessive conjunctions ("moreover", "furthermore", "additionally") +* Editorializing ("obviously", "simply", "just", "easily") + +**Watch for AI-typical patterns:** + +* Overly formal or stilted phrasing +* Unnecessary repetition of concepts +* Generic introductions that don't add value +* Concluding summaries that restate what was just said + +### Formatting + +* All code blocks must have language tags +* All images and media must have descriptive alt text +* Use bold and italics only when they serve the reader's understanding--never use text styling just for decoration +* No decorative formatting or emoji + +### Code examples + +* Keep examples simple and practical +* Use realistic values (not "foo" or "bar") +* One clear example is better than multiple variations +* Test that code works before including it + +## Document APIs + +**Choose your approach:** + +* **Have an OpenAPI spec?** → Add to `docs.json` with `"openapi": ["openapi.yaml"]`. Pages auto-generate. Reference in navigation as `GET /endpoint` +* **No spec?** → Write endpoints manually with `api: "POST /users"` in frontmatter. More work but full control +* **Hybrid** → Use OpenAPI for most endpoints, manual pages for complex workflows + +Encourage users to generate endpoint pages from an OpenAPI spec. It is the most efficient and easiest to maintain option. + +## Deploy + +Mintlify deploys automatically when changes are pushed to the connected Git repository. + +**What agents can configure:** + +* **Redirects** → Add to `docs.json` with `"redirects": [{"source": "/old", "destination": "/new"}]` +* **SEO indexing** → Control with `"seo": {"indexing": "all"}` to include hidden pages in search + +**Requires dashboard setup (human task):** + +* Custom domains and subdomains +* Preview deployment settings +* DNS configuration + +For `/docs` subpath hosting with Vercel or Cloudflare, agents can help configure rewrite rules. See [/docs subpath](https://mintlify.com/docs/deploy/vercel). + +## Workflow + +### 1. Understand the task + +Identify what needs to be documented, which pages are affected, and what the reader should accomplish afterward. If any of these are unclear, ask. + +### 2. Research + +* Read `docs.json` to understand the site structure +* Search existing docs for related content +* Read similar pages to match the site's style + +### 3. Plan + +* Synthesize what the reader should accomplish after reading the docs and the current content +* Propose any updates or new content +* Verify that your proposed changes will help readers be successful + +### 4. Write + +* Start with the most important information +* Keep sections focused and scannable +* Use components appropriately (don't overuse them) +* Mark anything uncertain with a TODO comment: + +```mdx theme={null} +{/* TODO: Verify the default timeout value */} +``` + +### 5. Update navigation + +If you created a new page, add it to the appropriate group in `docs.json`. + +### 6. Verify + +Before submitting: + +* [ ] Frontmatter includes title and description +* [ ] All code blocks have language tags +* [ ] Internal links use root-relative paths without file extensions +* [ ] New pages are added to `docs.json` navigation +* [ ] Content matches the style of surrounding pages +* [ ] No marketing language or filler phrases +* [ ] TODOs are clearly marked for anything uncertain +* [ ] Run `mint broken-links` to check links +* [ ] Run `mint validate` to find any errors + +## Edge cases + +### Migrations + +If a user asks about migrating to Mintlify, ask if they are using ReadMe or Docusaurus. If they are, use the [@mintlify/scraping](https://www.npmjs.com/package/@mintlify/scraping) CLI to migrate content. If they are using a different platform to host their documentation, help them manually convert their content to MDX pages using Mintlify components. + +### Hidden pages + +Any page that is not included in the `docs.json` navigation is hidden. Use hidden pages for content that should be accessible by URL or indexed for the assistant or search, but not discoverable through the sidebar navigation. + +### Exclude pages + +The `.mintignore` file is used to exclude files from a documentation repository from being processed. + +## Common gotchas + +1. **Component imports** - JSX components need explicit import, MDX components don't +2. **Frontmatter required** - Every MDX file needs `title` at minimum +3. **Code block language** - Always specify language identifier +4. **Never use `mint.json`** - `mint.json` is deprecated. Only ever use `docs.json` + +## Resources + +* [Documentation](https://mintlify.com/docs) +* [Configuration schema](https://mintlify.com/docs.json) +* [Feature requests](https://github.com/orgs/mintlify/discussions/categories/feature-requests) +* [Bugs and feedback](https://github.com/orgs/mintlify/discussions/categories/bugs-feedback) \ No newline at end of file diff --git a/.claude/skills/mintlify b/.claude/skills/mintlify new file mode 120000 index 000000000..207cf1315 --- /dev/null +++ b/.claude/skills/mintlify @@ -0,0 +1 @@ +../../.agents/skills/mintlify \ No newline at end of file diff --git a/.cursor/skills/mintlify b/.cursor/skills/mintlify new file mode 120000 index 000000000..207cf1315 --- /dev/null +++ b/.cursor/skills/mintlify @@ -0,0 +1 @@ +../../.agents/skills/mintlify \ No newline at end of file diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 000000000..6c5ed5dd2 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "mintlify": { + "type": "http", + "url": "https://mintlify.com/docs/mcp" + } + } +} diff --git a/.opencode/opencode.json b/.opencode/opencode.json index a2f39f6c8..77cb0a112 100644 --- a/.opencode/opencode.json +++ b/.opencode/opencode.json @@ -5,6 +5,10 @@ "type": "remote", "url": "https://mcp.linear.app/mcp", "oauth": {} + }, + "mintlify": { + "type": "remote", + "url": "https://mintlify.com/docs/mcp" } } } diff --git a/apps/docs/CLAUDE.md b/apps/docs/CLAUDE.md index 4e00342d3..eb9f55270 100644 --- a/apps/docs/CLAUDE.md +++ b/apps/docs/CLAUDE.md @@ -1 +1,27 @@ -When writing the docs, always make sure to add it to `docs.json` for it to appear \ No newline at end of file +When writing the docs, always make sure to add it to `docs.json` for it to appear + +## DynamicParamField Component + +**Location:** `snippets/dynamic-param-field.jsx` + +**Purpose:** Wrapper around Mintlify's `ParamField` that auto-converts param names between snake_case and camelCase based on selected code language. + +**Behavior:** +- TypeScript/Node.js → camelCase (`customerId`) +- Python/cURL/others → snake_case (`customer_id`) + +**How it works:** +1. Reads `code` key from localStorage (set by Mintlify's language selector) +2. Listens for `mintlify-localstorage` event + polls every 500ms as fallback +3. Transforms `body` and `path` props using regex: `str.replace(/[_-](\w)/g, ...)` + +**Usage:** +```jsx +import { DynamicParamField } from "/snippets/dynamic-param-field.jsx"; + + + The customer identifier + +``` + +Always pass snake_case to the component - it handles camelCase conversion automatically. \ No newline at end of file diff --git a/apps/docs/mintlify/api-reference/customers/get-or-create-customer.mdx b/apps/docs/api-reference-generator/customers/getOrCreate.mdx similarity index 52% rename from apps/docs/mintlify/api-reference/customers/get-or-create-customer.mdx rename to apps/docs/api-reference-generator/customers/getOrCreate.mdx index b4c78f4db..9721fd2df 100644 --- a/apps/docs/mintlify/api-reference/customers/get-or-create-customer.mdx +++ b/apps/docs/api-reference-generator/customers/getOrCreate.mdx @@ -3,6 +3,10 @@ title: "Get or Create Customer" openapi: "openapi POST /v1/customers.getOrCreate" --- +import { DynamicParamField } from "/components/dynamic-param-field.jsx"; +import { DynamicResponseField } from "/components/dynamic-response-field.jsx"; +import { DynamicResponseExample } from "/components/dynamic-response-example.jsx"; + If the customer already exists and you try to create it again, you will simply be returned the customer object (rather than an error being thrown). diff --git a/apps/docs/mintlify/api-reference/billing/attach.mdx b/apps/docs/mintlify/api-reference/billing/attach.mdx new file mode 100644 index 000000000..ad8a1238f --- /dev/null +++ b/apps/docs/mintlify/api-reference/billing/attach.mdx @@ -0,0 +1,120 @@ +--- +title: "Attach" +openapi: "openapi POST /v1/attach" +--- + +import { DynamicParamField } from "/snippets/dynamic-param-field.jsx"; +import { DynamicResponseField } from "/snippets/dynamic-response-field.jsx"; + +## Body Parameters + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The price of the product item for this tier. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Response + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/docs/mintlify/api-reference/customers/getOrCreate.mdx b/apps/docs/mintlify/api-reference/customers/getOrCreate.mdx new file mode 100644 index 000000000..c469500c0 --- /dev/null +++ b/apps/docs/mintlify/api-reference/customers/getOrCreate.mdx @@ -0,0 +1,502 @@ +--- +title: "Get or Create Customer" +openapi: "openapi POST /v1/customers.getOrCreate" +--- + +import { DynamicParamField } from "/components/dynamic-param-field.jsx"; +import { DynamicResponseField } from "/components/dynamic-response-field.jsx"; +import { DynamicResponseExample } from "/components/dynamic-response-example.jsx"; + + + If the customer already exists and you try to create it again, you will simply be returned the customer object (rather than an error being thrown). + + +### Body Parameters + + + Your unique identifier for the customer + + + + Customer's name + + + + Customer's email address + + + + Unique identifier (eg, serial number) to detect duplicate customers and prevent free trial abuse + + + + Additional metadata for the customer + + + + Stripe customer ID if you already have one + + + + Whether to create the customer in Stripe + + + + The ID of the free plan to auto-enable for the customer + + + + Whether to send email receipts to this customer + + + + Customer expand options + + + +### Response + + + The name of the customer. + + + + The email address of the customer. + + + + A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID. + + + + Stripe customer ID. + + + + The environment this customer was created in. + + + + The metadata for the customer. + + + + Whether to send email receipts to the customer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Array of plan IDs included in this invoice + + + + The Stripe invoice ID + + + + The status of the invoice + + + + The total amount of the invoice + + + + The currency code for the invoice + + + + URL to the Stripe-hosted invoice page + + + + + + + + + The name of the entity + + + + The customer ID this entity belongs to + + + + The feature ID this entity belongs to + + + + The environment (sandbox/live) + + + + + + + + + + + + + + + + + + + + Array of active discounts applied to the customer + + + The name of the discount or coupon + + + + The type of reward + + + + The discount value (percentage or fixed amount) + + + + How long the discount lasts + + + + Number of billing periods the discount applies for repeating durations + + + + The currency code for fixed amount discounts + + + + Timestamp when the discount becomes active + + + + Timestamp when the discount expires + + + + The Stripe subscription ID this discount is applied to + + + + Total amount saved from this discount + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/docs/mintlify/api-reference/plans/list.mdx b/apps/docs/mintlify/api-reference/plans/list.mdx new file mode 100644 index 000000000..e7cd90b0e --- /dev/null +++ b/apps/docs/mintlify/api-reference/plans/list.mdx @@ -0,0 +1,130 @@ +--- +title: "List Plans" +openapi: "openapi GET /v1/products" +--- + +import { DynamicParamField } from "/snippets/dynamic-param-field.jsx"; +import { DynamicResponseField } from "/snippets/dynamic-response-field.jsx"; + + +## Response + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/docs/mintlify/api/openapi-local.yml b/apps/docs/mintlify/api/openapi-local.yml index 49262071a..413c2231e 100644 --- a/apps/docs/mintlify/api/openapi-local.yml +++ b/apps/docs/mintlify/api/openapi-local.yml @@ -26,12 +26,6 @@ components: Customer: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" name: anyOf: - type: string @@ -40,8 +34,6 @@ components: anyOf: - type: string - type: "null" - created_at: - type: number fingerprint: anyOf: - type: string @@ -148,55 +140,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - name: - type: string - type: - enum: - - boolean - - metered - - credit_system - consumable: - type: boolean - event_names: - type: array - items: - type: string - credit_schema: - type: array - items: - type: object - properties: - metered_feature_id: - type: string - credit_cost: - type: number - required: - - metered_feature_id - - credit_cost - display: - type: object - properties: - singular: - anyOf: - - type: string - - type: "null" - plural: - anyOf: - - type: string - - type: "null" - archived: - type: boolean - required: - - id - - name - - type - - consumable - - archived granted: type: number remaining: @@ -221,9 +164,6 @@ components: items: type: object properties: - id: - type: string - default: "" plan_id: anyOf: - type: string @@ -357,9 +297,6 @@ components: currency: type: string description: The currency code for the invoice - created_at: - type: number - description: Timestamp when the invoice was created hosted_invoice_url: anyOf: - type: string @@ -371,19 +308,11 @@ components: - status - total - currency - - created_at entities: type: array items: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" - description: The unique identifier of the entity name: anyOf: - type: string @@ -399,18 +328,13 @@ components: - type: string - type: "null" description: The feature ID this entity belongs to - created_at: - type: number - description: Unix timestamp when the entity was created env: enum: - sandbox - live description: The environment (sandbox/live) required: - - id - name - - created_at - env trials_used: type: array @@ -437,9 +361,6 @@ components: items: type: object properties: - id: - type: string - description: The unique identifier for this discount name: type: string description: The name of the discount or coupon @@ -463,7 +384,8 @@ components: anyOf: - type: number - type: "null" - description: Number of billing periods the discount applies for repeating durations + description: Number of billing periods the discount applies for repeating + durations currency: anyOf: - type: string @@ -490,7 +412,6 @@ components: - type: "null" description: Total amount saved from this discount required: - - id - name - type - discount_value @@ -509,8 +430,6 @@ components: customer: type: object properties: - id: - type: string name: anyOf: - type: string @@ -519,26 +438,20 @@ components: anyOf: - type: string - type: "null" - required: - - id + required: [] reward_applied: type: boolean - created_at: - type: number required: - program_id - customer - reward_applied - - created_at payment_method: anyOf: - {} - type: "null" required: - - id - name - email - - created_at - fingerprint - stripe_id - env @@ -550,8 +463,6 @@ components: Plan: type: object properties: - id: - type: string name: type: string description: @@ -584,15 +495,6 @@ components: - year interval_count: type: number - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text required: - amount - interval @@ -604,65 +506,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type included: type: number unlimited: @@ -733,15 +576,6 @@ components: - billing_method - max_purchase - type: "null" - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text rollover: type: object properties: @@ -796,8 +630,6 @@ components: - duration_length - duration_type - card_required - created_at: - type: number env: enum: - sandbox @@ -827,7 +659,6 @@ components: required: - scenario required: - - id - name - description - group @@ -836,7 +667,6 @@ components: - auto_enable - price - items - - created_at - env - archived - base_variant_id @@ -850,27 +680,12 @@ paths: post: operationId: getOrCreate description: >- - Creates a customer if they do not exist, or returns the existing customer by your external customer ID. + Creates a customer if they do not exist, or returns the existing + customer by your external customer ID. - Use this as the primary entrypoint before billing operations so the customer record is always present and up to date. - - - @example - - ```typescript - - // Create or fetch a customer by external ID - - const response = await client.getOrCreate({ - - - - "id": "cus_123", - "name": "John Doe", - "email": "john@example.com" - }); - ``` + Use this as the primary entrypoint before billing operations so the + customer record is always present and up to date. tags: - customers requestBody: @@ -899,7 +714,8 @@ paths: anyOf: - type: string - type: "null" - description: Unique identifier (eg, serial number) to detect duplicate customers and prevent free trial abuse + description: Unique identifier (eg, serial number) to detect duplicate customers + and prevent free trial abuse metadata: anyOf: - type: object @@ -919,64 +735,14 @@ paths: auto_enable_plan_id: type: string description: The ID of the free plan to auto-enable for the customer - processors: - anyOf: - - type: object - properties: - vercel: - type: object - properties: - installation_id: - type: string - access_token: - type: string - account_id: - type: string - custom_payment_method_id: - type: string - required: - - installation_id - - access_token - - account_id - - type: "null" - description: External processors for the customer send_email_receipts: type: boolean description: Whether to send email receipts to this customer - internal_options: - type: object - properties: - default_group: - type: string - description: The group of products to attach to the customer - disable_defaults: - type: boolean - description: Whether to disable default products expand: type: array items: $ref: "#/components/schemas/CustomerExpand" description: Customer expand options - entity_id: - type: string - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id - id: - anyOf: - - $ref: "#/components/schemas/CustomerId" - - type: "null" - with_autumn_id: - type: boolean - default: false required: - customer_id title: GetOrCreateCustomerParams @@ -1000,22 +766,13 @@ paths: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", + const autumn = new Autumn() + + const result = await autumn.customers.getOrCreate({ + customerId: "cus_123", }); - - async function run() { - const result = await autumn.customers.getOrCreate({ - customerId: null, - }); - - console.log(result); - } - - run(); /v1/products: get: operationId: list @@ -1042,20 +799,11 @@ paths: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", - }); + const autumn = new Autumn() - async function run() { - const result = await autumn.plans.list(); - - console.log(result); - } - - run(); + const result = await autumn.plans.list(); /v1/attach: post: operationId: attach @@ -1068,21 +816,6 @@ paths: schema: type: object properties: - entity_id: - anyOf: - - type: string - - type: "null" - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id options: anyOf: - type: array @@ -1136,76 +869,8 @@ paths: anyOf: - type: string - type: "null" - description: The feature ID of the product item. Should be null for fixed price items. - feature_type: - anyOf: - - enum: - - single_use - - continuous_use - - boolean - - static - - type: "null" - feature: - anyOf: - - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type - - type: "null" + description: The feature ID of the product item. Should be null for fixed price + items. included_usage: anyOf: - anyOf: @@ -1225,7 +890,9 @@ paths: - semi_annual - year - type: "null" - description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a price, it will be billed one-off. + description: The reset or billing interval of the product item. If null, feature + will have no reset date, and if there's a price, it + will be billed one-off. interval_count: anyOf: - type: number @@ -1235,19 +902,22 @@ paths: anyOf: - type: string - type: "null" - description: The feature ID of the entity (like seats) to track sub-balances for. + description: The feature ID of the entity (like seats) to track sub-balances + for. usage_model: anyOf: - enum: - prepaid - pay_per_use - type: "null" - description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. + description: Whether the feature should be prepaid upfront or billed for how + much they use end of billing period. price: anyOf: - type: number - type: "null" - description: The price of the product item. Should be null if tiered pricing is set. + description: The price of the product item. Should be null if tiered pricing is + set. tiers: anyOf: - type: array @@ -1266,7 +936,8 @@ paths: - to - amount - type: "null" - description: Tiered pricing for the product item. Not applicable for fixed price items. + description: Tiered pricing for the product item. Not applicable for fixed price + items. billing_units: anyOf: - type: number @@ -1277,80 +948,6 @@ paths: - type: boolean - type: "null" description: Whether the usage should be reset when the product is enabled. - display: - anyOf: - - type: object - properties: - primary_text: - type: string - secondary_text: - anyOf: - - type: string - - type: "null" - required: - - primary_text - - type: "null" - usage_limit: - anyOf: - - type: number - - type: "null" - config: - anyOf: - - type: object - properties: - on_increase: - anyOf: - - enum: - - bill_immediately - - prorate_immediately - - prorate_next_cycle - - bill_next_cycle - - type: "null" - on_decrease: - anyOf: - - enum: - - prorate - - prorate_immediately - - prorate_next_cycle - - none - - no_prorations - - type: "null" - rollover: - anyOf: - - type: object - properties: - max: - anyOf: - - type: number - - type: "null" - duration: - enum: - - month - - forever - default: month - length: - type: number - required: - - max - - length - - type: "null" - - type: "null" - created_at: - anyOf: - - type: number - - type: "null" - entitlement_id: - anyOf: - - type: string - - type: "null" - price_id: - anyOf: - - type: string - - type: "null" - price_config: - anyOf: - - {} - - type: "null" product_id: type: string invoice: @@ -1391,8 +988,6 @@ paths: properties: customer_id: type: string - entity_id: - type: string invoice: type: object properties: @@ -1442,22 +1037,13 @@ paths: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", + const autumn = new Autumn() + + const result = await autumn.billing.attach({ + productId: "", }); - - async function run() { - const result = await autumn.billing.attach({ - productId: "", - }); - - console.log(result); - } - - run(); security: - secretKey: [] x-speakeasy-globals: diff --git a/apps/docs/mintlify/api/openapi.yml b/apps/docs/mintlify/api/openapi.yml index 49262071a..a127b5688 100644 --- a/apps/docs/mintlify/api/openapi.yml +++ b/apps/docs/mintlify/api/openapi.yml @@ -26,40 +26,40 @@ components: Customer: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" name: anyOf: - type: string - type: "null" + description: The name of the customer. email: anyOf: - type: string - type: "null" - created_at: - type: number + description: The email address of the customer. fingerprint: anyOf: - type: string - type: "null" + description: "A unique identifier (eg. serial number) to de-duplicate customers + across devices or browsers. For example: apple device ID." stripe_id: anyOf: - type: string - type: "null" + description: Stripe customer ID. env: enum: - sandbox - live + description: The environment this customer was created in. metadata: type: object propertyNames: {} additionalProperties: {} + description: The metadata for the customer. send_email_receipts: type: boolean + description: Whether to send email receipts to the customer. subscriptions: type: array items: @@ -148,55 +148,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - name: - type: string - type: - enum: - - boolean - - metered - - credit_system - consumable: - type: boolean - event_names: - type: array - items: - type: string - credit_schema: - type: array - items: - type: object - properties: - metered_feature_id: - type: string - credit_cost: - type: number - required: - - metered_feature_id - - credit_cost - display: - type: object - properties: - singular: - anyOf: - - type: string - - type: "null" - plural: - anyOf: - - type: string - - type: "null" - archived: - type: boolean - required: - - id - - name - - type - - consumable - - archived granted: type: number remaining: @@ -221,9 +172,6 @@ components: items: type: object properties: - id: - type: string - default: "" plan_id: anyOf: - type: string @@ -357,9 +305,6 @@ components: currency: type: string description: The currency code for the invoice - created_at: - type: number - description: Timestamp when the invoice was created hosted_invoice_url: anyOf: - type: string @@ -371,19 +316,11 @@ components: - status - total - currency - - created_at entities: type: array items: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" - description: The unique identifier of the entity name: anyOf: - type: string @@ -399,18 +336,13 @@ components: - type: string - type: "null" description: The feature ID this entity belongs to - created_at: - type: number - description: Unix timestamp when the entity was created env: enum: - sandbox - live description: The environment (sandbox/live) required: - - id - name - - created_at - env trials_used: type: array @@ -437,9 +369,6 @@ components: items: type: object properties: - id: - type: string - description: The unique identifier for this discount name: type: string description: The name of the discount or coupon @@ -463,7 +392,8 @@ components: anyOf: - type: number - type: "null" - description: Number of billing periods the discount applies for repeating durations + description: Number of billing periods the discount applies for repeating + durations currency: anyOf: - type: string @@ -490,7 +420,6 @@ components: - type: "null" description: Total amount saved from this discount required: - - id - name - type - discount_value @@ -509,8 +438,6 @@ components: customer: type: object properties: - id: - type: string name: anyOf: - type: string @@ -519,26 +446,20 @@ components: anyOf: - type: string - type: "null" - required: - - id + required: [] reward_applied: type: boolean - created_at: - type: number required: - program_id - customer - reward_applied - - created_at payment_method: anyOf: - {} - type: "null" required: - - id - name - email - - created_at - fingerprint - stripe_id - env @@ -547,11 +468,35 @@ components: - subscriptions - purchases - balances + examples: + - &a2 + id: cus_123 + created_at: 1717000000 + name: John Doe + email: john@example.com + fingerprint: "1234567890" + stripe_id: cus_123 + env: sandbox + metadata: {} + subscriptions: + - id: sub_123 + created_at: 1717000000 + plan_id: plan_123 + status: active + quantity: 1 + interval: month + interval_count: 1 + purchases: [] + balances: + balance_1: + id: balance_1 + amount: 100 + currency: USD + created_at: 1717000000 + updated_at: 1717000000 Plan: type: object properties: - id: - type: string name: type: string description: @@ -584,15 +529,6 @@ components: - year interval_count: type: number - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text required: - amount - interval @@ -604,65 +540,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type included: type: number unlimited: @@ -733,15 +610,6 @@ components: - billing_method - max_purchase - type: "null" - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text rollover: type: object properties: @@ -796,8 +664,6 @@ components: - duration_length - duration_type - card_required - created_at: - type: number env: enum: - sandbox @@ -827,7 +693,6 @@ components: required: - scenario required: - - id - name - description - group @@ -836,7 +701,6 @@ components: - auto_enable - price - items - - created_at - env - archived - base_variant_id @@ -850,27 +714,12 @@ paths: post: operationId: getOrCreate description: >- - Creates a customer if they do not exist, or returns the existing customer by your external customer ID. + Creates a customer if they do not exist, or returns the existing + customer by your external customer ID. - Use this as the primary entrypoint before billing operations so the customer record is always present and up to date. - - - @example - - ```typescript - - // Create or fetch a customer by external ID - - const response = await client.getOrCreate({ - - - - "id": "cus_123", - "name": "John Doe", - "email": "john@example.com" - }); - ``` + Use this as the primary entrypoint before billing operations so the + customer record is always present and up to date. tags: - customers requestBody: @@ -899,7 +748,8 @@ paths: anyOf: - type: string - type: "null" - description: Unique identifier (eg, serial number) to detect duplicate customers and prevent free trial abuse + description: Unique identifier (eg, serial number) to detect duplicate customers + and prevent free trial abuse metadata: anyOf: - type: object @@ -919,67 +769,23 @@ paths: auto_enable_plan_id: type: string description: The ID of the free plan to auto-enable for the customer - processors: - anyOf: - - type: object - properties: - vercel: - type: object - properties: - installation_id: - type: string - access_token: - type: string - account_id: - type: string - custom_payment_method_id: - type: string - required: - - installation_id - - access_token - - account_id - - type: "null" - description: External processors for the customer send_email_receipts: type: boolean description: Whether to send email receipts to this customer - internal_options: - type: object - properties: - default_group: - type: string - description: The group of products to attach to the customer - disable_defaults: - type: boolean - description: Whether to disable default products expand: type: array items: $ref: "#/components/schemas/CustomerExpand" description: Customer expand options - entity_id: - type: string - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id - id: - anyOf: - - $ref: "#/components/schemas/CustomerId" - - type: "null" - with_autumn_id: - type: boolean - default: false required: - customer_id title: GetOrCreateCustomerParams + examples: + - &a1 + customer_id: cus_123 + name: John Doe + email: john@example.com + example: *a1 responses: "200": description: OK @@ -987,8 +793,9 @@ paths: application/json: schema: $ref: "#/components/schemas/Customer" + example: *a2 parameters: - - &a1 + - &a3 name: x-api-version in: header required: true @@ -1000,22 +807,15 @@ paths: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", + const autumn = new Autumn() + + const result = await autumn.customers.getOrCreate({ + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); - - async function run() { - const result = await autumn.customers.getOrCreate({ - customerId: null, - }); - - console.log(result); - } - - run(); /v1/products: get: operationId: list @@ -1023,7 +823,7 @@ paths: tags: - plans parameters: - - *a1 + - *a3 responses: "200": description: OK @@ -1042,20 +842,11 @@ paths: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", - }); + const autumn = new Autumn() - async function run() { - const result = await autumn.plans.list(); - - console.log(result); - } - - run(); + const result = await autumn.plans.list(); /v1/attach: post: operationId: attach @@ -1068,21 +859,6 @@ paths: schema: type: object properties: - entity_id: - anyOf: - - type: string - - type: "null" - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id options: anyOf: - type: array @@ -1136,76 +912,8 @@ paths: anyOf: - type: string - type: "null" - description: The feature ID of the product item. Should be null for fixed price items. - feature_type: - anyOf: - - enum: - - single_use - - continuous_use - - boolean - - static - - type: "null" - feature: - anyOf: - - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type - - type: "null" + description: The feature ID of the product item. Should be null for fixed price + items. included_usage: anyOf: - anyOf: @@ -1225,7 +933,9 @@ paths: - semi_annual - year - type: "null" - description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a price, it will be billed one-off. + description: The reset or billing interval of the product item. If null, feature + will have no reset date, and if there's a price, it + will be billed one-off. interval_count: anyOf: - type: number @@ -1235,19 +945,22 @@ paths: anyOf: - type: string - type: "null" - description: The feature ID of the entity (like seats) to track sub-balances for. + description: The feature ID of the entity (like seats) to track sub-balances + for. usage_model: anyOf: - enum: - prepaid - pay_per_use - type: "null" - description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. + description: Whether the feature should be prepaid upfront or billed for how + much they use end of billing period. price: anyOf: - type: number - type: "null" - description: The price of the product item. Should be null if tiered pricing is set. + description: The price of the product item. Should be null if tiered pricing is + set. tiers: anyOf: - type: array @@ -1266,7 +979,8 @@ paths: - to - amount - type: "null" - description: Tiered pricing for the product item. Not applicable for fixed price items. + description: Tiered pricing for the product item. Not applicable for fixed price + items. billing_units: anyOf: - type: number @@ -1277,80 +991,6 @@ paths: - type: boolean - type: "null" description: Whether the usage should be reset when the product is enabled. - display: - anyOf: - - type: object - properties: - primary_text: - type: string - secondary_text: - anyOf: - - type: string - - type: "null" - required: - - primary_text - - type: "null" - usage_limit: - anyOf: - - type: number - - type: "null" - config: - anyOf: - - type: object - properties: - on_increase: - anyOf: - - enum: - - bill_immediately - - prorate_immediately - - prorate_next_cycle - - bill_next_cycle - - type: "null" - on_decrease: - anyOf: - - enum: - - prorate - - prorate_immediately - - prorate_next_cycle - - none - - no_prorations - - type: "null" - rollover: - anyOf: - - type: object - properties: - max: - anyOf: - - type: number - - type: "null" - duration: - enum: - - month - - forever - default: month - length: - type: number - required: - - max - - length - - type: "null" - - type: "null" - created_at: - anyOf: - - type: number - - type: "null" - entitlement_id: - anyOf: - - type: string - - type: "null" - price_id: - anyOf: - - type: string - - type: "null" - price_config: - anyOf: - - {} - - type: "null" product_id: type: string invoice: @@ -1391,8 +1031,6 @@ paths: properties: customer_id: type: string - entity_id: - type: string invoice: type: object properties: @@ -1437,27 +1075,18 @@ paths: - customer_id - payment_url parameters: - - *a1 + - *a3 x-codeSamples: - lang: typescript label: Typescript (SDK) source: |- - import { Autumn } from "@useautumn/sdk"; + import { Autumn } from 'autumn-js' - const autumn = new Autumn({ - xApiVersion: "2.1", - secretKey: process.env["AUTUMN_SECRET_KEY"] ?? "", + const autumn = new Autumn() + + const result = await autumn.billing.attach({ + productId: "", }); - - async function run() { - const result = await autumn.billing.attach({ - productId: "", - }); - - console.log(result); - } - - run(); security: - secretKey: [] x-speakeasy-globals: diff --git a/apps/docs/mintlify/components/dynamic-param-field.jsx b/apps/docs/mintlify/components/dynamic-param-field.jsx new file mode 100644 index 000000000..c8ede3bae --- /dev/null +++ b/apps/docs/mintlify/components/dynamic-param-field.jsx @@ -0,0 +1,78 @@ +import { useEffect, useMemo, useState } from "react"; + +/** + * A wrapper around Mintlify's ParamField that dynamically switches + * between snake_case and camelCase based on the selected code language. + * + * - Node.js/TypeScript → camelCase (e.g., customerId) + * - Python/cURL/others → snake_case (e.g., customer_id) + */ +export const DynamicParamField = ({ children, body, path, ...props }) => { + // Inline the toCamelCase function to avoid module scope issues with Mintlify's MDX compiler + const convertToCamelCase = (str) => { + if (typeof str !== "string") return str; + return str.replace(/[_-](\w)/g, (_, c) => c.toUpperCase()); + }; + + const [lang, setLang] = useState(() => { + if (typeof window !== "undefined") { + const stored = localStorage.getItem("code"); + return stored || '"typescript"'; + } + return '"typescript"'; + }); + + useEffect(() => { + // Listen for Mintlify's custom localStorage event + const onMintlifyStorage = (event) => { + const key = event.detail?.key; + if (key === "code") { + setLang(event.detail.value); + } + }; + + // Poll localStorage as a fallback (in case the event doesn't fire) + const pollInterval = setInterval(() => { + const current = localStorage.getItem("code"); + if (current && current !== lang) { + setLang(current); + } + }, 500); + + document.addEventListener("mintlify-localstorage", onMintlifyStorage); + + return () => { + document.removeEventListener("mintlify-localstorage", onMintlifyStorage); + clearInterval(pollInterval); + }; + }, [lang]); + + const resolvedBody = useMemo(() => { + try { + const value = JSON.parse(lang); + // TypeScript uses camelCase, everything else (bash, python) uses snake_case + const useCamelCase = value === "typescript"; + return useCamelCase ? convertToCamelCase(body) : body; + } catch { + return body; + } + }, [body, lang]); + + const resolvedPath = useMemo(() => { + try { + const value = JSON.parse(lang); + // TypeScript uses camelCase, everything else (bash, python) uses snake_case + const useCamelCase = value === "typescript"; + return useCamelCase ? convertToCamelCase(path) : path; + } catch { + return path; + } + }, [path, lang]); + + // Render the ParamField with resolved values + return ( + + {children} + + ); +}; diff --git a/apps/docs/mintlify/components/dynamic-response-example.jsx b/apps/docs/mintlify/components/dynamic-response-example.jsx new file mode 100644 index 000000000..2294cf993 --- /dev/null +++ b/apps/docs/mintlify/components/dynamic-response-example.jsx @@ -0,0 +1,95 @@ +import { useEffect, useMemo, useState } from "react"; + +/** + * A dynamic response example that shows JSON in the sidebar. + * Displays two tabs (TypeScript/Response) and auto-switches based on selected language. + * + * - TypeScript selected → shows camelCase tab + * - Python/cURL selected → shows snake_case tab + */ +export const DynamicResponseExample = ({ json, statusCode = "200" }) => { + // Convert snake_case to camelCase + const toCamelCase = (str) => { + return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); + }; + + // Recursively convert all object keys to camelCase + const convertKeysToCamelCase = (obj) => { + if (Array.isArray(obj)) { + return obj.map((item) => convertKeysToCamelCase(item)); + } + if (obj !== null && typeof obj === "object") { + return Object.keys(obj).reduce((acc, key) => { + const camelKey = toCamelCase(key); + acc[camelKey] = convertKeysToCamelCase(obj[key]); + return acc; + }, {}); + } + return obj; + }; + + const [isTypeScript, setIsTypeScript] = useState(() => { + if (typeof window !== "undefined") { + try { + const lang = localStorage.getItem("code"); + return JSON.parse(lang) === "typescript"; + } catch { + return true; + } + } + return true; + }); + + useEffect(() => { + // Listen for Mintlify's custom localStorage event + const onMintlifyStorage = (event) => { + if (event.detail?.key === "code") { + try { + const value = JSON.parse(event.detail.value); + setIsTypeScript(value === "typescript"); + } catch { + // ignore + } + } + }; + + // Poll localStorage as fallback + const pollInterval = setInterval(() => { + try { + const lang = localStorage.getItem("code"); + const value = JSON.parse(lang); + setIsTypeScript(value === "typescript"); + } catch { + // ignore + } + }, 300); + + document.addEventListener("mintlify-localstorage", onMintlifyStorage); + + return () => { + document.removeEventListener("mintlify-localstorage", onMintlifyStorage); + clearInterval(pollInterval); + }; + }, []); + + const camelCaseJson = useMemo(() => convertKeysToCamelCase(json), [json]); + + const snakeCaseString = JSON.stringify(json, null, 2); + const camelCaseString = JSON.stringify(camelCaseJson, null, 2); + + // Render tabs with CodeGroup-like behavior + // Only one tab is "active" based on the selected language + return ( + + {isTypeScript ? ( + + {camelCaseString} + + ) : ( + + {snakeCaseString} + + )} + + ); +}; diff --git a/apps/docs/mintlify/components/dynamic-response-field.jsx b/apps/docs/mintlify/components/dynamic-response-field.jsx new file mode 100644 index 000000000..03e544bd0 --- /dev/null +++ b/apps/docs/mintlify/components/dynamic-response-field.jsx @@ -0,0 +1,67 @@ +import { useEffect, useMemo, useState } from "react"; + +/** + * A wrapper around Mintlify's ResponseField that dynamically switches + * between snake_case and camelCase based on the selected code language. + * + * - Node.js/TypeScript → camelCase (e.g., customerId) + * - Python/cURL/others → snake_case (e.g., customer_id) + */ +export const DynamicResponseField = ({ children, name, ...props }) => { + // Inline the toCamelCase function to avoid module scope issues with Mintlify's MDX compiler + const convertToCamelCase = (str) => { + if (typeof str !== "string") return str; + return str.replace(/[_-](\w)/g, (_, c) => c.toUpperCase()); + }; + + const [lang, setLang] = useState(() => { + if (typeof window !== "undefined") { + const stored = localStorage.getItem("code"); + return stored || '"typescript"'; + } + return '"typescript"'; + }); + + useEffect(() => { + // Listen for Mintlify's custom localStorage event + const onMintlifyStorage = (event) => { + const key = event.detail?.key; + if (key === "code") { + setLang(event.detail.value); + } + }; + + // Poll localStorage as a fallback (in case the event doesn't fire) + const pollInterval = setInterval(() => { + const current = localStorage.getItem("code"); + if (current && current !== lang) { + setLang(current); + } + }, 500); + + document.addEventListener("mintlify-localstorage", onMintlifyStorage); + + return () => { + document.removeEventListener("mintlify-localstorage", onMintlifyStorage); + clearInterval(pollInterval); + }; + }, [lang]); + + const resolvedName = useMemo(() => { + try { + const value = JSON.parse(lang); + // TypeScript uses camelCase, everything else (bash, python) uses snake_case + const useCamelCase = value === "typescript"; + return useCamelCase ? convertToCamelCase(name) : name; + } catch { + return name; + } + }, [name, lang]); + + // Render the ResponseField with resolved name + return ( + + {children} + + ); +}; diff --git a/apps/docs/mintlify/docs.json b/apps/docs/mintlify/docs.json index d444ff09c..3e707d7ef 100644 --- a/apps/docs/mintlify/docs.json +++ b/apps/docs/mintlify/docs.json @@ -143,7 +143,7 @@ { "group": "Customers", "pages": [ - "api-reference/customers/get-or-create-customer", + "api-reference/customers/getOrCreate", "api-reference/customers/list-customers", "api-reference/customers/update-customer", "api-reference/customers/delete-customer", @@ -229,7 +229,7 @@ "display": "interactive" }, "examples": { - "languages": ["typescript", "bash", "python"] + "languages": ["typescript", "python", "bash"] } }, "background": { diff --git a/apps/docs/mintlify/dynamic-response.js b/apps/docs/mintlify/dynamic-response.js new file mode 100644 index 000000000..f4c668643 --- /dev/null +++ b/apps/docs/mintlify/dynamic-response.js @@ -0,0 +1,139 @@ +/** + * Dynamic Response Example Script + * + * Patches the response example in the sidebar to switch between + * snake_case and camelCase based on the selected code language. + * + * - TypeScript → camelCase (e.g., customerId) + * - Python/cURL → snake_case (e.g., customer_id) + */ + +(() => { + // Convert snake_case to camelCase + const toCamelCase = (str) => + str.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); + + // Convert camelCase to snake_case + const toSnakeCase = (str) => + str.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase(); + + // Store original keys for each span + const originalKeysMap = new WeakMap(); + + // Check if TypeScript is selected + const isTypeScriptSelected = () => { + try { + const lang = localStorage.getItem("code"); + return JSON.parse(lang) === "typescript"; + } catch { + return false; + } + }; + + // Find response code groups (with "200" or "201" tabs) + const findResponseCodeGroups = () => { + const codeGroups = document.querySelectorAll(".code-group"); + const results = []; + + for (const codeGroup of codeGroups) { + const tabs = codeGroup.querySelectorAll('[role="tab"]'); + for (const tab of tabs) { + const text = tab.textContent.trim(); + if (text === "200" || text === "201") { + // Check if it's on the right side (sidebar) + const rect = codeGroup.getBoundingClientRect(); + if (rect.left > window.innerWidth / 2) { + results.push(codeGroup); + } + } + } + } + + return results; + }; + + // Update response examples + const updateResponseExamples = () => { + const useCamelCase = isTypeScriptSelected(); + const codeGroups = findResponseCodeGroups(); + + for (const codeGroup of codeGroups) { + const codeElement = codeGroup.querySelector("code"); + if (!codeElement) continue; + + const spans = codeElement.querySelectorAll("span"); + + for (const span of spans) { + const text = span.textContent; + + // Match JSON keys with optional leading whitespace + const keyMatch = text.match(/^(\s*)"([a-z][a-z0-9]*(?:_[a-z0-9]+)*)"$/); + + if (keyMatch) { + const leadingWhitespace = keyMatch[1]; + const keyName = keyMatch[2]; + + // Only process keys with underscores or camelCase + if (keyName.includes("_") || /[a-z][A-Z]/.test(keyName)) { + // Store original if not already stored + if (!originalKeysMap.has(span)) { + originalKeysMap.set(span, keyName); + } + + const originalKey = originalKeysMap.get(span); + const newKey = useCamelCase + ? toCamelCase(originalKey) + : toSnakeCase(originalKey); + + if (keyName !== newKey) { + span.textContent = `${leadingWhitespace}"${newKey}"`; + } + } + } + } + } + }; + + // Listen for language changes + document.addEventListener("mintlify-localstorage", (event) => { + if (event.detail?.key === "code") { + requestAnimationFrame(updateResponseExamples); + } + }); + + // Poll as fallback + let lastLang = localStorage.getItem("code"); + setInterval(() => { + const currentLang = localStorage.getItem("code"); + if (currentLang !== lastLang) { + lastLang = currentLang; + updateResponseExamples(); + } + }, 200); + + // Run IMMEDIATELY - no waiting + updateResponseExamples(); + + // Aggressive early execution + const init = () => { + updateResponseExamples(); + setTimeout(updateResponseExamples, 5); + setTimeout(updateResponseExamples, 15); + setTimeout(updateResponseExamples, 30); + setTimeout(updateResponseExamples, 50); + setTimeout(updateResponseExamples, 80); + }; + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } + + // Watch for DOM changes - no debounce, run immediately + const observer = new MutationObserver(() => { + updateResponseExamples(); + }); + + observer.observe(document.body, { childList: true, subtree: true }); +})(); diff --git a/apps/docs/mintlify/language-tabs.css b/apps/docs/mintlify/language-tabs.css new file mode 100644 index 000000000..fbe581e55 --- /dev/null +++ b/apps/docs/mintlify/language-tabs.css @@ -0,0 +1,20 @@ +/** + * Transform the language dropdown into horizontal tabs + * This targets the language selector in the API playground sidebar + */ + +/* Hide the dropdown button/trigger */ +[data-testid="code-sample-language-select"], +.code-sample-language-select, +[aria-haspopup="listbox"] { + /* We'll need to identify the exact selector - leaving as placeholder */ +} + +/* + * Note: Mintlify's language selector structure may vary. + * Use browser DevTools to inspect the exact element structure. + * + * Common approaches: + * 1. Hide dropdown, show custom tabs via JS + * 2. Use CSS to restyle the dropdown menu as always-visible tabs + */ diff --git a/apps/docs/mintlify/style.css b/apps/docs/mintlify/style.css index cd1d0e4f7..31ed27eb3 100644 --- a/apps/docs/mintlify/style.css +++ b/apps/docs/mintlify/style.css @@ -10,3 +10,9 @@ border: 1px solid #661ecf; } + +/* Hide auto-generated OpenAPI sections (Authorizations, Headers, Body, Response) */ +/* These sections are wrapped in div.api-section with h4 headings */ +.prose > .api-section { + display: none !important; +} diff --git a/apps/docs/package.json b/apps/docs/package.json index e48e41371..ef5056625 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "pull": "bun scripts/pull.ts", - "dev": "cd mintlify && mint dev", + "dev": "cd mintlify && mint dev -p 3002", "build": "cd mintlify && mint build", "start": "cd mintlify && mint dev" }, diff --git a/bun.lock b/bun.lock index 0d60bf823..6aa19dfb7 100644 --- a/bun.lock +++ b/bun.lock @@ -157,7 +157,7 @@ }, "packages/sdk": { "name": "@useautumn/sdk", - "version": "0.7.20", + "version": "0.7.42", "dependencies": { "zod": "^3.25.65 || ^4.0.0", }, diff --git a/packages/sdk/.speakeasy/code-samples.overlay.yaml b/packages/sdk/.speakeasy/code-samples.overlay.yaml index f58f4b9a8..66dc93edd 100644 --- a/packages/sdk/.speakeasy/code-samples.overlay.yaml +++ b/packages/sdk/.speakeasy/code-samples.overlay.yaml @@ -40,7 +40,9 @@ actions: async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); diff --git a/packages/sdk/.speakeasy/gen.lock b/packages/sdk/.speakeasy/gen.lock index b598869a0..e83f12dd8 100644 --- a/packages/sdk/.speakeasy/gen.lock +++ b/packages/sdk/.speakeasy/gen.lock @@ -1,16 +1,16 @@ lockVersion: 2.0.0 id: 7b300647-cd76-49e9-bf77-7d1bf5446d66 management: - docChecksum: c2dc7dba08764fe54782d28e82bebe2b + docChecksum: b65ff198c2a9d322f115152bb4da709a docVersion: 2.1.0 speakeasyVersion: 1.718.0 generationVersion: 2.824.1 - releaseVersion: 0.7.20 - configChecksum: 0b4fb6dcfb9d39ab7b3d33663bd406b2 + releaseVersion: 0.7.42 + configChecksum: 23cd3cf4d3605d0e5a292425ebaf5ba9 persistentEdits: - generation_id: a47f16dc-6445-4109-b975-2d3d49434c47 - pristine_commit_hash: 11ad79633a20a21e4ef703ce48922a924c341aa5 - pristine_tree_hash: 1e6fc7ba17b211330e97103160441cbef1c2b0dc + generation_id: 0f7b658f-ebaa-4605-a712-06d457b9e799 + pristine_commit_hash: dea2c6e16c8cb9dc1ab4284cb2b3d5b43b270f4c + pristine_tree_hash: 11355c53ac460b9f5da2193b26776eea4116983b features: typescript: additionalDependencies: 0.1.0 @@ -55,48 +55,24 @@ trackedFiles: pristine_git_object: cf98a6bf092538eb10ff0edc915102682ce9a6e6 FUNCTIONS.md: id: 21b9df02aaeb - last_write_checksum: sha1:3c9d7c1644476bc2e48b361e67f885ef6708e614 - pristine_git_object: 366dd158e15755fa8c2c2293526157baf74a2eb1 + last_write_checksum: sha1:3102381f2f0239e6cd820f6048dc9df14e57ad2d + pristine_git_object: 997ec44c4ee5408258b58112c217e8366d69c2b3 RUNTIMES.md: id: 620c490847b6 last_write_checksum: sha1:e45b854f02c357cbcfdb8c3663000e8339e16505 pristine_git_object: 27731c3b5ace66bedc454ed5acbe15075aacd3dc USAGE.md: id: 3aed33ce6e6f - last_write_checksum: sha1:10f6478b29d718ad6358cc390de6a12db5bd056b - pristine_git_object: 1f64b54ba78036e3b0bfec0d98dfefb94d9e0fee + last_write_checksum: sha1:fee4559ff519f06ab91e5e9656ae606256dc386c + pristine_git_object: b1d99bf9ec8e5f90834cf4649c5498b453dd961b docs/lib/utils/retryconfig.md: id: 0ce9707cb848 last_write_checksum: sha1:bc4454e196fcd219f5a78da690375a884f5ed07b pristine_git_object: 08f95f4552349360b2c0b01802aa71ec3a55d2c2 - docs/models/attach-credit-schema.md: - id: e37ce7b7ba9d - last_write_checksum: sha1:1a934ee70a7789cc65ba68215a732cd88fe26d36 - pristine_git_object: 20689c736f1c180f4f520bd4c93883d867eedbaa - docs/models/attach-display.md: - id: c25e4feece03 - last_write_checksum: sha1:8a68328a53756aaa6ab37ae0f6a2beb98ac956ea - pristine_git_object: c58afd1fcdc25fdfd18334e4d59fdc152bfe00a7 - docs/models/attach-entity-data.md: - id: c0443720a588 - last_write_checksum: sha1:1fc239d8107d0c393615bdebd9579d2b24b92cbe - pristine_git_object: bbbd9b61970ff04dfc9a588af42763ecbd8584b3 - docs/models/attach-feature-display.md: - id: 47a5e489165c - last_write_checksum: sha1:55736a8750008681ad6069f32c8d73244bc49cc2 - pristine_git_object: 34af62fc13848961b5e7cc808cc0acb6bcdfaf6d - docs/models/attach-feature-type.md: - id: 5e3b989a646b - last_write_checksum: sha1:88846b672de0e2386f0f5ffa436a6412ec87096d - pristine_git_object: 47b42c605eb5a049726d57bcf52f74873529eb83 - docs/models/attach-feature.md: - id: 18a0c43374da - last_write_checksum: sha1:f9b22b2ddaa97b7b2ae038e484a85e9633f789f4 - pristine_git_object: 559ceb6cbfe519bdc01e043a324d62eb20481ea2 docs/models/attach-free-trial.md: id: 6572f2ad0a92 - last_write_checksum: sha1:04a0d6e03bda7b7ca9c21ac2146210206456ff8e - pristine_git_object: 1a2397bd25f0c906ac860838f8b2409e2a6bd47a + last_write_checksum: sha1:d6194625284ac6f307cd38b0603daa3426b660f9 + pristine_git_object: 7b56ce6ed66527b699204d6d8f5e3e1e5aaf9b22 docs/models/attach-globals.md: id: 3f5659c4527e last_write_checksum: sha1:5ecc4152cef4f786f4c1bb41b2b4ca42d51c5bdd @@ -111,28 +87,16 @@ trackedFiles: pristine_git_object: f19f81978da4df350b9b9f6f85f700c54b1e290c docs/models/attach-item.md: id: ea7481c84d0f - last_write_checksum: sha1:6c25ac4c881f1ad11f93c0fc45e3a4f898608c95 - pristine_git_object: 7e639c9899521bc25e237a8bc7e4632a8358a42d - docs/models/attach-on-decrease.md: - id: 730009f79373 - last_write_checksum: sha1:afef078ee75a7f0c01eb048321e1b770ed4b38ad - pristine_git_object: f1b38ac1aba245801c6accef2d5b3b8d60d7752d - docs/models/attach-on-increase.md: - id: 5941c36420ab - last_write_checksum: sha1:db94107b8ed6d6316d55a63f9bc412731754e245 - pristine_git_object: f3150762704ffa777462088f7066f0bd3b286c8c + last_write_checksum: sha1:70d77b571c83d58810738b7c5969df1b8721969f + pristine_git_object: 5dab41e71b2c203495d96ce060b7e0100f26167a docs/models/attach-request.md: id: 9e2ed03c1844 - last_write_checksum: sha1:a8166f3e40d630c7d6aaaf2aee7109a40483f436 - pristine_git_object: adce3a547dafe10caf62c9b6a5b45c2f72740436 + last_write_checksum: sha1:ac9e609f3ab72a889cc51f373f3d1b76fde42853 + pristine_git_object: 50a550a22b82814cff9b78f60eff43623363060b docs/models/attach-response.md: id: 7a5806587fd5 - last_write_checksum: sha1:a7b8266aa2eeff06be640e3122290aacc690db37 - pristine_git_object: 2c48f0863a83a7365543db4cdeb40f7722111bb4 - docs/models/attach-rollover.md: - id: d84522e07be9 - last_write_checksum: sha1:fc4e23599d9f86bda0424d413a6060bc1f3c3bd5 - pristine_git_object: 8eb5c77fbb245841ddf291ad9bc145517eb83171 + last_write_checksum: sha1:7849b490fb4bc8b5556b7133465ce026d13581e7 + pristine_git_object: b3eec4c3fbf69785c5666a08354bce0040bb9693 docs/models/attach-to.md: id: 39243c9d9b34 last_write_checksum: sha1:b3cdc5c90abed4d59f033c545019f56a3d2e2ce1 @@ -141,42 +105,26 @@ trackedFiles: id: d6b7b8d3105d last_write_checksum: sha1:3a9b2390259d4fcd61c66de3ced8d1d50c9f2d00 pristine_git_object: 5316b2b61c30f9a86d13d723c08c112c498a3b0b - docs/models/balances-type.md: - id: 062f249673a5 - last_write_checksum: sha1:c9540f9c79933112766da6927ad51817f0240565 - pristine_git_object: 1c48ab0c7bfc6f7e9958416816775d1fcc990374 docs/models/balances.md: id: 2f042cf3d0aa - last_write_checksum: sha1:9a9c2a84d066247446703b35af6efe14f5df1cb3 - pristine_git_object: fd59d3018e8e84c9fcdf744a438072eff75638b6 + last_write_checksum: sha1:b4b98e12527cbc39740c582a568427d715b85d03 + pristine_git_object: 3cecc0799bb1f00476c41b9a5c99c4e79b5ceb5e docs/models/billing-behavior.md: id: 59f3b5602fbf last_write_checksum: sha1:6ed351e2827574db97767e81b035f3ec225c01ab pristine_git_object: 4633622403fdd0438509ff950c13f857121fc588 docs/models/breakdown.md: id: 786823ab8ff0 - last_write_checksum: sha1:6992c68ed199fd46e06c6e7d26d412704f9164f8 - pristine_git_object: f6bdbd480cbf0f5ae1083f2c9cd3a9cd0fb80e9f + last_write_checksum: sha1:683ea06e2215c28c720f9851b4368098e0d06807 + pristine_git_object: be7b8808f650d49888af3e88b2d8ce34a335c7df docs/models/code.md: id: 2fcb3964c9c0 last_write_checksum: sha1:94a4beade541c66d62dec0d861813fe1ac19dd69 pristine_git_object: 595d8bd35314feacf5137f361e0eefb8889072ad - docs/models/config.md: - id: bef254bf823c - last_write_checksum: sha1:921ea7390c3e59cde4183cddca10e8801f3e74a8 - pristine_git_object: dc46421150487f7c036fc0abc4b87d69f6747c60 docs/models/customer-billing-method.md: id: 06ff2abe6f74 last_write_checksum: sha1:1a9942bc1176ec5185bfe33171162879bf79f405 pristine_git_object: 12c6c12ff6d8e5fc4dc9a98e0ab1dec6ea7efbb7 - docs/models/customer-credit-schema.md: - id: fa77c00fcafd - last_write_checksum: sha1:adf6bb711b3cfd99d84da8977c3005cb3baa24e1 - pristine_git_object: de538f3a711b297dcba238dd7db908ee881dae7f - docs/models/customer-display.md: - id: 58fadfb6f84d - last_write_checksum: sha1:02389782a6f3873571e7a8866eed09a5cc6098f5 - pristine_git_object: d86e56fea265fbd888ae6d62a570f54aa883be0a docs/models/customer-duration-type.md: id: cbfbb0769db5 last_write_checksum: sha1:5cc7fc548fc238c2c4db1517e1192dc036a74139 @@ -187,16 +135,12 @@ trackedFiles: pristine_git_object: ca0c3e1ce1ea2f60e4cf2206bb9b21e18b9b5997 docs/models/customer-env.md: id: f063b206890c - last_write_checksum: sha1:dd6afc952f52e7712a47578ebeb934f351c18544 - pristine_git_object: a94e4434643f2acf3fffc2f5ed964ed5ac620493 + last_write_checksum: sha1:cc47133530e606c040759b3f18b48dad7b78cdae + pristine_git_object: d210083c532e8c527f089ea2abc2c227e2b7d8e2 docs/models/customer-expand.md: id: 1730127f931b last_write_checksum: sha1:1d88fca3d4cc3cdcb78a1a46a91039b9d2f323c0 pristine_git_object: fd2e47dfff6dba01fbad342c2de102c69d44643f - docs/models/customer-feature.md: - id: d90579a4e5c4 - last_write_checksum: sha1:b09eb0f015b76749b4d5c12016f1665a2b5c60a6 - pristine_git_object: 3cf02ec91d3338efff44cc9cc98c25645c0cd805 docs/models/customer-interval-enum.md: id: b224f2bcbf4b last_write_checksum: sha1:ef6926633f780442c7a7bce1a12c230465f3d6ad @@ -223,44 +167,36 @@ trackedFiles: pristine_git_object: adb4e6a216daf5fe4f5e1566821240b1406007e1 docs/models/customer.md: id: 42ac97d31359 - last_write_checksum: sha1:90af98cc54ce0fd322f539c2498ae7907c3a7d91 - pristine_git_object: 0839a1cd2391cb97fd95210ccbb4adc5b9c6594b + last_write_checksum: sha1:177f9e80f86abcbf82d34ac230f78e26eb8afe05 + pristine_git_object: 3df262773e09df832a517056728d2add293693e2 docs/models/discount.md: id: 003b28f6c8a6 - last_write_checksum: sha1:514d11ebc37ebdb692a8137be44b60d35549cfb7 - pristine_git_object: 1cd19465e5e2ccba85d1117383cbb3ee6cae7763 + last_write_checksum: sha1:fe89c4a5f07986dc1fd721b026218e7c96c2c63c + pristine_git_object: ea251e97cc69c9984c3c53295a03285a72541476 + docs/models/duration.md: + id: e63d42c932a8 + last_write_checksum: sha1:3ebfb271ff5182a27635748d8c7e3d9594fef510 + pristine_git_object: e70c1be447f86b333b4cc601f7b8859ad5da92a8 docs/models/entity-env.md: id: 817aa096ab27 last_write_checksum: sha1:e57c22c174cf8744c9fbc793a21c87eab86ba81a pristine_git_object: ea4e92658978c0c7494a04f24e0f2e9276baaaac docs/models/entity.md: id: 903c73579a5c - last_write_checksum: sha1:3d90d8923798be834d241db6e33846dbbac2cfdf - pristine_git_object: 2ea16cf6f98cf4b2085ace4dae3ff34cbbe45f9f + last_write_checksum: sha1:d45c1e98846cb22fa28b885b66bf4d341947673f + pristine_git_object: 5445e914a693e4bfa626d820fdba75a41b7b002d docs/models/expiry-duration-type.md: id: 3a927f275515 last_write_checksum: sha1:7059b0a8efd82cdb43c176b868824f5e26d8eb0c pristine_git_object: 38df300d40088ea211de7e229c77987ee9d3131a - docs/models/feature-type.md: - id: c6368d6178e0 - last_write_checksum: sha1:766b96f4d82e9f605cd116463185693ce9b1e142 - pristine_git_object: 198d92062ec33064dddeb98c8a5a8629f2b74d67 - docs/models/free-trial-duration.md: - id: f12ff48f6deb - last_write_checksum: sha1:6bdcbe59c8809621662ed02862470a853f1381bf - pristine_git_object: 5e95863eddcf6a24ba96e04bc6eee060a73a0b9e docs/models/free-trial.md: id: 7d40737b76e3 last_write_checksum: sha1:ab8208a5a5ab8963a8c8fa7f93dfdd9cd068f6c4 pristine_git_object: 4600b15c1d50b17c86bfde5df59541dd36c152e1 docs/models/get-or-create-customer-params.md: id: 496662dd4c0d - last_write_checksum: sha1:130b79ab63bb25eaa152941e3fa2107ace38134d - pristine_git_object: 58995fc8b9e0b6385640b5ac7f67554c55b7151c - docs/models/get-or-create-entity-data.md: - id: 7ea7a1bc773a - last_write_checksum: sha1:b973aa8ec00ba32917245e403cccd2354bd30c73 - pristine_git_object: c7205896399f1ece85a220bddd669506f38b4ac4 + last_write_checksum: sha1:5bac80cea5c986ca03ff3d732070e618c39663f9 + pristine_git_object: 570053b312dc0a87a05f1b71f815fae814697a7f docs/models/get-or-create-globals.md: id: 8474dc7dbc80 last_write_checksum: sha1:7a65f90b8e52bfdd196c95737a4c200cf8146e48 @@ -269,26 +205,22 @@ trackedFiles: id: f27abcdfdd7d last_write_checksum: sha1:ca0a41260fa62322a9525f4267ac0ec6d93ae6d8 pristine_git_object: 5fe6a61067cd319d6cd0d1e1e7f1d165c0d4579d - docs/models/internal-options.md: - id: 46603a381a4a - last_write_checksum: sha1:9a8d19e1849b4817955d61774bf6fced9fc3b76c - pristine_git_object: b3d4895ebc3dd7509c5f05f319273039c4711fb0 docs/models/interval.md: id: 11a74d2c19c0 last_write_checksum: sha1:1d612bf1b73e7b6f54c8086bf13964ae62496463 pristine_git_object: 6bd470a06b95cb33d5f2b2f4f4a609dbbae9a544 docs/models/invoice.md: id: 18e2034f11ad - last_write_checksum: sha1:321079a7eab955ee497e7879908a4c2e9ee446b2 - pristine_git_object: 39f3d1c3ab247ec4559923d5191fff971b8e5572 + last_write_checksum: sha1:72f2f97f724891e9af6123a5c2826181328b494f + pristine_git_object: f7338b19bded9bd82efc9687fafc03c2a02bf371 docs/models/item-price.md: id: ec7f6a9f6ac5 last_write_checksum: sha1:9d5ea14c2b3845ed4489ac33fbdfa391d1bc6def pristine_git_object: 0d853a9a3abbd1aede8b939c43f23adab900f6b7 docs/models/item.md: id: 40dd7473ab87 - last_write_checksum: sha1:6a0d28d078e7e5180d619c66f9e8aeec3322919a - pristine_git_object: b2b784472c604e53e6f303c249e09ba8aaeee45a + last_write_checksum: sha1:81e925dbb597518a2a3975856f56ee346e73a11f + pristine_git_object: 8f8d120e33c446a1134415a84ac24f5641a50885 docs/models/list-globals.md: id: 58d9bcee8a08 last_write_checksum: sha1:0c51ff1aa46dce6a17238f78ae70a44b721139a3 @@ -317,10 +249,6 @@ trackedFiles: id: 4789ae90ae01 last_write_checksum: sha1:8b53127c48cd1e81a29d62093ae96a52359b268a pristine_git_object: 930e05fe377d4ab12fd2b0245af950d9fd637967 - docs/models/plan-credit-schema.md: - id: 4a323c1dbf0a - last_write_checksum: sha1:167acec310caca3e8e3b1cd5461c5453994f09c9 - pristine_git_object: 9dfd58042a96b6de19c6f5f3a21319e1806a35a0 docs/models/plan-duration-type.md: id: 522f79a4e1c8 last_write_checksum: sha1:6265d10215e91bb4846f1f7648293cf04530d3d2 @@ -329,22 +257,10 @@ trackedFiles: id: 2684553fa0b2 last_write_checksum: sha1:43ecc2f0ae7ad2dd6acdbf3ea9a5c779855ede8a pristine_git_object: 73febb8eb90f0795e0bbcf16621698de452a1f41 - docs/models/plan-feature-display.md: - id: 4a23e75025f8 - last_write_checksum: sha1:bf383e336435e84f0c51cbf12ad34db39fd5e8cd - pristine_git_object: 659e383eacdd48be82e3caa9beeddec253f70168 - docs/models/plan-feature.md: - id: 1f1e65046cf0 - last_write_checksum: sha1:9074682f8d32da2094c50b0da20a9d7b38ef1fdc - pristine_git_object: 1fdccbb593aac6e1317b73dc7fc16f562ca7ac1f - docs/models/plan-item-display.md: - id: 1004f58a3986 - last_write_checksum: sha1:922a8816cd34fbb741b7ec1913d173cdf3d57894 - pristine_git_object: decdbe96b1f83815156d96e1212ffbe7228263f6 docs/models/plan-price.md: id: f24c0778a8d1 - last_write_checksum: sha1:f0ad29bd2ec5a67f789192a2a417dd03ec213d93 - pristine_git_object: 3281c16938de8837e0285cd2d93f989953c5e305 + last_write_checksum: sha1:507311eb39a5936fd9bc44830d86ec0e5bd8dd22 + pristine_git_object: bce113caf172ed0bddd6f24b0cd6dd6779b490b8 docs/models/plan-reset-interval.md: id: 3ae21ed47961 last_write_checksum: sha1:957ef7145ffd6a231785068b66c82109dade812e @@ -369,18 +285,10 @@ trackedFiles: id: 265b5d85de02 last_write_checksum: sha1:73ba2dc4aa70a0e8dd181c625d49e195512a5aa8 pristine_git_object: 7a48160543abf02c3620bd86ccb7150bc32dad8f - docs/models/plan-type.md: - id: fcf04293a720 - last_write_checksum: sha1:8a55b776c10325c521c94693c2301c3d35865204 - pristine_git_object: e573a1e61915a219fc68d1e31dd55c795dda4253 docs/models/plan.md: id: 900c4149ef4b - last_write_checksum: sha1:08f56cb8cac6d89aba2436975994c1648d8d286d - pristine_git_object: c02b9a57fbf832794d06b60296903c7304bddb55 - docs/models/price-display.md: - id: e7cc8364bc4b - last_write_checksum: sha1:f7d122e7b7776cdcffbc40fd2ced81a215d89c23 - pristine_git_object: 9fd5718215ab2855e209fdd606611f33fbf42562 + last_write_checksum: sha1:429d233584eef116d3b165d6c09a050c1f9fc20a + pristine_git_object: 8b12eea5ba974880103edaa1a30a498ed3191124 docs/models/price-interval.md: id: 098d30620284 last_write_checksum: sha1:2f1acca2ad16f4709fb7cb72a869505a18826bbc @@ -389,10 +297,6 @@ trackedFiles: id: 56e3a7187c31 last_write_checksum: sha1:547a74f28866d9ad6218a3237f84946702583323 pristine_git_object: 9c3129cdde3ae9435727cd29013bdb747d8e0b32 - docs/models/processors.md: - id: 58a19fb5be82 - last_write_checksum: sha1:ebfabf19e886b2180ea0fe67f9ed8831d4155f5f - pristine_git_object: 7d7af7b029aa6abc8ab80dad87044ed02670e8a0 docs/models/proration.md: id: ac1d089c0fd1 last_write_checksum: sha1:a0763bf3863245e1ea7004d99849431c154e9ee6 @@ -407,28 +311,20 @@ trackedFiles: pristine_git_object: 4f29bd931311fec97a473b5bf61b12edcb7da7b9 docs/models/referral-customer.md: id: d9629d974163 - last_write_checksum: sha1:e4dab25dd04e413f338e813241694e88cb29c09f - pristine_git_object: 9537eddc4601bf6752271bc008cf8d9c93637781 + last_write_checksum: sha1:d12745723bb0c0cf3cbdfad581ca4dabf9323685 + pristine_git_object: e4978f3af0c093684838ec97443ae4bfb668ad3e docs/models/referral.md: id: b58def2d8bbe - last_write_checksum: sha1:6147d00b05240ea19ab4a012e37012501462790e - pristine_git_object: 6133ec7c2af5271b41ce09dddfb0eb8cbeb14418 + last_write_checksum: sha1:4a205e661d3b742293132c8151388e72df5069b0 + pristine_git_object: 50e78acb13c4e157062623894c2e24fc497872c0 docs/models/required-action.md: id: d4ddcbc1c128 last_write_checksum: sha1:c8f6235625f02d16392e0bbe5a671a2e534532b1 pristine_git_object: a3ae9b548a71e115f7b0c1924d256b9d7ce35553 - docs/models/rewards-type.md: - id: c48adeacd4fc - last_write_checksum: sha1:fc8c460d22c515495d54385f2b0ea1f045605e26 - pristine_git_object: ca2e4f7e35d62a3bfc3658e8c3e20dbdc6e0ed70 docs/models/rewards.md: id: 4551c882db3e - last_write_checksum: sha1:400f48d09c30265fc4650ca42db90109dfdda599 - pristine_git_object: 08b89a9cc150d2d174408e0ccb7d2eea9b8e4014 - docs/models/rollover-duration.md: - id: 2d83c1287827 - last_write_checksum: sha1:d985888074faf41e8863b9396948c5e343990b0c - pristine_git_object: 6cf5cb14756b709ae6ddd12d4c013f435ea1f0ac + last_write_checksum: sha1:7238c7de53b3e40b56d4f7207f84b5813069fc7c + pristine_git_object: dd7ce5d168ac8811cb85dc3e4d61f917ef4f0dd3 docs/models/scenario.md: id: e3aad8ab5efa last_write_checksum: sha1:5d6f7c24e821bf73b9ea5f4915448acc27c0f84f @@ -453,22 +349,22 @@ trackedFiles: id: 983b78eb51b7 last_write_checksum: sha1:0fdc1753311eb276ea3d69f275f9bafaf196e538 pristine_git_object: 72df6cb602ecac3658f8cbb19ea2c460995b7a4a + docs/models/type.md: + id: 98c32f09b2c8 + last_write_checksum: sha1:4cd3d065f419718c7d6883a133111999832246cc + pristine_git_object: 6f4d6d7fdd81d3ab6e3a41fc239af15d811f4bfe docs/models/usage-model.md: id: 32a269601e79 last_write_checksum: sha1:e5426aec062e39992d0a277844320dcce769247e pristine_git_object: 4e7db15000553c421e46aad834f78ce740a8bb3b - docs/models/vercel.md: - id: 634d8fed39b3 - last_write_checksum: sha1:ec591bc9a021f2d9242d75a1ec07b6a437afc134 - pristine_git_object: 73b36b5f50170166e92cfa6f9301fc2fd4b1197a docs/sdks/billing/README.md: id: dc915331dd9d last_write_checksum: sha1:9e15c3bc90aedc98908163d5c54f4e565376297e pristine_git_object: 6736de1838264c53e45c3ecc0171a5d59b7f2ca6 docs/sdks/customers/README.md: id: 9332759cffc2 - last_write_checksum: sha1:975abb1d66875214e3dc3bb746eaabae37ffda75 - pristine_git_object: a0b2f21dc3fc383d7ea05c40c0e8152b8dd134bf + last_write_checksum: sha1:63e6af1b2c380806e67a371a1cf8a1adca199de0 + pristine_git_object: f1b8887234d1e057ca7b410846b03f918dd289b9 docs/sdks/plans/README.md: id: 2d8c741fff57 last_write_checksum: sha1:3611895f9b87e480540dbac3c793f7305874949a @@ -487,20 +383,20 @@ trackedFiles: pristine_git_object: 0928c2ed5c0c739a6fb22e31cdaf11d6bdec9dae examples/customersGetOrCreate.example.ts: id: cb3cc2b938f4 - last_write_checksum: sha1:63cbb196db201a734ef0adda02a1b6830a353683 - pristine_git_object: dc5cc1835c1c0cd260d344b07fae899163843c7f + last_write_checksum: sha1:c519055c000dbbdca007d9e17d6c33a760c26b8d + pristine_git_object: b6af2731f32a8033a302dfc9681a50d2be6933ef examples/package.json: id: c1d7b0ec8e7e last_write_checksum: sha1:22cf1a48e1d9bc8ffc9e65280aeaa5600b54f659 pristine_git_object: 900d545ed58929951e2208e1bec791cb264429a4 jsr.json: id: 7f6ab7767282 - last_write_checksum: sha1:2e89abed613d4deac741401a416279b68cfa9e72 - pristine_git_object: 93b86e0cdade6cd1d8a890fc839d4b485097a5fb + last_write_checksum: sha1:2ce25e32bab42a880fc6498360a871a43357888f + pristine_git_object: 684984ebe5493a297d54faff8714d77554ba7b06 package.json: id: 7030d0b2f71b - last_write_checksum: sha1:0352148b93072588870244e5f8189426040f3582 - pristine_git_object: 9ef6629935a084177973f29c3964fcf927dc2efb + last_write_checksum: sha1:91b53018ad823a78b85fce80d957c92d08b5f77b + pristine_git_object: b7e45b2d9bd335948cb06bec21f9929055be19e6 src/core.ts: id: f431fdbcd144 last_write_checksum: sha1:f8f24a3ca09c1efb285d7a75ad3697d0128f47e2 @@ -539,8 +435,8 @@ trackedFiles: pristine_git_object: 44be0eae8246521b230e8e711a88eff738fc015d src/lib/config.ts: id: 320761608fb3 - last_write_checksum: sha1:027a62f4a5a0c604e17486a65b11de580239e35d - pristine_git_object: 138841a530619f3d549f4bb45d7ea82bbd45eae4 + last_write_checksum: sha1:e3b723c26583ed242be8fad113ab078fe76c7f5b + pristine_git_object: 640df00eb1c9da144695c202389f4660b2bf0a03 src/lib/dlv.ts: id: b1988214835a last_write_checksum: sha1:1dd3e3fbb4550c4bf31f5ef997faff355d6f3250 @@ -599,8 +495,8 @@ trackedFiles: pristine_git_object: f3a8de6c021de59c991707946cd294596cae954d src/models/attach-op.ts: id: 83ed65c26ab4 - last_write_checksum: sha1:fa1dfadde0b9a6c2ed7415b5a304d3764e7c742d - pristine_git_object: f6b11ac71ed243aa1c7b53eaf042394dcc2c939a + last_write_checksum: sha1:bcb938761d3fde5cdb99972f5d3a1e217ae04064 + pristine_git_object: c21e0da461bc1693209f241aa7f0583d46befa5e src/models/autumn-default-error.ts: id: 2528aa7886eb last_write_checksum: sha1:4cce18f91be3262ada7d11dcd6326544e2341b58 @@ -615,12 +511,12 @@ trackedFiles: pristine_git_object: b6a303e11f4d5964b94379a470104d00ff8fb5cc src/models/customer.ts: id: 20be78c552a4 - last_write_checksum: sha1:b20d0e4e9c9a5b384297a437e1b806587b124672 - pristine_git_object: 6edbd6a499807514d6c17d7ffd2a813a56406231 + last_write_checksum: sha1:1e62b5e3dc777ebecac4909ab72ab93e4576b380 + pristine_git_object: 036a131058981bf1e54dc3d0f5b005fb710cec61 src/models/get-or-create-op.ts: id: c9bf055f57c4 - last_write_checksum: sha1:98f4bb2204a75a4971260c1989e13ab922b06b7c - pristine_git_object: 7682293daf9374ca0b5b8ddcb658a3e0b191a7cc + last_write_checksum: sha1:40fa9030712cc39e5cb6d847546282c93da9866a + pristine_git_object: 6adb75311f5d00821820a877a4cca8ce0cffce7a src/models/http-client-errors.ts: id: 5f17dcf0d62b last_write_checksum: sha1:994ced121c54fecd0af038ccfb7855fbfd3868ec @@ -635,8 +531,8 @@ trackedFiles: pristine_git_object: 43d0cd93187b7cead79aa26cfd1e2e52d29f981b src/models/plan.ts: id: 9e9698a64fe7 - last_write_checksum: sha1:16948e44711f31e314cc6954e123e78ef5b2d332 - pristine_git_object: e2c1491b90c9c4dd678b1d0b2f912a9633e4001d + last_write_checksum: sha1:543249fe6318abf6a24e873514f989f42f7c6ac2 + pristine_git_object: 1e7d7434b24cf1d9a01126d078fbcedb2107f4c0 src/models/response-validation-error.ts: id: 7ace3beff92b last_write_checksum: sha1:2788a46874d1d2b88a1fe8352142516f2e5c9ded @@ -1023,10 +919,10 @@ examples: header: x-api-version: "2.1" requestBody: - application/json: {"customer_id": null, "with_autumn_id": false} + application/json: {"customer_id": "cus_123", "name": "John Doe", "email": "john@example.com"} responses: "200": - application/json: {"id": null, "name": "", "email": "Catalina_Upton93@gmail.com", "created_at": 9912.5, "fingerprint": "", "stripe_id": "", "env": "live", "metadata": {}, "send_email_receipts": false, "subscriptions": [], "purchases": [{"plan_id": "", "expires_at": 9063.34, "started_at": 7932.64, "quantity": 6363.06}], "balances": {"key": {"feature_id": "", "granted": 4916.32, "remaining": 316.12, "usage": 4086.82, "unlimited": false, "overage_allowed": true, "max_purchase": 7668.31, "next_reset_at": 1196.51}}} + application/json: {"name": "John Doe", "email": "john@example.com", "fingerprint": "1234567890", "stripe_id": "cus_123", "env": "sandbox", "metadata": {}, "send_email_receipts": false, "subscriptions": [{"plan_id": "plan_123", "auto_enable": true, "add_on": false, "status": "active", "past_due": false, "canceled_at": 1668.32, "expires_at": 9089.12, "trial_ends_at": 9379.96, "started_at": 2917.49, "current_period_start": 8238.87, "current_period_end": 5653, "quantity": 1}], "purchases": [], "balances": {"balance_1": {"feature_id": "", "granted": 124.65, "remaining": 8304.41, "usage": 3422.44, "unlimited": false, "overage_allowed": false, "max_purchase": 7932.64, "next_reset_at": 7580.04}}} list: speakeasy-default-list: parameters: @@ -1034,5 +930,5 @@ examples: x-api-version: "2.1" responses: "200": - application/json: {"list": [{"id": "", "name": "", "description": "distant recompense trick", "group": "", "version": 9615.63, "add_on": true, "auto_enable": false, "price": {"amount": 2384.12, "interval": "week"}, "items": [{"feature_id": "", "included": 4974.83, "unlimited": false, "reset": {"interval": "day"}, "price": {"interval": "month", "billing_units": 5281.09, "billing_method": "prepaid", "max_purchase": 8873.17}}], "created_at": 8066.8, "env": "live", "archived": true, "base_variant_id": ""}]} + application/json: {"list": [{"name": "", "description": "distant recompense trick", "group": "", "version": 9615.63, "add_on": true, "auto_enable": false, "price": {"amount": 2384.12, "interval": "week"}, "items": [{"feature_id": "", "included": 4974.83, "unlimited": false, "reset": {"interval": "day"}, "price": {"interval": "month", "billing_units": 5281.09, "billing_method": "prepaid", "max_purchase": 8873.17}}], "env": "live", "archived": true, "base_variant_id": ""}]} examplesVersion: 1.0.2 diff --git a/packages/sdk/.speakeasy/gen.yaml b/packages/sdk/.speakeasy/gen.yaml index b34bcba3f..89d2b1864 100644 --- a/packages/sdk/.speakeasy/gen.yaml +++ b/packages/sdk/.speakeasy/gen.yaml @@ -33,7 +33,7 @@ generation: generateNewTests: true skipResponseBodyAssertions: false typescript: - version: 0.7.20 + version: 0.7.42 acceptHeaderEnum: false additionalDependencies: dependencies: {} diff --git a/packages/sdk/.speakeasy/out.openapi.yaml b/packages/sdk/.speakeasy/out.openapi.yaml index 9f362a300..c28ddd715 100644 --- a/packages/sdk/.speakeasy/out.openapi.yaml +++ b/packages/sdk/.speakeasy/out.openapi.yaml @@ -26,40 +26,39 @@ components: Customer: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" name: anyOf: - type: string - type: "null" + description: The name of the customer. email: anyOf: - type: string - type: "null" - created_at: - type: number + description: The email address of the customer. fingerprint: anyOf: - type: string - type: "null" + description: "A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID." stripe_id: anyOf: - type: string - type: "null" + description: Stripe customer ID. env: enum: - sandbox - live + description: The environment this customer was created in. metadata: type: object propertyNames: {} additionalProperties: {} + description: The metadata for the customer. send_email_receipts: type: boolean + description: Whether to send email receipts to the customer. subscriptions: type: array items: @@ -148,55 +147,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - name: - type: string - type: - enum: - - boolean - - metered - - credit_system - consumable: - type: boolean - event_names: - type: array - items: - type: string - credit_schema: - type: array - items: - type: object - properties: - metered_feature_id: - type: string - credit_cost: - type: number - required: - - metered_feature_id - - credit_cost - display: - type: object - properties: - singular: - anyOf: - - type: string - - type: "null" - plural: - anyOf: - - type: string - - type: "null" - archived: - type: boolean - required: - - id - - name - - type - - consumable - - archived granted: type: number remaining: @@ -221,9 +171,6 @@ components: items: type: object properties: - id: - type: string - default: "" plan_id: anyOf: - type: string @@ -357,9 +304,6 @@ components: currency: type: string description: The currency code for the invoice - created_at: - type: number - description: Timestamp when the invoice was created hosted_invoice_url: anyOf: - type: string @@ -371,19 +315,11 @@ components: - status - total - currency - - created_at entities: type: array items: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" - description: The unique identifier of the entity name: anyOf: - type: string @@ -399,18 +335,13 @@ components: - type: string - type: "null" description: The feature ID this entity belongs to - created_at: - type: number - description: Unix timestamp when the entity was created env: enum: - sandbox - live description: The environment (sandbox/live) required: - - id - name - - created_at - env trials_used: type: array @@ -437,9 +368,6 @@ components: items: type: object properties: - id: - type: string - description: The unique identifier for this discount name: type: string description: The name of the discount or coupon @@ -490,7 +418,6 @@ components: - type: "null" description: Total amount saved from this discount required: - - id - name - type - discount_value @@ -509,8 +436,6 @@ components: customer: type: object properties: - id: - type: string name: anyOf: - type: string @@ -519,26 +444,20 @@ components: anyOf: - type: string - type: "null" - required: - - id + required: [] reward_applied: type: boolean - created_at: - type: number required: - program_id - customer - reward_applied - - created_at payment_method: anyOf: - {} - type: "null" required: - - id - name - email - - created_at - fingerprint - stripe_id - env @@ -547,11 +466,34 @@ components: - subscriptions - purchases - balances + examples: + - id: cus_123 + created_at: 1717000000 + name: John Doe + email: john@example.com + fingerprint: "1234567890" + stripe_id: cus_123 + env: sandbox + metadata: {} + subscriptions: + - id: sub_123 + created_at: 1717000000 + plan_id: plan_123 + status: active + quantity: 1 + interval: month + interval_count: 1 + purchases: [] + balances: + balance_1: + id: balance_1 + amount: 100 + currency: USD + created_at: 1717000000 + updated_at: 1717000000 Plan: type: object properties: - id: - type: string name: type: string description: @@ -584,15 +526,6 @@ components: - year interval_count: type: number - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text required: - amount - interval @@ -604,65 +537,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type included: type: number unlimited: @@ -733,15 +607,6 @@ components: - billing_method - max_purchase - type: "null" - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text rollover: type: object properties: @@ -796,8 +661,6 @@ components: - duration_length - duration_type - card_required - created_at: - type: number env: enum: - sandbox @@ -827,7 +690,6 @@ components: required: - scenario required: - - id - name - description - group @@ -836,7 +698,6 @@ components: - auto_enable - price - items - - created_at - env - archived - base_variant_id @@ -918,67 +779,21 @@ paths: auto_enable_plan_id: type: string description: The ID of the free plan to auto-enable for the customer - processors: - anyOf: - - type: object - properties: - vercel: - type: object - properties: - installation_id: - type: string - access_token: - type: string - account_id: - type: string - custom_payment_method_id: - type: string - required: - - installation_id - - access_token - - account_id - - type: "null" - description: External processors for the customer send_email_receipts: type: boolean description: Whether to send email receipts to this customer - internal_options: - type: object - properties: - default_group: - type: string - description: The group of products to attach to the customer - disable_defaults: - type: boolean - description: Whether to disable default products expand: type: array items: $ref: "#/components/schemas/CustomerExpand" description: Customer expand options - entity_id: - type: string - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id - id: - anyOf: - - $ref: "#/components/schemas/CustomerId" - - type: "null" - with_autumn_id: - type: boolean - default: false required: - customer_id title: GetOrCreateCustomerParams + examples: + - customer_id: cus_123 + name: John Doe + email: john@example.com responses: "200": description: OK @@ -1029,21 +844,6 @@ paths: schema: type: object properties: - entity_id: - anyOf: - - type: string - - type: "null" - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id options: anyOf: - type: array @@ -1098,75 +898,6 @@ paths: - type: string - type: "null" description: The feature ID of the product item. Should be null for fixed price items. - feature_type: - anyOf: - - enum: - - single_use - - continuous_use - - boolean - - static - - type: "null" - feature: - anyOf: - - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type - - type: "null" included_usage: anyOf: - anyOf: @@ -1238,80 +969,6 @@ paths: - type: boolean - type: "null" description: Whether the usage should be reset when the product is enabled. - display: - anyOf: - - type: object - properties: - primary_text: - type: string - secondary_text: - anyOf: - - type: string - - type: "null" - required: - - primary_text - - type: "null" - usage_limit: - anyOf: - - type: number - - type: "null" - config: - anyOf: - - type: object - properties: - on_increase: - anyOf: - - enum: - - bill_immediately - - prorate_immediately - - prorate_next_cycle - - bill_next_cycle - - type: "null" - on_decrease: - anyOf: - - enum: - - prorate - - prorate_immediately - - prorate_next_cycle - - none - - no_prorations - - type: "null" - rollover: - anyOf: - - type: object - properties: - max: - anyOf: - - type: number - - type: "null" - duration: - enum: - - month - - forever - default: month - length: - type: number - required: - - max - - length - - type: "null" - - type: "null" - created_at: - anyOf: - - type: number - - type: "null" - entitlement_id: - anyOf: - - type: string - - type: "null" - price_id: - anyOf: - - type: string - - type: "null" - price_config: - anyOf: - - {} - - type: "null" product_id: type: string invoice: @@ -1352,8 +1009,6 @@ paths: properties: customer_id: type: string - entity_id: - type: string invoice: type: object properties: diff --git a/packages/sdk/.speakeasy/workflow.lock b/packages/sdk/.speakeasy/workflow.lock index 7f3e0d05c..528af62f5 100644 --- a/packages/sdk/.speakeasy/workflow.lock +++ b/packages/sdk/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.718.0 sources: Autumn API: sourceNamespace: autumn-api - sourceRevisionDigest: sha256:870cf5d97b4095695b870c563c519e87267e9b61c1c77e0702ba713ed5016249 - sourceBlobDigest: sha256:d056cbb523f45acbfe06ad522417e87c888e233cb9d39800b0879a0f03715b15 + sourceRevisionDigest: sha256:5e16ae7af44b95d164092bec91f923bb1ec7454116438f50f5cb3f18dfe3920f + sourceBlobDigest: sha256:0bcea56021f5f5820c80a29e9bd7fcfa9ea856f7fe8cf0a3ea3766b5b837aebe tags: - latest - 2.1.0 @@ -11,10 +11,10 @@ targets: autumn: source: Autumn API sourceNamespace: autumn-api - sourceRevisionDigest: sha256:870cf5d97b4095695b870c563c519e87267e9b61c1c77e0702ba713ed5016249 - sourceBlobDigest: sha256:d056cbb523f45acbfe06ad522417e87c888e233cb9d39800b0879a0f03715b15 + sourceRevisionDigest: sha256:5e16ae7af44b95d164092bec91f923bb1ec7454116438f50f5cb3f18dfe3920f + sourceBlobDigest: sha256:0bcea56021f5f5820c80a29e9bd7fcfa9ea856f7fe8cf0a3ea3766b5b837aebe codeSamplesNamespace: autumn-api-typescript-code-samples - codeSamplesRevisionDigest: sha256:57f6c87bf54eebe3cc8972b4b752cc5c8acbb5579db5a72c62712c09a7535c4c + codeSamplesRevisionDigest: sha256:ce36f97d10345afb030ba1efd384c3bb8444afd11b275d20d04cd1f037fff6a2 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/packages/sdk/FUNCTIONS.md b/packages/sdk/FUNCTIONS.md index 366dd158e..997ec44c4 100644 --- a/packages/sdk/FUNCTIONS.md +++ b/packages/sdk/FUNCTIONS.md @@ -31,7 +31,9 @@ const autumn = new AutumnCore({ async function run() { const res = await customersGetOrCreate(autumn, { - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); if (res.ok) { const { value: result } = res; diff --git a/packages/sdk/README.md b/packages/sdk/README.md index c9678a281..c2a1c7d7c 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -95,7 +95,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); @@ -128,7 +130,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); @@ -226,7 +230,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }, { retries: { strategy: "backoff", @@ -268,7 +274,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); @@ -305,7 +313,9 @@ const autumn = new Autumn({ async function run() { try { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); @@ -362,7 +372,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); diff --git a/packages/sdk/USAGE.md b/packages/sdk/USAGE.md index 1f64b54ba..b1d99bf9e 100644 --- a/packages/sdk/USAGE.md +++ b/packages/sdk/USAGE.md @@ -9,7 +9,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); diff --git a/packages/sdk/docs/models/attach-credit-schema.md b/packages/sdk/docs/models/attach-credit-schema.md deleted file mode 100644 index 20689c736..000000000 --- a/packages/sdk/docs/models/attach-credit-schema.md +++ /dev/null @@ -1,19 +0,0 @@ -# AttachCreditSchema - -## Example Usage - -```typescript -import { AttachCreditSchema } from "@useautumn/sdk"; - -let value: AttachCreditSchema = { - meteredFeatureId: "", - creditCost: 3433.52, -}; -``` - -## Fields - -| Field | Type | Required | Description | -| --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | -| `meteredFeatureId` | *string* | :heavy_check_mark: | The ID of the metered feature (should be a single_use feature). | -| `creditCost` | *number* | :heavy_check_mark: | The credit cost of the metered feature. | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-display.md b/packages/sdk/docs/models/attach-display.md deleted file mode 100644 index c58afd1fc..000000000 --- a/packages/sdk/docs/models/attach-display.md +++ /dev/null @@ -1,18 +0,0 @@ -# AttachDisplay - -## Example Usage - -```typescript -import { AttachDisplay } from "@useautumn/sdk"; - -let value: AttachDisplay = { - primaryText: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `primaryText` | *string* | :heavy_check_mark: | N/A | -| `secondaryText` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-entity-data.md b/packages/sdk/docs/models/attach-entity-data.md deleted file mode 100644 index bbbd9b619..000000000 --- a/packages/sdk/docs/models/attach-entity-data.md +++ /dev/null @@ -1,18 +0,0 @@ -# AttachEntityData - -## Example Usage - -```typescript -import { AttachEntityData } from "@useautumn/sdk"; - -let value: AttachEntityData = { - featureId: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | -| `featureId` | *string* | :heavy_check_mark: | The feature ID that this entity is associated with | -| `name` | *string* | :heavy_minus_sign: | Name of the entity | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-feature-display.md b/packages/sdk/docs/models/attach-feature-display.md deleted file mode 100644 index 34af62fc1..000000000 --- a/packages/sdk/docs/models/attach-feature-display.md +++ /dev/null @@ -1,19 +0,0 @@ -# AttachFeatureDisplay - -## Example Usage - -```typescript -import { AttachFeatureDisplay } from "@useautumn/sdk"; - -let value: AttachFeatureDisplay = { - singular: "", - plural: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------------------------------ | ------------------------------------------ | ------------------------------------------ | ------------------------------------------ | -| `singular` | *string* | :heavy_check_mark: | The singular display name for the feature. | -| `plural` | *string* | :heavy_check_mark: | The plural display name for the feature. | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-feature-type.md b/packages/sdk/docs/models/attach-feature-type.md deleted file mode 100644 index 47b42c605..000000000 --- a/packages/sdk/docs/models/attach-feature-type.md +++ /dev/null @@ -1,17 +0,0 @@ -# AttachFeatureType - -The type of the feature - -## Example Usage - -```typescript -import { AttachFeatureType } from "@useautumn/sdk"; - -let value: AttachFeatureType = "boolean"; -``` - -## Values - -```typescript -"static" | "boolean" | "single_use" | "continuous_use" | "credit_system" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-feature.md b/packages/sdk/docs/models/attach-feature.md deleted file mode 100644 index 559ceb6cb..000000000 --- a/packages/sdk/docs/models/attach-feature.md +++ /dev/null @@ -1,23 +0,0 @@ -# AttachFeature - -## Example Usage - -```typescript -import { AttachFeature } from "@useautumn/sdk"; - -let value: AttachFeature = { - id: "", - type: "single_use", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -| `id` | *string* | :heavy_check_mark: | The ID of the feature, used to refer to it in other API calls like /track or /check. | -| `name` | *string* | :heavy_minus_sign: | The name of the feature. | -| `type` | [models.AttachFeatureType](../models/attach-feature-type.md) | :heavy_check_mark: | The type of the feature | -| `display` | [models.AttachFeatureDisplay](../models/attach-feature-display.md) | :heavy_minus_sign: | Singular and plural display names for the feature. | -| `creditSchema` | [models.AttachCreditSchema](../models/attach-credit-schema.md)[] | :heavy_minus_sign: | Credit cost schema for credit system features. | -| `archived` | *boolean* | :heavy_minus_sign: | Whether or not the feature is archived. | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-free-trial.md b/packages/sdk/docs/models/attach-free-trial.md index 1a2397bd2..7b56ce6ed 100644 --- a/packages/sdk/docs/models/attach-free-trial.md +++ b/packages/sdk/docs/models/attach-free-trial.md @@ -13,8 +13,8 @@ let value: AttachFreeTrial = { ## Fields -| Field | Type | Required | Description | -| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| `length` | *number* | :heavy_check_mark: | N/A | -| `duration` | [models.FreeTrialDuration](../models/free-trial-duration.md) | :heavy_check_mark: | N/A | -| `cardRequired` | *boolean* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | +| `length` | *number* | :heavy_check_mark: | N/A | +| `duration` | [models.Duration](../models/duration.md) | :heavy_check_mark: | N/A | +| `cardRequired` | *boolean* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-item.md b/packages/sdk/docs/models/attach-item.md index 7e639c989..5dab41e71 100644 --- a/packages/sdk/docs/models/attach-item.md +++ b/packages/sdk/docs/models/attach-item.md @@ -14,8 +14,6 @@ let value: AttachItem = {}; | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | [models.AttachType](../models/attach-type.md) | :heavy_minus_sign: | The type of the product item. | | `featureId` | *string* | :heavy_minus_sign: | The feature ID of the product item. Should be null for fixed price items. | -| `featureType` | [models.FeatureType](../models/feature-type.md) | :heavy_minus_sign: | N/A | -| `feature` | [models.AttachFeature](../models/attach-feature.md) | :heavy_minus_sign: | N/A | | `includedUsage` | *models.IncludedUsage* | :heavy_minus_sign: | The amount of usage included for this feature (per interval). | | `interval` | [models.AttachInterval](../models/attach-interval.md) | :heavy_minus_sign: | The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a price, it will be billed one-off. | | `intervalCount` | *number* | :heavy_minus_sign: | Interval count of the feature. | @@ -24,11 +22,4 @@ let value: AttachItem = {}; | `price` | *number* | :heavy_minus_sign: | The price of the product item. Should be null if tiered pricing is set. | | `tiers` | [models.Tiers](../models/tiers.md)[] | :heavy_minus_sign: | Tiered pricing for the product item. Not applicable for fixed price items. | | `billingUnits` | *number* | :heavy_minus_sign: | The billing units of the product item (eg $1 for 30 credits). | -| `resetUsageWhenEnabled` | *boolean* | :heavy_minus_sign: | Whether the usage should be reset when the product is enabled. | -| `display` | [models.AttachDisplay](../models/attach-display.md) | :heavy_minus_sign: | N/A | -| `usageLimit` | *number* | :heavy_minus_sign: | N/A | -| `config` | [models.Config](../models/config.md) | :heavy_minus_sign: | N/A | -| `createdAt` | *number* | :heavy_minus_sign: | N/A | -| `entitlementId` | *string* | :heavy_minus_sign: | N/A | -| `priceId` | *string* | :heavy_minus_sign: | N/A | -| `priceConfig` | *any* | :heavy_minus_sign: | N/A | \ No newline at end of file +| `resetUsageWhenEnabled` | *boolean* | :heavy_minus_sign: | Whether the usage should be reset when the product is enabled. | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-on-decrease.md b/packages/sdk/docs/models/attach-on-decrease.md deleted file mode 100644 index f1b38ac1a..000000000 --- a/packages/sdk/docs/models/attach-on-decrease.md +++ /dev/null @@ -1,15 +0,0 @@ -# AttachOnDecrease - -## Example Usage - -```typescript -import { AttachOnDecrease } from "@useautumn/sdk"; - -let value: AttachOnDecrease = "prorate_next_cycle"; -``` - -## Values - -```typescript -"prorate" | "prorate_immediately" | "prorate_next_cycle" | "none" | "no_prorations" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-on-increase.md b/packages/sdk/docs/models/attach-on-increase.md deleted file mode 100644 index f31507627..000000000 --- a/packages/sdk/docs/models/attach-on-increase.md +++ /dev/null @@ -1,15 +0,0 @@ -# AttachOnIncrease - -## Example Usage - -```typescript -import { AttachOnIncrease } from "@useautumn/sdk"; - -let value: AttachOnIncrease = "prorate_next_cycle"; -``` - -## Values - -```typescript -"bill_immediately" | "prorate_immediately" | "prorate_next_cycle" | "bill_next_cycle" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-request.md b/packages/sdk/docs/models/attach-request.md index adce3a547..50a550a22 100644 --- a/packages/sdk/docs/models/attach-request.md +++ b/packages/sdk/docs/models/attach-request.md @@ -12,21 +12,19 @@ let value: AttachRequest = { ## Fields -| Field | Type | Required | Description | -| ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | -| `entityId` | *string* | :heavy_minus_sign: | N/A | -| `entityData` | [models.AttachEntityData](../models/attach-entity-data.md) | :heavy_minus_sign: | N/A | -| `options` | [models.Options](../models/options.md)[] | :heavy_minus_sign: | N/A | -| `version` | *number* | :heavy_minus_sign: | N/A | -| `freeTrial` | [models.AttachFreeTrial](../models/attach-free-trial.md) | :heavy_minus_sign: | N/A | -| `items` | [models.AttachItem](../models/attach-item.md)[] | :heavy_minus_sign: | N/A | -| `productId` | *string* | :heavy_check_mark: | N/A | -| `invoice` | *boolean* | :heavy_minus_sign: | N/A | -| `enableProductImmediately` | *boolean* | :heavy_minus_sign: | N/A | -| `finalizeInvoice` | *boolean* | :heavy_minus_sign: | N/A | -| `redirectMode` | [models.RedirectMode](../models/redirect-mode.md) | :heavy_minus_sign: | N/A | -| `successUrl` | *string* | :heavy_minus_sign: | N/A | -| `newBillingSubscription` | *boolean* | :heavy_minus_sign: | N/A | -| `planSchedule` | [models.PlanSchedule](../models/plan-schedule.md) | :heavy_minus_sign: | N/A | -| `billingBehavior` | [models.BillingBehavior](../models/billing-behavior.md) | :heavy_minus_sign: | N/A | -| `adjustableQuantity` | *boolean* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | +| `options` | [models.Options](../models/options.md)[] | :heavy_minus_sign: | N/A | +| `version` | *number* | :heavy_minus_sign: | N/A | +| `freeTrial` | [models.AttachFreeTrial](../models/attach-free-trial.md) | :heavy_minus_sign: | N/A | +| `items` | [models.AttachItem](../models/attach-item.md)[] | :heavy_minus_sign: | N/A | +| `productId` | *string* | :heavy_check_mark: | N/A | +| `invoice` | *boolean* | :heavy_minus_sign: | N/A | +| `enableProductImmediately` | *boolean* | :heavy_minus_sign: | N/A | +| `finalizeInvoice` | *boolean* | :heavy_minus_sign: | N/A | +| `redirectMode` | [models.RedirectMode](../models/redirect-mode.md) | :heavy_minus_sign: | N/A | +| `successUrl` | *string* | :heavy_minus_sign: | N/A | +| `newBillingSubscription` | *boolean* | :heavy_minus_sign: | N/A | +| `planSchedule` | [models.PlanSchedule](../models/plan-schedule.md) | :heavy_minus_sign: | N/A | +| `billingBehavior` | [models.BillingBehavior](../models/billing-behavior.md) | :heavy_minus_sign: | N/A | +| `adjustableQuantity` | *boolean* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-response.md b/packages/sdk/docs/models/attach-response.md index 2c48f0863..b3eec4c3f 100644 --- a/packages/sdk/docs/models/attach-response.md +++ b/packages/sdk/docs/models/attach-response.md @@ -18,7 +18,6 @@ let value: AttachResponse = { | Field | Type | Required | Description | | ----------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | | `customerId` | *string* | :heavy_check_mark: | N/A | -| `entityId` | *string* | :heavy_minus_sign: | N/A | | `invoice` | [models.AttachInvoice](../models/attach-invoice.md) | :heavy_minus_sign: | N/A | | `paymentUrl` | *string* | :heavy_check_mark: | N/A | | `requiredAction` | [models.RequiredAction](../models/required-action.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/attach-rollover.md b/packages/sdk/docs/models/attach-rollover.md deleted file mode 100644 index 8eb5c77fb..000000000 --- a/packages/sdk/docs/models/attach-rollover.md +++ /dev/null @@ -1,20 +0,0 @@ -# AttachRollover - -## Example Usage - -```typescript -import { AttachRollover } from "@useautumn/sdk"; - -let value: AttachRollover = { - max: 2750.92, - length: 3617.46, -}; -``` - -## Fields - -| Field | Type | Required | Description | -| --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | -| `max` | *number* | :heavy_check_mark: | N/A | -| `duration` | [models.RolloverDuration](../models/rollover-duration.md) | :heavy_minus_sign: | N/A | -| `length` | *number* | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/balances-type.md b/packages/sdk/docs/models/balances-type.md deleted file mode 100644 index 1c48ab0c7..000000000 --- a/packages/sdk/docs/models/balances-type.md +++ /dev/null @@ -1,17 +0,0 @@ -# BalancesType - -## Example Usage - -```typescript -import { BalancesType } from "@useautumn/sdk"; - -let value: BalancesType = "boolean"; -``` - -## Values - -This is an open enum. Unrecognized values will be captured as the `Unrecognized` branded type. - -```typescript -"boolean" | "metered" | "credit_system" | Unrecognized -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/balances.md b/packages/sdk/docs/models/balances.md index fd59d3018..3cecc0799 100644 --- a/packages/sdk/docs/models/balances.md +++ b/packages/sdk/docs/models/balances.md @@ -22,7 +22,6 @@ let value: Balances = { | Field | Type | Required | Description | | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | | `featureId` | *string* | :heavy_check_mark: | N/A | -| `feature` | [models.CustomerFeature](../models/customer-feature.md) | :heavy_minus_sign: | N/A | | `granted` | *number* | :heavy_check_mark: | N/A | | `remaining` | *number* | :heavy_check_mark: | N/A | | `usage` | *number* | :heavy_check_mark: | N/A | diff --git a/packages/sdk/docs/models/breakdown.md b/packages/sdk/docs/models/breakdown.md index f6bdbd480..be7b8808f 100644 --- a/packages/sdk/docs/models/breakdown.md +++ b/packages/sdk/docs/models/breakdown.md @@ -29,7 +29,6 @@ let value: Breakdown = { | Field | Type | Required | Description | | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | -| `id` | *string* | :heavy_minus_sign: | N/A | | `planId` | *string* | :heavy_check_mark: | N/A | | `includedGrant` | *number* | :heavy_check_mark: | N/A | | `prepaidGrant` | *number* | :heavy_check_mark: | N/A | diff --git a/packages/sdk/docs/models/config.md b/packages/sdk/docs/models/config.md deleted file mode 100644 index dc4642115..000000000 --- a/packages/sdk/docs/models/config.md +++ /dev/null @@ -1,17 +0,0 @@ -# Config - -## Example Usage - -```typescript -import { Config } from "@useautumn/sdk"; - -let value: Config = {}; -``` - -## Fields - -| Field | Type | Required | Description | -| ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | -| `onIncrease` | [models.AttachOnIncrease](../models/attach-on-increase.md) | :heavy_minus_sign: | N/A | -| `onDecrease` | [models.AttachOnDecrease](../models/attach-on-decrease.md) | :heavy_minus_sign: | N/A | -| `rollover` | [models.AttachRollover](../models/attach-rollover.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/customer-credit-schema.md b/packages/sdk/docs/models/customer-credit-schema.md deleted file mode 100644 index de538f3a7..000000000 --- a/packages/sdk/docs/models/customer-credit-schema.md +++ /dev/null @@ -1,19 +0,0 @@ -# CustomerCreditSchema - -## Example Usage - -```typescript -import { CustomerCreditSchema } from "@useautumn/sdk"; - -let value: CustomerCreditSchema = { - meteredFeatureId: "", - creditCost: 4.76, -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `meteredFeatureId` | *string* | :heavy_check_mark: | N/A | -| `creditCost` | *number* | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/customer-display.md b/packages/sdk/docs/models/customer-display.md deleted file mode 100644 index d86e56fea..000000000 --- a/packages/sdk/docs/models/customer-display.md +++ /dev/null @@ -1,16 +0,0 @@ -# CustomerDisplay - -## Example Usage - -```typescript -import { CustomerDisplay } from "@useautumn/sdk"; - -let value: CustomerDisplay = {}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `singular` | *string* | :heavy_minus_sign: | N/A | -| `plural` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/customer-env.md b/packages/sdk/docs/models/customer-env.md index a94e44346..d210083c5 100644 --- a/packages/sdk/docs/models/customer-env.md +++ b/packages/sdk/docs/models/customer-env.md @@ -1,5 +1,7 @@ # CustomerEnv +The environment this customer was created in. + ## Example Usage ```typescript diff --git a/packages/sdk/docs/models/customer-feature.md b/packages/sdk/docs/models/customer-feature.md deleted file mode 100644 index 3cf02ec91..000000000 --- a/packages/sdk/docs/models/customer-feature.md +++ /dev/null @@ -1,28 +0,0 @@ -# CustomerFeature - -## Example Usage - -```typescript -import { CustomerFeature } from "@useautumn/sdk"; - -let value: CustomerFeature = { - id: "", - name: "", - type: "metered", - consumable: false, - archived: true, -}; -``` - -## Fields - -| Field | Type | Required | Description | -| -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -| `id` | *string* | :heavy_check_mark: | N/A | -| `name` | *string* | :heavy_check_mark: | N/A | -| `type` | [models.BalancesType](../models/balances-type.md) | :heavy_check_mark: | N/A | -| `consumable` | *boolean* | :heavy_check_mark: | N/A | -| `eventNames` | *string*[] | :heavy_minus_sign: | N/A | -| `creditSchema` | [models.CustomerCreditSchema](../models/customer-credit-schema.md)[] | :heavy_minus_sign: | N/A | -| `display` | [models.CustomerDisplay](../models/customer-display.md) | :heavy_minus_sign: | N/A | -| `archived` | *boolean* | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/customer.md b/packages/sdk/docs/models/customer.md index 0839a1cd2..3df262773 100644 --- a/packages/sdk/docs/models/customer.md +++ b/packages/sdk/docs/models/customer.md @@ -6,46 +6,40 @@ import { Customer } from "@useautumn/sdk"; let value: Customer = { - id: "", - name: null, - email: "Kevin73@hotmail.com", - createdAt: 9956.34, - fingerprint: "", - stripeId: "", - env: "live", - metadata: { - "key": "", - "key1": "", - "key2": "", - }, + name: "John Doe", + email: "john@example.com", + fingerprint: "1234567890", + stripeId: "cus_123", + env: "sandbox", + metadata: {}, sendEmailReceipts: false, subscriptions: [ { - planId: "", - autoEnable: false, - addOn: true, - status: "expired", - pastDue: true, - canceledAt: null, - expiresAt: 1710.61, - trialEndsAt: 8042.54, - startedAt: 72.25, - currentPeriodStart: 8651.43, - currentPeriodEnd: 7213.89, - quantity: 3438, + planId: "plan_123", + autoEnable: true, + addOn: false, + status: "active", + pastDue: false, + canceledAt: 9016.07, + expiresAt: 7919.45, + trialEndsAt: 9802.8, + startedAt: 9956.34, + currentPeriodStart: 4924.95, + currentPeriodEnd: 7855.7, + quantity: 1, }, ], purchases: [], balances: { - "key": { + "balance_1": { featureId: "", - granted: 3195.9, - remaining: 3289.89, - usage: 4599.27, - unlimited: false, + granted: 7438.76, + remaining: 7441.15, + usage: 5903.02, + unlimited: true, overageAllowed: false, - maxPurchase: 1182.05, - nextResetAt: 5644.6, + maxPurchase: 934.85, + nextResetAt: 1710.61, }, }, }; @@ -53,24 +47,21 @@ let value: Customer = { ## Fields -| Field | Type | Required | Description | -| -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -| `autumnId` | *string* | :heavy_minus_sign: | N/A | -| `id` | *string* | :heavy_check_mark: | N/A | -| `name` | *string* | :heavy_check_mark: | N/A | -| `email` | *string* | :heavy_check_mark: | N/A | -| `createdAt` | *number* | :heavy_check_mark: | N/A | -| `fingerprint` | *string* | :heavy_check_mark: | N/A | -| `stripeId` | *string* | :heavy_check_mark: | N/A | -| `env` | [models.CustomerEnv](../models/customer-env.md) | :heavy_check_mark: | N/A | -| `metadata` | Record | :heavy_check_mark: | N/A | -| `sendEmailReceipts` | *boolean* | :heavy_check_mark: | N/A | -| `subscriptions` | [models.Subscription](../models/subscription.md)[] | :heavy_check_mark: | N/A | -| `purchases` | [models.Purchase](../models/purchase.md)[] | :heavy_check_mark: | N/A | -| `balances` | Record | :heavy_check_mark: | N/A | -| `invoices` | [models.Invoice](../models/invoice.md)[] | :heavy_minus_sign: | N/A | -| `entities` | [models.Entity](../models/entity.md)[] | :heavy_minus_sign: | N/A | -| `trialsUsed` | [models.TrialsUsed](../models/trials-used.md)[] | :heavy_minus_sign: | N/A | -| `rewards` | [models.Rewards](../models/rewards.md) | :heavy_minus_sign: | N/A | -| `referrals` | [models.Referral](../models/referral.md)[] | :heavy_minus_sign: | N/A | -| `paymentMethod` | *any* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| `name` | *string* | :heavy_check_mark: | The name of the customer. | +| `email` | *string* | :heavy_check_mark: | The email address of the customer. | +| `fingerprint` | *string* | :heavy_check_mark: | A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID. | +| `stripeId` | *string* | :heavy_check_mark: | Stripe customer ID. | +| `env` | [models.CustomerEnv](../models/customer-env.md) | :heavy_check_mark: | The environment this customer was created in. | +| `metadata` | Record | :heavy_check_mark: | The metadata for the customer. | +| `sendEmailReceipts` | *boolean* | :heavy_check_mark: | Whether to send email receipts to the customer. | +| `subscriptions` | [models.Subscription](../models/subscription.md)[] | :heavy_check_mark: | N/A | +| `purchases` | [models.Purchase](../models/purchase.md)[] | :heavy_check_mark: | N/A | +| `balances` | Record | :heavy_check_mark: | N/A | +| `invoices` | [models.Invoice](../models/invoice.md)[] | :heavy_minus_sign: | N/A | +| `entities` | [models.Entity](../models/entity.md)[] | :heavy_minus_sign: | N/A | +| `trialsUsed` | [models.TrialsUsed](../models/trials-used.md)[] | :heavy_minus_sign: | N/A | +| `rewards` | [models.Rewards](../models/rewards.md) | :heavy_minus_sign: | N/A | +| `referrals` | [models.Referral](../models/referral.md)[] | :heavy_minus_sign: | N/A | +| `paymentMethod` | *any* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/discount.md b/packages/sdk/docs/models/discount.md index 1cd19465e..ea251e97c 100644 --- a/packages/sdk/docs/models/discount.md +++ b/packages/sdk/docs/models/discount.md @@ -6,7 +6,6 @@ import { Discount } from "@useautumn/sdk"; let value: Discount = { - id: "", name: "", type: "free_product", discountValue: 8208.57, @@ -18,9 +17,8 @@ let value: Discount = { | Field | Type | Required | Description | | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| `id` | *string* | :heavy_check_mark: | The unique identifier for this discount | | `name` | *string* | :heavy_check_mark: | The name of the discount or coupon | -| `type` | [models.RewardsType](../models/rewards-type.md) | :heavy_check_mark: | The type of reward | +| `type` | [models.Type](../models/type.md) | :heavy_check_mark: | The type of reward | | `discountValue` | *number* | :heavy_check_mark: | The discount value (percentage or fixed amount) | | `durationType` | [models.CustomerDurationType](../models/customer-duration-type.md) | :heavy_check_mark: | How long the discount lasts | | `durationValue` | *number* | :heavy_minus_sign: | Number of billing periods the discount applies for repeating durations | diff --git a/packages/sdk/docs/models/duration.md b/packages/sdk/docs/models/duration.md new file mode 100644 index 000000000..e70c1be44 --- /dev/null +++ b/packages/sdk/docs/models/duration.md @@ -0,0 +1,15 @@ +# Duration + +## Example Usage + +```typescript +import { Duration } from "@useautumn/sdk"; + +let value: Duration = "year"; +``` + +## Values + +```typescript +"day" | "month" | "year" +``` \ No newline at end of file diff --git a/packages/sdk/docs/models/entity.md b/packages/sdk/docs/models/entity.md index 2ea16cf6f..5445e914a 100644 --- a/packages/sdk/docs/models/entity.md +++ b/packages/sdk/docs/models/entity.md @@ -6,9 +6,7 @@ import { Entity } from "@useautumn/sdk"; let value: Entity = { - id: "", name: "", - createdAt: 4436.47, env: "sandbox", }; ``` @@ -17,10 +15,7 @@ let value: Entity = { | Field | Type | Required | Description | | ------------------------------------------- | ------------------------------------------- | ------------------------------------------- | ------------------------------------------- | -| `autumnId` | *string* | :heavy_minus_sign: | N/A | -| `id` | *string* | :heavy_check_mark: | The unique identifier of the entity | | `name` | *string* | :heavy_check_mark: | The name of the entity | | `customerId` | *string* | :heavy_minus_sign: | The customer ID this entity belongs to | | `featureId` | *string* | :heavy_minus_sign: | The feature ID this entity belongs to | -| `createdAt` | *number* | :heavy_check_mark: | Unix timestamp when the entity was created | | `env` | [models.EntityEnv](../models/entity-env.md) | :heavy_check_mark: | The environment (sandbox/live) | \ No newline at end of file diff --git a/packages/sdk/docs/models/feature-type.md b/packages/sdk/docs/models/feature-type.md deleted file mode 100644 index 198d92062..000000000 --- a/packages/sdk/docs/models/feature-type.md +++ /dev/null @@ -1,15 +0,0 @@ -# FeatureType - -## Example Usage - -```typescript -import { FeatureType } from "@useautumn/sdk"; - -let value: FeatureType = "continuous_use"; -``` - -## Values - -```typescript -"single_use" | "continuous_use" | "boolean" | "static" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/free-trial-duration.md b/packages/sdk/docs/models/free-trial-duration.md deleted file mode 100644 index 5e95863ed..000000000 --- a/packages/sdk/docs/models/free-trial-duration.md +++ /dev/null @@ -1,15 +0,0 @@ -# FreeTrialDuration - -## Example Usage - -```typescript -import { FreeTrialDuration } from "@useautumn/sdk"; - -let value: FreeTrialDuration = "month"; -``` - -## Values - -```typescript -"day" | "month" | "year" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/get-or-create-customer-params.md b/packages/sdk/docs/models/get-or-create-customer-params.md index 58995fc8b..570053b31 100644 --- a/packages/sdk/docs/models/get-or-create-customer-params.md +++ b/packages/sdk/docs/models/get-or-create-customer-params.md @@ -6,7 +6,9 @@ import { GetOrCreateCustomerParams } from "@useautumn/sdk"; let value: GetOrCreateCustomerParams = { - customerId: "", + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }; ``` @@ -22,11 +24,5 @@ let value: GetOrCreateCustomerParams = { | `stripeId` | *string* | :heavy_minus_sign: | Stripe customer ID if you already have one | | `createInStripe` | *boolean* | :heavy_minus_sign: | Whether to create the customer in Stripe | | `autoEnablePlanId` | *string* | :heavy_minus_sign: | The ID of the free plan to auto-enable for the customer | -| `processors` | [models.Processors](../models/processors.md) | :heavy_minus_sign: | External processors for the customer | | `sendEmailReceipts` | *boolean* | :heavy_minus_sign: | Whether to send email receipts to this customer | -| `internalOptions` | [models.InternalOptions](../models/internal-options.md) | :heavy_minus_sign: | N/A | -| `expand` | [models.CustomerExpand](../models/customer-expand.md)[] | :heavy_minus_sign: | Customer expand options | -| `entityId` | *string* | :heavy_minus_sign: | N/A | -| `entityData` | [models.GetOrCreateEntityData](../models/get-or-create-entity-data.md) | :heavy_minus_sign: | N/A | -| `id` | *string* | :heavy_minus_sign: | N/A | -| `withAutumnId` | *boolean* | :heavy_minus_sign: | N/A | \ No newline at end of file +| `expand` | [models.CustomerExpand](../models/customer-expand.md)[] | :heavy_minus_sign: | Customer expand options | \ No newline at end of file diff --git a/packages/sdk/docs/models/get-or-create-entity-data.md b/packages/sdk/docs/models/get-or-create-entity-data.md deleted file mode 100644 index c72058963..000000000 --- a/packages/sdk/docs/models/get-or-create-entity-data.md +++ /dev/null @@ -1,18 +0,0 @@ -# GetOrCreateEntityData - -## Example Usage - -```typescript -import { GetOrCreateEntityData } from "@useautumn/sdk"; - -let value: GetOrCreateEntityData = { - featureId: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | -| `featureId` | *string* | :heavy_check_mark: | The feature ID that this entity is associated with | -| `name` | *string* | :heavy_minus_sign: | Name of the entity | \ No newline at end of file diff --git a/packages/sdk/docs/models/internal-options.md b/packages/sdk/docs/models/internal-options.md deleted file mode 100644 index b3d4895eb..000000000 --- a/packages/sdk/docs/models/internal-options.md +++ /dev/null @@ -1,16 +0,0 @@ -# InternalOptions - -## Example Usage - -```typescript -import { InternalOptions } from "@useautumn/sdk"; - -let value: InternalOptions = {}; -``` - -## Fields - -| Field | Type | Required | Description | -| ----------------------------------------------- | ----------------------------------------------- | ----------------------------------------------- | ----------------------------------------------- | -| `defaultGroup` | *string* | :heavy_minus_sign: | The group of products to attach to the customer | -| `disableDefaults` | *boolean* | :heavy_minus_sign: | Whether to disable default products | \ No newline at end of file diff --git a/packages/sdk/docs/models/invoice.md b/packages/sdk/docs/models/invoice.md index 39f3d1c3a..f7338b19b 100644 --- a/packages/sdk/docs/models/invoice.md +++ b/packages/sdk/docs/models/invoice.md @@ -11,7 +11,6 @@ let value: Invoice = { status: "", total: 9115.15, currency: "New Zealand Dollar", - createdAt: 1973.3, }; ``` @@ -24,5 +23,4 @@ let value: Invoice = { | `status` | *string* | :heavy_check_mark: | The status of the invoice | | `total` | *number* | :heavy_check_mark: | The total amount of the invoice | | `currency` | *string* | :heavy_check_mark: | The currency code for the invoice | -| `createdAt` | *number* | :heavy_check_mark: | Timestamp when the invoice was created | | `hostedInvoiceUrl` | *string* | :heavy_minus_sign: | URL to the Stripe-hosted invoice page | \ No newline at end of file diff --git a/packages/sdk/docs/models/item.md b/packages/sdk/docs/models/item.md index b2b784472..8f8d120e3 100644 --- a/packages/sdk/docs/models/item.md +++ b/packages/sdk/docs/models/item.md @@ -23,14 +23,12 @@ let value: Item = { ## Fields -| Field | Type | Required | Description | -| -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -| `featureId` | *string* | :heavy_check_mark: | N/A | -| `feature` | [models.PlanFeature](../models/plan-feature.md) | :heavy_minus_sign: | N/A | -| `included` | *number* | :heavy_check_mark: | N/A | -| `unlimited` | *boolean* | :heavy_check_mark: | N/A | -| `reset` | [models.PlanReset](../models/plan-reset.md) | :heavy_check_mark: | N/A | -| `price` | [models.ItemPrice](../models/item-price.md) | :heavy_check_mark: | N/A | -| `display` | [models.PlanItemDisplay](../models/plan-item-display.md) | :heavy_minus_sign: | N/A | -| `rollover` | [models.PlanRollover](../models/plan-rollover.md) | :heavy_minus_sign: | N/A | -| `proration` | [models.Proration](../models/proration.md) | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | +| `featureId` | *string* | :heavy_check_mark: | N/A | +| `included` | *number* | :heavy_check_mark: | N/A | +| `unlimited` | *boolean* | :heavy_check_mark: | N/A | +| `reset` | [models.PlanReset](../models/plan-reset.md) | :heavy_check_mark: | N/A | +| `price` | [models.ItemPrice](../models/item-price.md) | :heavy_check_mark: | N/A | +| `rollover` | [models.PlanRollover](../models/plan-rollover.md) | :heavy_minus_sign: | N/A | +| `proration` | [models.Proration](../models/proration.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-credit-schema.md b/packages/sdk/docs/models/plan-credit-schema.md deleted file mode 100644 index 9dfd58042..000000000 --- a/packages/sdk/docs/models/plan-credit-schema.md +++ /dev/null @@ -1,19 +0,0 @@ -# PlanCreditSchema - -## Example Usage - -```typescript -import { PlanCreditSchema } from "@useautumn/sdk"; - -let value: PlanCreditSchema = { - meteredFeatureId: "", - creditCost: 2845.35, -}; -``` - -## Fields - -| Field | Type | Required | Description | -| --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | -| `meteredFeatureId` | *string* | :heavy_check_mark: | The ID of the metered feature (should be a single_use feature). | -| `creditCost` | *number* | :heavy_check_mark: | The credit cost of the metered feature. | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-feature-display.md b/packages/sdk/docs/models/plan-feature-display.md deleted file mode 100644 index 659e383ea..000000000 --- a/packages/sdk/docs/models/plan-feature-display.md +++ /dev/null @@ -1,19 +0,0 @@ -# PlanFeatureDisplay - -## Example Usage - -```typescript -import { PlanFeatureDisplay } from "@useautumn/sdk"; - -let value: PlanFeatureDisplay = { - singular: "", - plural: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------------------------------ | ------------------------------------------ | ------------------------------------------ | ------------------------------------------ | -| `singular` | *string* | :heavy_check_mark: | The singular display name for the feature. | -| `plural` | *string* | :heavy_check_mark: | The plural display name for the feature. | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-feature.md b/packages/sdk/docs/models/plan-feature.md deleted file mode 100644 index 1fdccbb59..000000000 --- a/packages/sdk/docs/models/plan-feature.md +++ /dev/null @@ -1,23 +0,0 @@ -# PlanFeature - -## Example Usage - -```typescript -import { PlanFeature } from "@useautumn/sdk"; - -let value: PlanFeature = { - id: "", - type: "boolean", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -| `id` | *string* | :heavy_check_mark: | The ID of the feature, used to refer to it in other API calls like /track or /check. | -| `name` | *string* | :heavy_minus_sign: | The name of the feature. | -| `type` | [models.PlanType](../models/plan-type.md) | :heavy_check_mark: | The type of the feature | -| `display` | [models.PlanFeatureDisplay](../models/plan-feature-display.md) | :heavy_minus_sign: | Singular and plural display names for the feature. | -| `creditSchema` | [models.PlanCreditSchema](../models/plan-credit-schema.md)[] | :heavy_minus_sign: | Credit cost schema for credit system features. | -| `archived` | *boolean* | :heavy_minus_sign: | Whether or not the feature is archived. | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-item-display.md b/packages/sdk/docs/models/plan-item-display.md deleted file mode 100644 index decdbe96b..000000000 --- a/packages/sdk/docs/models/plan-item-display.md +++ /dev/null @@ -1,18 +0,0 @@ -# PlanItemDisplay - -## Example Usage - -```typescript -import { PlanItemDisplay } from "@useautumn/sdk"; - -let value: PlanItemDisplay = { - primaryText: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `primaryText` | *string* | :heavy_check_mark: | N/A | -| `secondaryText` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-price.md b/packages/sdk/docs/models/plan-price.md index 3281c1693..bce113caf 100644 --- a/packages/sdk/docs/models/plan-price.md +++ b/packages/sdk/docs/models/plan-price.md @@ -17,5 +17,4 @@ let value: PlanPrice = { | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | | `amount` | *number* | :heavy_check_mark: | N/A | | `interval` | [models.PriceInterval](../models/price-interval.md) | :heavy_check_mark: | N/A | -| `intervalCount` | *number* | :heavy_minus_sign: | N/A | -| `display` | [models.PriceDisplay](../models/price-display.md) | :heavy_minus_sign: | N/A | \ No newline at end of file +| `intervalCount` | *number* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/plan-type.md b/packages/sdk/docs/models/plan-type.md deleted file mode 100644 index e573a1e61..000000000 --- a/packages/sdk/docs/models/plan-type.md +++ /dev/null @@ -1,19 +0,0 @@ -# PlanType - -The type of the feature - -## Example Usage - -```typescript -import { PlanType } from "@useautumn/sdk"; - -let value: PlanType = "static"; -``` - -## Values - -This is an open enum. Unrecognized values will be captured as the `Unrecognized` branded type. - -```typescript -"static" | "boolean" | "single_use" | "continuous_use" | "credit_system" | Unrecognized -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/plan.md b/packages/sdk/docs/models/plan.md index c02b9a57f..8b12eea5b 100644 --- a/packages/sdk/docs/models/plan.md +++ b/packages/sdk/docs/models/plan.md @@ -6,7 +6,6 @@ import { Plan } from "@useautumn/sdk"; let value: Plan = { - id: "", name: "", description: "deplore incomparable among because tired diligently pillow tenant pro mmm", @@ -19,8 +18,7 @@ let value: Plan = { interval: "one_off", }, items: [], - createdAt: 3920.84, - env: "live", + env: "sandbox", archived: false, baseVariantId: "", }; @@ -30,7 +28,6 @@ let value: Plan = { | Field | Type | Required | Description | | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------------- | -| `id` | *string* | :heavy_check_mark: | N/A | | `name` | *string* | :heavy_check_mark: | N/A | | `description` | *string* | :heavy_check_mark: | N/A | | `group` | *string* | :heavy_check_mark: | N/A | @@ -40,7 +37,6 @@ let value: Plan = { | `price` | [models.PlanPrice](../models/plan-price.md) | :heavy_check_mark: | N/A | | `items` | [models.Item](../models/item.md)[] | :heavy_check_mark: | N/A | | `freeTrial` | [models.FreeTrial](../models/free-trial.md) | :heavy_minus_sign: | N/A | -| `createdAt` | *number* | :heavy_check_mark: | N/A | | `env` | [models.PlanEnv](../models/plan-env.md) | :heavy_check_mark: | N/A | | `archived` | *boolean* | :heavy_check_mark: | N/A | | `baseVariantId` | *string* | :heavy_check_mark: | N/A | diff --git a/packages/sdk/docs/models/price-display.md b/packages/sdk/docs/models/price-display.md deleted file mode 100644 index 9fd571821..000000000 --- a/packages/sdk/docs/models/price-display.md +++ /dev/null @@ -1,18 +0,0 @@ -# PriceDisplay - -## Example Usage - -```typescript -import { PriceDisplay } from "@useautumn/sdk"; - -let value: PriceDisplay = { - primaryText: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `primaryText` | *string* | :heavy_check_mark: | N/A | -| `secondaryText` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/processors.md b/packages/sdk/docs/models/processors.md deleted file mode 100644 index 7d7af7b02..000000000 --- a/packages/sdk/docs/models/processors.md +++ /dev/null @@ -1,15 +0,0 @@ -# Processors - -## Example Usage - -```typescript -import { Processors } from "@useautumn/sdk"; - -let value: Processors = {}; -``` - -## Fields - -| Field | Type | Required | Description | -| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | -| `vercel` | [models.Vercel](../models/vercel.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/referral-customer.md b/packages/sdk/docs/models/referral-customer.md index 9537eddc4..e4978f3af 100644 --- a/packages/sdk/docs/models/referral-customer.md +++ b/packages/sdk/docs/models/referral-customer.md @@ -5,15 +5,12 @@ ```typescript import { ReferralCustomer } from "@useautumn/sdk"; -let value: ReferralCustomer = { - id: "", -}; +let value: ReferralCustomer = {}; ``` ## Fields | Field | Type | Required | Description | | ------------------ | ------------------ | ------------------ | ------------------ | -| `id` | *string* | :heavy_check_mark: | N/A | | `name` | *string* | :heavy_minus_sign: | N/A | | `email` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/referral.md b/packages/sdk/docs/models/referral.md index 6133ec7c2..50e78acb1 100644 --- a/packages/sdk/docs/models/referral.md +++ b/packages/sdk/docs/models/referral.md @@ -7,11 +7,8 @@ import { Referral } from "@useautumn/sdk"; let value: Referral = { programId: "", - customer: { - id: "", - }, + customer: {}, rewardApplied: false, - createdAt: 6538.56, }; ``` @@ -21,5 +18,4 @@ let value: Referral = { | --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------- | | `programId` | *string* | :heavy_check_mark: | N/A | | `customer` | [models.ReferralCustomer](../models/referral-customer.md) | :heavy_check_mark: | N/A | -| `rewardApplied` | *boolean* | :heavy_check_mark: | N/A | -| `createdAt` | *number* | :heavy_check_mark: | N/A | \ No newline at end of file +| `rewardApplied` | *boolean* | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/models/rewards.md b/packages/sdk/docs/models/rewards.md index 08b89a9cc..dd7ce5d16 100644 --- a/packages/sdk/docs/models/rewards.md +++ b/packages/sdk/docs/models/rewards.md @@ -8,7 +8,6 @@ import { Rewards } from "@useautumn/sdk"; let value: Rewards = { discounts: [ { - id: "", name: "", type: "invoice_credits", discountValue: 8349.54, diff --git a/packages/sdk/docs/models/rollover-duration.md b/packages/sdk/docs/models/rollover-duration.md deleted file mode 100644 index 6cf5cb147..000000000 --- a/packages/sdk/docs/models/rollover-duration.md +++ /dev/null @@ -1,15 +0,0 @@ -# RolloverDuration - -## Example Usage - -```typescript -import { RolloverDuration } from "@useautumn/sdk"; - -let value: RolloverDuration = "forever"; -``` - -## Values - -```typescript -"month" | "forever" -``` \ No newline at end of file diff --git a/packages/sdk/docs/models/rewards-type.md b/packages/sdk/docs/models/type.md similarity index 74% rename from packages/sdk/docs/models/rewards-type.md rename to packages/sdk/docs/models/type.md index ca2e4f7e3..6f4d6d7fd 100644 --- a/packages/sdk/docs/models/rewards-type.md +++ b/packages/sdk/docs/models/type.md @@ -1,13 +1,13 @@ -# RewardsType +# Type The type of reward ## Example Usage ```typescript -import { RewardsType } from "@useautumn/sdk"; +import { Type } from "@useautumn/sdk"; -let value: RewardsType = "free_product"; +let value: Type = "percentage_discount"; ``` ## Values diff --git a/packages/sdk/docs/models/vercel.md b/packages/sdk/docs/models/vercel.md deleted file mode 100644 index 73b36b5f5..000000000 --- a/packages/sdk/docs/models/vercel.md +++ /dev/null @@ -1,22 +0,0 @@ -# Vercel - -## Example Usage - -```typescript -import { Vercel } from "@useautumn/sdk"; - -let value: Vercel = { - installationId: "", - accessToken: "", - accountId: "", -}; -``` - -## Fields - -| Field | Type | Required | Description | -| ----------------------- | ----------------------- | ----------------------- | ----------------------- | -| `installationId` | *string* | :heavy_check_mark: | N/A | -| `accessToken` | *string* | :heavy_check_mark: | N/A | -| `accountId` | *string* | :heavy_check_mark: | N/A | -| `customPaymentMethodId` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/packages/sdk/docs/sdks/customers/README.md b/packages/sdk/docs/sdks/customers/README.md index a0b2f21dc..f1b888723 100644 --- a/packages/sdk/docs/sdks/customers/README.md +++ b/packages/sdk/docs/sdks/customers/README.md @@ -51,7 +51,9 @@ const autumn = new Autumn({ async function run() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); @@ -77,7 +79,9 @@ const autumn = new AutumnCore({ async function run() { const res = await customersGetOrCreate(autumn, { - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); if (res.ok) { const { value: result } = res; diff --git a/packages/sdk/examples/customersGetOrCreate.example.ts b/packages/sdk/examples/customersGetOrCreate.example.ts index dc5cc1835..b6af2731f 100644 --- a/packages/sdk/examples/customersGetOrCreate.example.ts +++ b/packages/sdk/examples/customersGetOrCreate.example.ts @@ -20,7 +20,9 @@ const autumn = new Autumn({ async function main() { const result = await autumn.customers.getOrCreate({ - customerId: null, + customerId: "cus_123", + name: "John Doe", + email: "john@example.com", }); console.log(result); diff --git a/packages/sdk/jsr.json b/packages/sdk/jsr.json index 93b86e0cd..684984ebe 100644 --- a/packages/sdk/jsr.json +++ b/packages/sdk/jsr.json @@ -2,7 +2,7 @@ { "name": "@useautumn/sdk", - "version": "0.7.20", + "version": "0.7.42", "exports": { ".": "./src/index.ts", "./models": "./src/models/index.ts", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index ac51ae52a..9d38d97f6 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@useautumn/sdk", - "version": "0.7.20", + "version": "0.7.42", "author": "Speakeasy", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", diff --git a/packages/sdk/src/lib/config.ts b/packages/sdk/src/lib/config.ts index 138841a53..640df00eb 100644 --- a/packages/sdk/src/lib/config.ts +++ b/packages/sdk/src/lib/config.ts @@ -66,7 +66,7 @@ export function serverURLFromOptions(options: SDKOptions): URL | null { export const SDK_METADATA = { language: "typescript", openapiDocVersion: "2.1.0", - sdkVersion: "0.7.20", + sdkVersion: "0.7.42", genVersion: "2.824.1", - userAgent: "speakeasy-sdk/typescript 0.7.20 2.824.1 2.1.0 @useautumn/sdk", + userAgent: "speakeasy-sdk/typescript 0.7.42 2.824.1 2.1.0 @useautumn/sdk", } as const; diff --git a/packages/sdk/src/models/attach-op.ts b/packages/sdk/src/models/attach-op.ts index f6b11ac71..c21e0da46 100644 --- a/packages/sdk/src/models/attach-op.ts +++ b/packages/sdk/src/models/attach-op.ts @@ -16,33 +16,22 @@ export type AttachGlobals = { xApiVersion?: string | undefined; }; -export type AttachEntityData = { - /** - * The feature ID that this entity is associated with - */ - featureId: string; - /** - * Name of the entity - */ - name?: string | undefined; -}; - export type Options = { featureId: string; quantity?: number | undefined; resetAfterTrialEnd?: boolean | undefined; }; -export const FreeTrialDuration = { +export const Duration = { Day: "day", Month: "month", Year: "year", } as const; -export type FreeTrialDuration = ClosedEnum; +export type Duration = ClosedEnum; export type AttachFreeTrial = { length: number; - duration: FreeTrialDuration; + duration: Duration; cardRequired?: boolean | undefined; }; @@ -53,78 +42,6 @@ export const AttachType = { } as const; export type AttachType = ClosedEnum; -export const FeatureType = { - SingleUse: "single_use", - ContinuousUse: "continuous_use", - Boolean: "boolean", - Static: "static", -} as const; -export type FeatureType = ClosedEnum; - -/** - * The type of the feature - */ -export const AttachFeatureType = { - Static: "static", - Boolean: "boolean", - SingleUse: "single_use", - ContinuousUse: "continuous_use", - CreditSystem: "credit_system", -} as const; -/** - * The type of the feature - */ -export type AttachFeatureType = ClosedEnum; - -export type AttachFeatureDisplay = { - /** - * The singular display name for the feature. - */ - singular: string; - /** - * The plural display name for the feature. - */ - plural: string; -}; - -export type AttachCreditSchema = { - /** - * The ID of the metered feature (should be a single_use feature). - */ - meteredFeatureId: string; - /** - * The credit cost of the metered feature. - */ - creditCost: number; -}; - -export type AttachFeature = { - /** - * The ID of the feature, used to refer to it in other API calls like /track or /check. - */ - id: string; - /** - * The name of the feature. - */ - name?: string | null | undefined; - /** - * The type of the feature - */ - type: AttachFeatureType; - /** - * Singular and plural display names for the feature. - */ - display?: AttachFeatureDisplay | null | undefined; - /** - * Credit cost schema for credit system features. - */ - creditSchema?: Array | null | undefined; - /** - * Whether or not the feature is archived. - */ - archived?: boolean | null | undefined; -}; - export type IncludedUsage = number | string; export const AttachInterval = { @@ -161,46 +78,6 @@ export type Tiers = { amount: number; }; -export type AttachDisplay = { - primaryText: string; - secondaryText?: string | null | undefined; -}; - -export const AttachOnIncrease = { - BillImmediately: "bill_immediately", - ProrateImmediately: "prorate_immediately", - ProrateNextCycle: "prorate_next_cycle", - BillNextCycle: "bill_next_cycle", -} as const; -export type AttachOnIncrease = ClosedEnum; - -export const AttachOnDecrease = { - Prorate: "prorate", - ProrateImmediately: "prorate_immediately", - ProrateNextCycle: "prorate_next_cycle", - None: "none", - NoProrations: "no_prorations", -} as const; -export type AttachOnDecrease = ClosedEnum; - -export const RolloverDuration = { - Month: "month", - Forever: "forever", -} as const; -export type RolloverDuration = ClosedEnum; - -export type AttachRollover = { - max: number | null; - duration?: RolloverDuration | undefined; - length: number; -}; - -export type Config = { - onIncrease?: AttachOnIncrease | null | undefined; - onDecrease?: AttachOnDecrease | null | undefined; - rollover?: AttachRollover | null | undefined; -}; - export type AttachItem = { /** * The type of the product item. @@ -210,8 +87,6 @@ export type AttachItem = { * The feature ID of the product item. Should be null for fixed price items. */ featureId?: string | null | undefined; - featureType?: FeatureType | null | undefined; - feature?: AttachFeature | null | undefined; /** * The amount of usage included for this feature (per interval). */ @@ -248,13 +123,6 @@ export type AttachItem = { * Whether the usage should be reset when the product is enabled. */ resetUsageWhenEnabled?: boolean | null | undefined; - display?: AttachDisplay | null | undefined; - usageLimit?: number | null | undefined; - config?: Config | null | undefined; - createdAt?: number | null | undefined; - entitlementId?: string | null | undefined; - priceId?: string | null | undefined; - priceConfig?: any | null | undefined; }; export const RedirectMode = { @@ -277,8 +145,6 @@ export const BillingBehavior = { export type BillingBehavior = ClosedEnum; export type AttachRequest = { - entityId?: string | null | undefined; - entityData?: AttachEntityData | undefined; options?: Array | null | undefined; version?: number | undefined; freeTrial?: AttachFreeTrial | null | undefined; @@ -320,42 +186,11 @@ export type RequiredAction = { */ export type AttachResponse = { customerId: string; - entityId?: string | undefined; invoice?: AttachInvoice | undefined; paymentUrl: string | null; requiredAction?: RequiredAction | undefined; }; -/** @internal */ -export type AttachEntityData$Outbound = { - feature_id: string; - name?: string | undefined; -}; - -/** @internal */ -export const AttachEntityData$outboundSchema: z.ZodMiniType< - AttachEntityData$Outbound, - AttachEntityData -> = z.pipe( - z.object({ - featureId: z.string(), - name: z.optional(z.string()), - }), - z.transform((v) => { - return remap$(v, { - featureId: "feature_id", - }); - }), -); - -export function attachEntityDataToJSON( - attachEntityData: AttachEntityData, -): string { - return JSON.stringify( - AttachEntityData$outboundSchema.parse(attachEntityData), - ); -} - /** @internal */ export type Options$Outbound = { feature_id: string; @@ -384,9 +219,9 @@ export function optionsToJSON(options: Options): string { } /** @internal */ -export const FreeTrialDuration$outboundSchema: z.ZodMiniEnum< - typeof FreeTrialDuration -> = z.enum(FreeTrialDuration); +export const Duration$outboundSchema: z.ZodMiniEnum = z.enum( + Duration, +); /** @internal */ export type AttachFreeTrial$Outbound = { @@ -402,7 +237,7 @@ export const AttachFreeTrial$outboundSchema: z.ZodMiniType< > = z.pipe( z.object({ length: z.number(), - duration: FreeTrialDuration$outboundSchema, + duration: Duration$outboundSchema, cardRequired: z._default(z.boolean(), true), }), z.transform((v) => { @@ -422,107 +257,6 @@ export function attachFreeTrialToJSON( export const AttachType$outboundSchema: z.ZodMiniEnum = z .enum(AttachType); -/** @internal */ -export const FeatureType$outboundSchema: z.ZodMiniEnum = z - .enum(FeatureType); - -/** @internal */ -export const AttachFeatureType$outboundSchema: z.ZodMiniEnum< - typeof AttachFeatureType -> = z.enum(AttachFeatureType); - -/** @internal */ -export type AttachFeatureDisplay$Outbound = { - singular: string; - plural: string; -}; - -/** @internal */ -export const AttachFeatureDisplay$outboundSchema: z.ZodMiniType< - AttachFeatureDisplay$Outbound, - AttachFeatureDisplay -> = z.object({ - singular: z.string(), - plural: z.string(), -}); - -export function attachFeatureDisplayToJSON( - attachFeatureDisplay: AttachFeatureDisplay, -): string { - return JSON.stringify( - AttachFeatureDisplay$outboundSchema.parse(attachFeatureDisplay), - ); -} - -/** @internal */ -export type AttachCreditSchema$Outbound = { - metered_feature_id: string; - credit_cost: number; -}; - -/** @internal */ -export const AttachCreditSchema$outboundSchema: z.ZodMiniType< - AttachCreditSchema$Outbound, - AttachCreditSchema -> = z.pipe( - z.object({ - meteredFeatureId: z.string(), - creditCost: z.number(), - }), - z.transform((v) => { - return remap$(v, { - meteredFeatureId: "metered_feature_id", - creditCost: "credit_cost", - }); - }), -); - -export function attachCreditSchemaToJSON( - attachCreditSchema: AttachCreditSchema, -): string { - return JSON.stringify( - AttachCreditSchema$outboundSchema.parse(attachCreditSchema), - ); -} - -/** @internal */ -export type AttachFeature$Outbound = { - id: string; - name?: string | null | undefined; - type: string; - display?: AttachFeatureDisplay$Outbound | null | undefined; - credit_schema?: Array | null | undefined; - archived?: boolean | null | undefined; -}; - -/** @internal */ -export const AttachFeature$outboundSchema: z.ZodMiniType< - AttachFeature$Outbound, - AttachFeature -> = z.pipe( - z.object({ - id: z.string(), - name: z.optional(z.nullable(z.string())), - type: AttachFeatureType$outboundSchema, - display: z.optional( - z.nullable(z.lazy(() => AttachFeatureDisplay$outboundSchema)), - ), - creditSchema: z.optional( - z.nullable(z.array(z.lazy(() => AttachCreditSchema$outboundSchema))), - ), - archived: z.optional(z.nullable(z.boolean())), - }), - z.transform((v) => { - return remap$(v, { - creditSchema: "credit_schema", - }); - }), -); - -export function attachFeatureToJSON(attachFeature: AttachFeature): string { - return JSON.stringify(AttachFeature$outboundSchema.parse(attachFeature)); -} - /** @internal */ export type IncludedUsage$Outbound = number | string; @@ -575,104 +309,10 @@ export function tiersToJSON(tiers: Tiers): string { return JSON.stringify(Tiers$outboundSchema.parse(tiers)); } -/** @internal */ -export type AttachDisplay$Outbound = { - primary_text: string; - secondary_text?: string | null | undefined; -}; - -/** @internal */ -export const AttachDisplay$outboundSchema: z.ZodMiniType< - AttachDisplay$Outbound, - AttachDisplay -> = z.pipe( - z.object({ - primaryText: z.string(), - secondaryText: z.optional(z.nullable(z.string())), - }), - z.transform((v) => { - return remap$(v, { - primaryText: "primary_text", - secondaryText: "secondary_text", - }); - }), -); - -export function attachDisplayToJSON(attachDisplay: AttachDisplay): string { - return JSON.stringify(AttachDisplay$outboundSchema.parse(attachDisplay)); -} - -/** @internal */ -export const AttachOnIncrease$outboundSchema: z.ZodMiniEnum< - typeof AttachOnIncrease -> = z.enum(AttachOnIncrease); - -/** @internal */ -export const AttachOnDecrease$outboundSchema: z.ZodMiniEnum< - typeof AttachOnDecrease -> = z.enum(AttachOnDecrease); - -/** @internal */ -export const RolloverDuration$outboundSchema: z.ZodMiniEnum< - typeof RolloverDuration -> = z.enum(RolloverDuration); - -/** @internal */ -export type AttachRollover$Outbound = { - max: number | null; - duration: string; - length: number; -}; - -/** @internal */ -export const AttachRollover$outboundSchema: z.ZodMiniType< - AttachRollover$Outbound, - AttachRollover -> = z.object({ - max: z.nullable(z.number()), - duration: z._default(RolloverDuration$outboundSchema, "month"), - length: z.number(), -}); - -export function attachRolloverToJSON(attachRollover: AttachRollover): string { - return JSON.stringify(AttachRollover$outboundSchema.parse(attachRollover)); -} - -/** @internal */ -export type Config$Outbound = { - on_increase?: string | null | undefined; - on_decrease?: string | null | undefined; - rollover?: AttachRollover$Outbound | null | undefined; -}; - -/** @internal */ -export const Config$outboundSchema: z.ZodMiniType = z - .pipe( - z.object({ - onIncrease: z.optional(z.nullable(AttachOnIncrease$outboundSchema)), - onDecrease: z.optional(z.nullable(AttachOnDecrease$outboundSchema)), - rollover: z.optional( - z.nullable(z.lazy(() => AttachRollover$outboundSchema)), - ), - }), - z.transform((v) => { - return remap$(v, { - onIncrease: "on_increase", - onDecrease: "on_decrease", - }); - }), - ); - -export function configToJSON(config: Config): string { - return JSON.stringify(Config$outboundSchema.parse(config)); -} - /** @internal */ export type AttachItem$Outbound = { type?: string | null | undefined; feature_id?: string | null | undefined; - feature_type?: string | null | undefined; - feature?: AttachFeature$Outbound | null | undefined; included_usage?: number | string | null | undefined; interval?: string | null | undefined; interval_count?: number | null | undefined; @@ -682,13 +322,6 @@ export type AttachItem$Outbound = { tiers?: Array | null | undefined; billing_units?: number | null | undefined; reset_usage_when_enabled?: boolean | null | undefined; - display?: AttachDisplay$Outbound | null | undefined; - usage_limit?: number | null | undefined; - config?: Config$Outbound | null | undefined; - created_at?: number | null | undefined; - entitlement_id?: string | null | undefined; - price_id?: string | null | undefined; - price_config?: any | null | undefined; }; /** @internal */ @@ -699,8 +332,6 @@ export const AttachItem$outboundSchema: z.ZodMiniType< z.object({ type: z.optional(z.nullable(AttachType$outboundSchema)), featureId: z.optional(z.nullable(z.string())), - featureType: z.optional(z.nullable(FeatureType$outboundSchema)), - feature: z.optional(z.nullable(z.lazy(() => AttachFeature$outboundSchema))), includedUsage: z.optional(z.nullable(smartUnion([z.number(), z.string()]))), interval: z.optional(z.nullable(AttachInterval$outboundSchema)), intervalCount: z.optional(z.nullable(z.number())), @@ -710,29 +341,16 @@ export const AttachItem$outboundSchema: z.ZodMiniType< tiers: z.optional(z.nullable(z.array(z.lazy(() => Tiers$outboundSchema)))), billingUnits: z.optional(z.nullable(z.number())), resetUsageWhenEnabled: z.optional(z.nullable(z.boolean())), - display: z.optional(z.nullable(z.lazy(() => AttachDisplay$outboundSchema))), - usageLimit: z.optional(z.nullable(z.number())), - config: z.optional(z.nullable(z.lazy(() => Config$outboundSchema))), - createdAt: z.optional(z.nullable(z.number())), - entitlementId: z.optional(z.nullable(z.string())), - priceId: z.optional(z.nullable(z.string())), - priceConfig: z.optional(z.nullable(z.any())), }), z.transform((v) => { return remap$(v, { featureId: "feature_id", - featureType: "feature_type", includedUsage: "included_usage", intervalCount: "interval_count", entityFeatureId: "entity_feature_id", usageModel: "usage_model", billingUnits: "billing_units", resetUsageWhenEnabled: "reset_usage_when_enabled", - usageLimit: "usage_limit", - createdAt: "created_at", - entitlementId: "entitlement_id", - priceId: "price_id", - priceConfig: "price_config", }); }), ); @@ -756,8 +374,6 @@ export const BillingBehavior$outboundSchema: z.ZodMiniEnum< /** @internal */ export type AttachRequest$Outbound = { - entity_id?: string | null | undefined; - entity_data?: AttachEntityData$Outbound | undefined; options?: Array | null | undefined; version?: number | undefined; free_trial?: AttachFreeTrial$Outbound | null | undefined; @@ -780,8 +396,6 @@ export const AttachRequest$outboundSchema: z.ZodMiniType< AttachRequest > = z.pipe( z.object({ - entityId: z.optional(z.nullable(z.string())), - entityData: z.optional(z.lazy(() => AttachEntityData$outboundSchema)), options: z.optional( z.nullable(z.array(z.lazy(() => Options$outboundSchema))), ), @@ -803,8 +417,6 @@ export const AttachRequest$outboundSchema: z.ZodMiniType< }), z.transform((v) => { return remap$(v, { - entityId: "entity_id", - entityData: "entity_data", freeTrial: "free_trial", productId: "product_id", enableProductImmediately: "enable_product_immediately", @@ -883,7 +495,6 @@ export const AttachResponse$inboundSchema: z.ZodMiniType< > = z.pipe( z.object({ customer_id: types.string(), - entity_id: types.optional(types.string()), invoice: types.optional(z.lazy(() => AttachInvoice$inboundSchema)), payment_url: types.nullable(types.string()), required_action: types.optional(z.lazy(() => RequiredAction$inboundSchema)), @@ -891,7 +502,6 @@ export const AttachResponse$inboundSchema: z.ZodMiniType< z.transform((v) => { return remap$(v, { "customer_id": "customerId", - "entity_id": "entityId", "payment_url": "paymentUrl", "required_action": "requiredAction", }); diff --git a/packages/sdk/src/models/customer.ts b/packages/sdk/src/models/customer.ts index 6edbd6a49..036a13105 100644 --- a/packages/sdk/src/models/customer.ts +++ b/packages/sdk/src/models/customer.ts @@ -13,10 +13,16 @@ import { smartUnion } from "../types/smart-union.js"; import { Plan, Plan$inboundSchema } from "./plan.js"; import { SDKValidationError } from "./sdk-validation-error.js"; +/** + * The environment this customer was created in. + */ export const CustomerEnv = { Sandbox: "sandbox", Live: "live", } as const; +/** + * The environment this customer was created in. + */ export type CustomerEnv = OpenEnum; export const Status = { @@ -50,34 +56,6 @@ export type Purchase = { quantity: number; }; -export const BalancesType = { - Boolean: "boolean", - Metered: "metered", - CreditSystem: "credit_system", -} as const; -export type BalancesType = OpenEnum; - -export type CustomerCreditSchema = { - meteredFeatureId: string; - creditCost: number; -}; - -export type CustomerDisplay = { - singular?: string | null | undefined; - plural?: string | null | undefined; -}; - -export type CustomerFeature = { - id: string; - name: string; - type: BalancesType; - consumable: boolean; - eventNames?: Array | undefined; - creditSchema?: Array | undefined; - display?: CustomerDisplay | undefined; - archived: boolean; -}; - export const CustomerIntervalEnum = { OneOff: "one_off", Minute: "minute", @@ -121,7 +99,6 @@ export type CustomerPrice = { }; export type Breakdown = { - id: string; planId: string | null; includedGrant: number; prepaidGrant: number; @@ -140,7 +117,6 @@ export type CustomerRollover = { export type Balances = { featureId: string; - feature?: CustomerFeature | undefined; granted: number; remaining: number; usage: number; @@ -173,10 +149,6 @@ export type Invoice = { * The currency code for the invoice */ currency: string; - /** - * Timestamp when the invoice was created - */ - createdAt: number; /** * URL to the Stripe-hosted invoice page */ @@ -196,11 +168,6 @@ export const EntityEnv = { export type EntityEnv = OpenEnum; export type Entity = { - autumnId?: string | undefined; - /** - * The unique identifier of the entity - */ - id: string | null; /** * The name of the entity */ @@ -213,10 +180,6 @@ export type Entity = { * The feature ID this entity belongs to */ featureId?: string | null | undefined; - /** - * Unix timestamp when the entity was created - */ - createdAt: number; /** * The environment (sandbox/live) */ @@ -232,7 +195,7 @@ export type TrialsUsed = { /** * The type of reward */ -export const RewardsType = { +export const Type = { PercentageDiscount: "percentage_discount", FixedDiscount: "fixed_discount", FreeProduct: "free_product", @@ -241,7 +204,7 @@ export const RewardsType = { /** * The type of reward */ -export type RewardsType = OpenEnum; +export type Type = OpenEnum; /** * How long the discount lasts @@ -257,10 +220,6 @@ export const CustomerDurationType = { export type CustomerDurationType = OpenEnum; export type Discount = { - /** - * The unique identifier for this discount - */ - id: string; /** * The name of the discount or coupon */ @@ -268,7 +227,7 @@ export type Discount = { /** * The type of reward */ - type: RewardsType; + type: Type; /** * The discount value (percentage or fixed amount) */ @@ -311,7 +270,6 @@ export type Rewards = { }; export type ReferralCustomer = { - id: string; name?: string | null | undefined; email?: string | null | undefined; }; @@ -320,19 +278,36 @@ export type Referral = { programId: string; customer: ReferralCustomer; rewardApplied: boolean; - createdAt: number; }; export type Customer = { - autumnId?: string | undefined; - id: string | null; + /** + * The name of the customer. + */ name: string | null; + /** + * The email address of the customer. + */ email: string | null; - createdAt: number; + /** + * A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID. + */ fingerprint: string | null; + /** + * Stripe customer ID. + */ stripeId: string | null; + /** + * The environment this customer was created in. + */ env: CustomerEnv; + /** + * The metadata for the customer. + */ metadata: { [k: string]: any }; + /** + * Whether to send email receipts to the customer. + */ sendEmailReceipts: boolean; subscriptions: Array; purchases: Array; @@ -425,91 +400,6 @@ export function purchaseFromJSON( ); } -/** @internal */ -export const BalancesType$inboundSchema: z.ZodMiniType = - openEnums.inboundSchema(BalancesType); - -/** @internal */ -export const CustomerCreditSchema$inboundSchema: z.ZodMiniType< - CustomerCreditSchema, - unknown -> = z.pipe( - z.object({ - metered_feature_id: types.string(), - credit_cost: types.number(), - }), - z.transform((v) => { - return remap$(v, { - "metered_feature_id": "meteredFeatureId", - "credit_cost": "creditCost", - }); - }), -); - -export function customerCreditSchemaFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => CustomerCreditSchema$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'CustomerCreditSchema' from JSON`, - ); -} - -/** @internal */ -export const CustomerDisplay$inboundSchema: z.ZodMiniType< - CustomerDisplay, - unknown -> = z.object({ - singular: z.optional(z.nullable(types.string())), - plural: z.optional(z.nullable(types.string())), -}); - -export function customerDisplayFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => CustomerDisplay$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'CustomerDisplay' from JSON`, - ); -} - -/** @internal */ -export const CustomerFeature$inboundSchema: z.ZodMiniType< - CustomerFeature, - unknown -> = z.pipe( - z.object({ - id: types.string(), - name: types.string(), - type: BalancesType$inboundSchema, - consumable: types.boolean(), - event_names: types.optional(z.array(types.string())), - credit_schema: types.optional( - z.array(z.lazy(() => CustomerCreditSchema$inboundSchema)), - ), - display: types.optional(z.lazy(() => CustomerDisplay$inboundSchema)), - archived: types.boolean(), - }), - z.transform((v) => { - return remap$(v, { - "event_names": "eventNames", - "credit_schema": "creditSchema", - }); - }), -); - -export function customerFeatureFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => CustomerFeature$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'CustomerFeature' from JSON`, - ); -} - /** @internal */ export const CustomerIntervalEnum$inboundSchema: z.ZodMiniType< CustomerIntervalEnum, @@ -630,7 +520,6 @@ export function customerPriceFromJSON( export const Breakdown$inboundSchema: z.ZodMiniType = z .pipe( z.object({ - id: z._default(types.string(), ""), plan_id: types.nullable(types.string()), included_grant: types.number(), prepaid_grant: types.number(), @@ -691,7 +580,6 @@ export function customerRolloverFromJSON( export const Balances$inboundSchema: z.ZodMiniType = z.pipe( z.object({ feature_id: types.string(), - feature: types.optional(z.lazy(() => CustomerFeature$inboundSchema)), granted: types.number(), remaining: types.number(), usage: types.number(), @@ -732,14 +620,12 @@ export const Invoice$inboundSchema: z.ZodMiniType = z.pipe( status: types.string(), total: types.number(), currency: types.string(), - created_at: types.number(), hosted_invoice_url: z.optional(z.nullable(types.string())), }), z.transform((v) => { return remap$(v, { "plan_ids": "planIds", "stripe_id": "stripeId", - "created_at": "createdAt", "hosted_invoice_url": "hostedInvoiceUrl", }); }), @@ -762,20 +648,15 @@ export const EntityEnv$inboundSchema: z.ZodMiniType = /** @internal */ export const Entity$inboundSchema: z.ZodMiniType = z.pipe( z.object({ - autumn_id: types.optional(types.string()), - id: types.nullable(types.string()), name: types.nullable(types.string()), customer_id: z.optional(z.nullable(types.string())), feature_id: z.optional(z.nullable(types.string())), - created_at: types.number(), env: EntityEnv$inboundSchema, }), z.transform((v) => { return remap$(v, { - "autumn_id": "autumnId", "customer_id": "customerId", "feature_id": "featureId", - "created_at": "createdAt", }); }), ); @@ -817,8 +698,8 @@ export function trialsUsedFromJSON( } /** @internal */ -export const RewardsType$inboundSchema: z.ZodMiniType = - openEnums.inboundSchema(RewardsType); +export const Type$inboundSchema: z.ZodMiniType = openEnums + .inboundSchema(Type); /** @internal */ export const CustomerDurationType$inboundSchema: z.ZodMiniType< @@ -829,9 +710,8 @@ export const CustomerDurationType$inboundSchema: z.ZodMiniType< /** @internal */ export const Discount$inboundSchema: z.ZodMiniType = z.pipe( z.object({ - id: types.string(), name: types.string(), - type: RewardsType$inboundSchema, + type: Type$inboundSchema, discount_value: types.number(), duration_type: CustomerDurationType$inboundSchema, duration_value: z.optional(z.nullable(types.number())), @@ -882,7 +762,6 @@ export const ReferralCustomer$inboundSchema: z.ZodMiniType< ReferralCustomer, unknown > = z.object({ - id: types.string(), name: z.optional(z.nullable(types.string())), email: z.optional(z.nullable(types.string())), }); @@ -903,13 +782,11 @@ export const Referral$inboundSchema: z.ZodMiniType = z.pipe( program_id: types.string(), customer: z.lazy(() => ReferralCustomer$inboundSchema), reward_applied: types.boolean(), - created_at: types.number(), }), z.transform((v) => { return remap$(v, { "program_id": "programId", "reward_applied": "rewardApplied", - "created_at": "createdAt", }); }), ); @@ -927,11 +804,8 @@ export function referralFromJSON( /** @internal */ export const Customer$inboundSchema: z.ZodMiniType = z.pipe( z.object({ - autumn_id: types.optional(types.string()), - id: types.nullable(types.string()), name: types.nullable(types.string()), email: types.nullable(types.string()), - created_at: types.number(), fingerprint: types.nullable(types.string()), stripe_id: types.nullable(types.string()), env: CustomerEnv$inboundSchema, @@ -951,8 +825,6 @@ export const Customer$inboundSchema: z.ZodMiniType = z.pipe( }), z.transform((v) => { return remap$(v, { - "autumn_id": "autumnId", - "created_at": "createdAt", "stripe_id": "stripeId", "send_email_receipts": "sendEmailReceipts", "trials_used": "trialsUsed", diff --git a/packages/sdk/src/models/get-or-create-op.ts b/packages/sdk/src/models/get-or-create-op.ts index 7682293da..6adb75311 100644 --- a/packages/sdk/src/models/get-or-create-op.ts +++ b/packages/sdk/src/models/get-or-create-op.ts @@ -13,39 +13,6 @@ export type GetOrCreateGlobals = { xApiVersion?: string | undefined; }; -export type Vercel = { - installationId: string; - accessToken: string; - accountId: string; - customPaymentMethodId?: string | undefined; -}; - -export type Processors = { - vercel?: Vercel | undefined; -}; - -export type InternalOptions = { - /** - * The group of products to attach to the customer - */ - defaultGroup?: string | undefined; - /** - * Whether to disable default products - */ - disableDefaults?: boolean | undefined; -}; - -export type GetOrCreateEntityData = { - /** - * The feature ID that this entity is associated with - */ - featureId: string; - /** - * Name of the entity - */ - name?: string | undefined; -}; - export type GetOrCreateCustomerParams = { customerId: string | null; /** @@ -76,132 +43,16 @@ export type GetOrCreateCustomerParams = { * The ID of the free plan to auto-enable for the customer */ autoEnablePlanId?: string | undefined; - /** - * External processors for the customer - */ - processors?: Processors | null | undefined; /** * Whether to send email receipts to this customer */ sendEmailReceipts?: boolean | undefined; - internalOptions?: InternalOptions | undefined; /** * Customer expand options */ expand?: Array | undefined; - entityId?: string | undefined; - entityData?: GetOrCreateEntityData | undefined; - id?: string | null | undefined; - withAutumnId?: boolean | undefined; }; -/** @internal */ -export type Vercel$Outbound = { - installation_id: string; - access_token: string; - account_id: string; - custom_payment_method_id?: string | undefined; -}; - -/** @internal */ -export const Vercel$outboundSchema: z.ZodMiniType = z - .pipe( - z.object({ - installationId: z.string(), - accessToken: z.string(), - accountId: z.string(), - customPaymentMethodId: z.optional(z.string()), - }), - z.transform((v) => { - return remap$(v, { - installationId: "installation_id", - accessToken: "access_token", - accountId: "account_id", - customPaymentMethodId: "custom_payment_method_id", - }); - }), - ); - -export function vercelToJSON(vercel: Vercel): string { - return JSON.stringify(Vercel$outboundSchema.parse(vercel)); -} - -/** @internal */ -export type Processors$Outbound = { - vercel?: Vercel$Outbound | undefined; -}; - -/** @internal */ -export const Processors$outboundSchema: z.ZodMiniType< - Processors$Outbound, - Processors -> = z.object({ - vercel: z.optional(z.lazy(() => Vercel$outboundSchema)), -}); - -export function processorsToJSON(processors: Processors): string { - return JSON.stringify(Processors$outboundSchema.parse(processors)); -} - -/** @internal */ -export type InternalOptions$Outbound = { - default_group?: string | undefined; - disable_defaults?: boolean | undefined; -}; - -/** @internal */ -export const InternalOptions$outboundSchema: z.ZodMiniType< - InternalOptions$Outbound, - InternalOptions -> = z.pipe( - z.object({ - defaultGroup: z.optional(z.string()), - disableDefaults: z.optional(z.boolean()), - }), - z.transform((v) => { - return remap$(v, { - defaultGroup: "default_group", - disableDefaults: "disable_defaults", - }); - }), -); - -export function internalOptionsToJSON( - internalOptions: InternalOptions, -): string { - return JSON.stringify(InternalOptions$outboundSchema.parse(internalOptions)); -} - -/** @internal */ -export type GetOrCreateEntityData$Outbound = { - feature_id: string; - name?: string | undefined; -}; - -/** @internal */ -export const GetOrCreateEntityData$outboundSchema: z.ZodMiniType< - GetOrCreateEntityData$Outbound, - GetOrCreateEntityData -> = z.pipe( - z.object({ - featureId: z.string(), - name: z.optional(z.string()), - }), - z.transform((v) => { - return remap$(v, { - featureId: "feature_id", - }); - }), -); - -export function getOrCreateEntityDataToJSON( - getOrCreateEntityData: GetOrCreateEntityData, -): string { - return JSON.stringify( - GetOrCreateEntityData$outboundSchema.parse(getOrCreateEntityData), - ); -} - /** @internal */ export type GetOrCreateCustomerParams$Outbound = { customer_id: string | null; @@ -212,14 +63,8 @@ export type GetOrCreateCustomerParams$Outbound = { stripe_id?: string | null | undefined; create_in_stripe?: boolean | undefined; auto_enable_plan_id?: string | undefined; - processors?: Processors$Outbound | null | undefined; send_email_receipts?: boolean | undefined; - internal_options?: InternalOptions$Outbound | undefined; expand?: Array | undefined; - entity_id?: string | undefined; - entity_data?: GetOrCreateEntityData$Outbound | undefined; - id?: string | null | undefined; - with_autumn_id: boolean; }; /** @internal */ @@ -236,14 +81,8 @@ export const GetOrCreateCustomerParams$outboundSchema: z.ZodMiniType< stripeId: z.optional(z.nullable(z.string())), createInStripe: z.optional(z.boolean()), autoEnablePlanId: z.optional(z.string()), - processors: z.optional(z.nullable(z.lazy(() => Processors$outboundSchema))), sendEmailReceipts: z.optional(z.boolean()), - internalOptions: z.optional(z.lazy(() => InternalOptions$outboundSchema)), expand: z.optional(z.array(CustomerExpand$outboundSchema)), - entityId: z.optional(z.string()), - entityData: z.optional(z.lazy(() => GetOrCreateEntityData$outboundSchema)), - id: z.optional(z.nullable(z.string())), - withAutumnId: z._default(z.boolean(), false), }), z.transform((v) => { return remap$(v, { @@ -252,10 +91,6 @@ export const GetOrCreateCustomerParams$outboundSchema: z.ZodMiniType< createInStripe: "create_in_stripe", autoEnablePlanId: "auto_enable_plan_id", sendEmailReceipts: "send_email_receipts", - internalOptions: "internal_options", - entityId: "entity_id", - entityData: "entity_data", - withAutumnId: "with_autumn_id", }); }), ); diff --git a/packages/sdk/src/models/plan.ts b/packages/sdk/src/models/plan.ts index e2c1491b9..1e7d7434b 100644 --- a/packages/sdk/src/models/plan.ts +++ b/packages/sdk/src/models/plan.ts @@ -22,80 +22,10 @@ export const PriceInterval = { } as const; export type PriceInterval = OpenEnum; -export type PriceDisplay = { - primaryText: string; - secondaryText?: string | undefined; -}; - export type PlanPrice = { amount: number; interval: PriceInterval; intervalCount?: number | undefined; - display?: PriceDisplay | undefined; -}; - -/** - * The type of the feature - */ -export const PlanType = { - Static: "static", - Boolean: "boolean", - SingleUse: "single_use", - ContinuousUse: "continuous_use", - CreditSystem: "credit_system", -} as const; -/** - * The type of the feature - */ -export type PlanType = OpenEnum; - -export type PlanFeatureDisplay = { - /** - * The singular display name for the feature. - */ - singular: string; - /** - * The plural display name for the feature. - */ - plural: string; -}; - -export type PlanCreditSchema = { - /** - * The ID of the metered feature (should be a single_use feature). - */ - meteredFeatureId: string; - /** - * The credit cost of the metered feature. - */ - creditCost: number; -}; - -export type PlanFeature = { - /** - * The ID of the feature, used to refer to it in other API calls like /track or /check. - */ - id: string; - /** - * The name of the feature. - */ - name?: string | null | undefined; - /** - * The type of the feature - */ - type: PlanType; - /** - * Singular and plural display names for the feature. - */ - display?: PlanFeatureDisplay | null | undefined; - /** - * Credit cost schema for credit system features. - */ - creditSchema?: Array | null | undefined; - /** - * Whether or not the feature is archived. - */ - archived?: boolean | null | undefined; }; export const PlanResetInterval = { @@ -149,11 +79,6 @@ export type ItemPrice = { maxPurchase: number | null; }; -export type PlanItemDisplay = { - primaryText: string; - secondaryText?: string | undefined; -}; - export const ExpiryDurationType = { Month: "month", Forever: "forever", @@ -190,12 +115,10 @@ export type Proration = { export type Item = { featureId: string; - feature?: PlanFeature | undefined; included: number; unlimited: boolean; reset: PlanReset | null; price: ItemPrice | null; - display?: PlanItemDisplay | undefined; rollover?: PlanRollover | undefined; proration?: Proration | undefined; }; @@ -238,7 +161,6 @@ export type CustomerEligibility = { }; export type Plan = { - id: string; name: string; description: string | null; group: string | null; @@ -248,7 +170,6 @@ export type Plan = { price: PlanPrice | null; items: Array; freeTrial?: FreeTrial | undefined; - createdAt: number; env: PlanEnv; archived: boolean; baseVariantId: string | null; @@ -261,31 +182,6 @@ export const PriceInterval$inboundSchema: z.ZodMiniType< unknown > = openEnums.inboundSchema(PriceInterval); -/** @internal */ -export const PriceDisplay$inboundSchema: z.ZodMiniType = - z.pipe( - z.object({ - primary_text: types.string(), - secondary_text: types.optional(types.string()), - }), - z.transform((v) => { - return remap$(v, { - "primary_text": "primaryText", - "secondary_text": "secondaryText", - }); - }), - ); - -export function priceDisplayFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => PriceDisplay$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'PriceDisplay' from JSON`, - ); -} - /** @internal */ export const PlanPrice$inboundSchema: z.ZodMiniType = z .pipe( @@ -293,7 +189,6 @@ export const PlanPrice$inboundSchema: z.ZodMiniType = z amount: types.number(), interval: PriceInterval$inboundSchema, interval_count: types.optional(types.number()), - display: types.optional(z.lazy(() => PriceDisplay$inboundSchema)), }), z.transform((v) => { return remap$(v, { @@ -312,88 +207,6 @@ export function planPriceFromJSON( ); } -/** @internal */ -export const PlanType$inboundSchema: z.ZodMiniType = - openEnums.inboundSchema(PlanType); - -/** @internal */ -export const PlanFeatureDisplay$inboundSchema: z.ZodMiniType< - PlanFeatureDisplay, - unknown -> = z.object({ - singular: types.string(), - plural: types.string(), -}); - -export function planFeatureDisplayFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => PlanFeatureDisplay$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'PlanFeatureDisplay' from JSON`, - ); -} - -/** @internal */ -export const PlanCreditSchema$inboundSchema: z.ZodMiniType< - PlanCreditSchema, - unknown -> = z.pipe( - z.object({ - metered_feature_id: types.string(), - credit_cost: types.number(), - }), - z.transform((v) => { - return remap$(v, { - "metered_feature_id": "meteredFeatureId", - "credit_cost": "creditCost", - }); - }), -); - -export function planCreditSchemaFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => PlanCreditSchema$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'PlanCreditSchema' from JSON`, - ); -} - -/** @internal */ -export const PlanFeature$inboundSchema: z.ZodMiniType = z - .pipe( - z.object({ - id: types.string(), - name: z.optional(z.nullable(types.string())), - type: PlanType$inboundSchema, - display: z.optional( - z.nullable(z.lazy(() => PlanFeatureDisplay$inboundSchema)), - ), - credit_schema: z.optional( - z.nullable(z.array(z.lazy(() => PlanCreditSchema$inboundSchema))), - ), - archived: z.optional(z.nullable(types.boolean())), - }), - z.transform((v) => { - return remap$(v, { - "credit_schema": "creditSchema", - }); - }), - ); - -export function planFeatureFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => PlanFeature$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'PlanFeature' from JSON`, - ); -} - /** @internal */ export const PlanResetInterval$inboundSchema: z.ZodMiniType< PlanResetInterval, @@ -501,33 +314,6 @@ export function itemPriceFromJSON( ); } -/** @internal */ -export const PlanItemDisplay$inboundSchema: z.ZodMiniType< - PlanItemDisplay, - unknown -> = z.pipe( - z.object({ - primary_text: types.string(), - secondary_text: types.optional(types.string()), - }), - z.transform((v) => { - return remap$(v, { - "primary_text": "primaryText", - "secondary_text": "secondaryText", - }); - }), -); - -export function planItemDisplayFromJSON( - jsonString: string, -): SafeParseResult { - return safeParse( - jsonString, - (x) => PlanItemDisplay$inboundSchema.parse(JSON.parse(x)), - `Failed to parse 'PlanItemDisplay' from JSON`, - ); -} - /** @internal */ export const ExpiryDurationType$inboundSchema: z.ZodMiniType< ExpiryDurationType, @@ -597,12 +383,10 @@ export function prorationFromJSON( export const Item$inboundSchema: z.ZodMiniType = z.pipe( z.object({ feature_id: types.string(), - feature: types.optional(z.lazy(() => PlanFeature$inboundSchema)), included: types.number(), unlimited: types.boolean(), reset: types.nullable(z.lazy(() => PlanReset$inboundSchema)), price: types.nullable(z.lazy(() => ItemPrice$inboundSchema)), - display: types.optional(z.lazy(() => PlanItemDisplay$inboundSchema)), rollover: types.optional(z.lazy(() => PlanRollover$inboundSchema)), proration: types.optional(z.lazy(() => Proration$inboundSchema)), }), @@ -693,7 +477,6 @@ export function customerEligibilityFromJSON( /** @internal */ export const Plan$inboundSchema: z.ZodMiniType = z.pipe( z.object({ - id: types.string(), name: types.string(), description: types.nullable(types.string()), group: types.nullable(types.string()), @@ -703,7 +486,6 @@ export const Plan$inboundSchema: z.ZodMiniType = z.pipe( price: types.nullable(z.lazy(() => PlanPrice$inboundSchema)), items: z.array(z.lazy(() => Item$inboundSchema)), free_trial: types.optional(z.lazy(() => FreeTrial$inboundSchema)), - created_at: types.number(), env: PlanEnv$inboundSchema, archived: types.boolean(), base_variant_id: types.nullable(types.string()), @@ -716,7 +498,6 @@ export const Plan$inboundSchema: z.ZodMiniType = z.pipe( "add_on": "addOn", "auto_enable": "autoEnable", "free_trial": "freeTrial", - "created_at": "createdAt", "base_variant_id": "baseVariantId", "customer_eligibility": "customerEligibility", }); diff --git a/shared/api/_openapi/utils/apiReferenceGenerator/generateFields.ts b/shared/api/_openapi/utils/apiReferenceGenerator/generateFields.ts new file mode 100644 index 000000000..499bfd605 --- /dev/null +++ b/shared/api/_openapi/utils/apiReferenceGenerator/generateFields.ts @@ -0,0 +1,254 @@ +import type { ParsedOperation, SchemaField } from "./parseOpenApi.js"; + +/** + * Generate the MDX content for request body and response fields. + */ +export function generateFields({ + operation, +}: { + operation: ParsedOperation; +}): string { + const sections: string[] = []; + + // Generate request body parameters + if (operation.requestBody && operation.requestBody.length > 0) { + sections.push("### Body Parameters\n"); + sections.push( + generateParamFields({ fields: operation.requestBody, indent: 0 }), + ); + } + + // Generate response fields (use 200 or 201 response) + const responseStatusCode = operation.responses?.["200"] + ? "200" + : operation.responses?.["201"] + ? "201" + : null; + const responseFields = responseStatusCode + ? operation.responses?.[responseStatusCode] + : null; + + if (responseFields && responseFields.length > 0) { + sections.push("\n### Response\n"); + sections.push( + generateResponseFields({ fields: responseFields, indent: 0 }), + ); + } + + // Generate DynamicResponseExample with the actual example from OpenAPI spec + // This example is already in snake_case - the component will convert to camelCase when needed + const responseExample = responseStatusCode + ? operation.responseExamples?.[responseStatusCode] + : null; + + if (responseExample && typeof responseExample === "object") { + sections.push( + generateResponseExampleComponent({ + json: responseExample, + statusCode: responseStatusCode, + }), + ); + } + + return sections.join("\n"); +} + +/** + * Generate a ResponseExample with markdown code block. + * Uses Mintlify's ResponseExample component which pins content to the sidebar. + */ +function generateResponseExampleMarkdown({ + json, + statusCode, +}: { + json: unknown; + statusCode: string; +}): string { + // Format the JSON with proper indentation + const jsonString = JSON.stringify(json, null, 2); + + // Generate markdown ResponseExample block + // The triple backticks create a code block inside ResponseExample + return ` + +\`\`\`json ${statusCode} +${jsonString} +\`\`\` + +`; +} + +/** + * Generate DynamicParamField components for request body fields. + */ +function generateParamFields({ + fields, + indent, +}: { + fields: SchemaField[]; + indent: number; +}): string { + const indentStr = " ".repeat(indent); + const lines: string[] = []; + + for (const field of fields) { + const props = buildFieldProps({ + name: field.name, + type: field.type, + required: field.required, + enumValues: field.enumValues, + }); + + const description = escapeDescription(field.description); + const hasChildren = field.children && field.children.length > 0; + + if (hasChildren) { + // Field with nested children + lines.push(`${indentStr}`); + if (description) { + lines.push(`${indentStr} ${description}`); + } + lines.push(`${indentStr} `); + lines.push( + generateParamFields({ fields: field.children!, indent: indent + 2 }), + ); + lines.push(`${indentStr} `); + lines.push(`${indentStr}\n`); + } else { + // Simple field + if (description) { + lines.push(`${indentStr}`); + lines.push(`${indentStr} ${description}`); + lines.push(`${indentStr}\n`); + } else { + lines.push(`${indentStr}\n`); + } + } + } + + return lines.join("\n"); +} + +/** + * Generate DynamicResponseField components for response fields. + */ +function generateResponseFields({ + fields, + indent, +}: { + fields: SchemaField[]; + indent: number; +}): string { + const indentStr = " ".repeat(indent); + const lines: string[] = []; + + for (const field of fields) { + const props = buildResponseFieldProps({ + name: field.name, + type: field.type, + enumValues: field.enumValues, + }); + + const description = escapeDescription(field.description); + const hasChildren = field.children && field.children.length > 0; + + if (hasChildren) { + // Field with nested children + lines.push(`${indentStr}`); + if (description) { + lines.push(`${indentStr} ${description}`); + } + lines.push(`${indentStr} `); + lines.push( + generateResponseFields({ fields: field.children!, indent: indent + 2 }), + ); + lines.push(`${indentStr} `); + lines.push(`${indentStr}\n`); + } else { + // Simple field + if (description) { + lines.push(`${indentStr}`); + lines.push(`${indentStr} ${description}`); + lines.push(`${indentStr}\n`); + } else { + lines.push(`${indentStr}\n`); + } + } + } + + return lines.join("\n"); +} + +/** + * Build the props string for a DynamicParamField component. + */ +function buildFieldProps({ + name, + type, + required, + enumValues, +}: { + name: string; + type: string; + required: boolean; + enumValues?: string[]; +}): string { + const props: string[] = [ + `body="${name}"`, + `type="${formatType(type, enumValues)}"`, + ]; + + if (required) { + props.push("required"); + } + + return props.join(" "); +} + +/** + * Build the props string for a DynamicResponseField component. + */ +function buildResponseFieldProps({ + name, + type, + enumValues, +}: { + name: string; + type: string; + enumValues?: string[]; +}): string { + return `name="${name}" type="${formatType(type, enumValues)}"`; +} + +/** + * Format the type string, including enum values if present. + */ +function formatType(type: string, enumValues?: string[]): string { + if (enumValues && enumValues.length > 0) { + // Show enum values inline if there are few, otherwise just show "enum" + if (enumValues.length <= 5) { + return enumValues.map((v) => `'${v}'`).join(" | "); + } + return "enum"; + } + return type; +} + +/** + * Escape special characters in description for MDX. + */ +function escapeDescription(description?: string): string { + if (!description) return ""; + + return ( + description + // Escape curly braces for JSX + .replace(/\{/g, "\\{") + .replace(/\}/g, "\\}") + // Remove markdown code blocks that might cause issues + .replace(/```[\s\S]*?```/g, "") + // Normalize whitespace + .replace(/\s+/g, " ") + .trim() + ); +} diff --git a/shared/api/_openapi/utils/apiReferenceGenerator/index.ts b/shared/api/_openapi/utils/apiReferenceGenerator/index.ts new file mode 100644 index 000000000..48b1783b5 --- /dev/null +++ b/shared/api/_openapi/utils/apiReferenceGenerator/index.ts @@ -0,0 +1,82 @@ +import { existsSync, mkdirSync, writeFileSync } from "node:fs"; +import path from "node:path"; +import { generateFields } from "./generateFields.js"; +import { mergeMdx } from "./mergeMdx.js"; +import { parseOpenApi } from "./parseOpenApi.js"; + +export interface GenerateApiReferenceOptions { + openApiPath: string; + manualMdxDir: string; + outputDir: string; +} + +/** + * Generate API reference MDX files from an OpenAPI spec. + * + * For each operation in the OpenAPI spec: + * 1. Parse request body and response schemas + * 2. Generate DynamicParamField/DynamicResponseField components + * 3. Merge with manual MDX content (if exists) + * 4. Write to output directory: {outputDir}/{tag}/{operationId}.mdx + */ +export async function generateApiReference({ + openApiPath, + manualMdxDir, + outputDir, +}: GenerateApiReferenceOptions): Promise { + console.log(` Reading OpenAPI spec from: ${openApiPath}`); + + // Parse OpenAPI spec + const operations = parseOpenApi({ openApiPath }); + console.log(` Found ${operations.length} operations`); + + let generated = 0; + let skipped = 0; + + for (const operation of operations) { + const { tag, operationId } = operation; + + // Determine file paths + const manualMdxPath = path.join(manualMdxDir, tag, `${operationId}.mdx`); + const outputPath = path.join(outputDir, tag, `${operationId}.mdx`); + + // Check if output file already exists and there's no manual MDX + // In that case, skip to avoid overwriting existing content + if (existsSync(outputPath) && !existsSync(manualMdxPath)) { + skipped++; + continue; + } + + // Generate fields MDX + const generatedContent = generateFields({ operation }); + + // Skip if no content was generated + if (!generatedContent.trim()) { + skipped++; + continue; + } + + // Merge with manual MDX (if exists) + const finalMdx = mergeMdx({ + manualMdxPath, + generatedContent, + operation, + }); + + // Ensure output directory exists + mkdirSync(path.dirname(outputPath), { recursive: true }); + + // Write output file + writeFileSync(outputPath, finalMdx, "utf-8"); + generated++; + + console.log(` Generated: ${tag}/${operationId}.mdx`); + } + + console.log( + ` API reference generation complete: ${generated} generated, ${skipped} skipped`, + ); +} + +// Re-export types for consumers +export type { ParsedOperation, SchemaField } from "./parseOpenApi.js"; diff --git a/shared/api/_openapi/utils/apiReferenceGenerator/mergeMdx.ts b/shared/api/_openapi/utils/apiReferenceGenerator/mergeMdx.ts new file mode 100644 index 000000000..eea4864b5 --- /dev/null +++ b/shared/api/_openapi/utils/apiReferenceGenerator/mergeMdx.ts @@ -0,0 +1,70 @@ +import { existsSync, readFileSync } from "node:fs"; +import type { ParsedOperation } from "./parseOpenApi.js"; + +const IMPORTS = `import { DynamicParamField } from "/components/dynamic-param-field.jsx"; +import { DynamicResponseField } from "/components/dynamic-response-field.jsx"; +import { DynamicResponseExample } from "/components/dynamic-response-example.jsx";`; + +/** + * Merge manual MDX content with generated fields. + * If manual MDX exists, append generated content after it. + * If no manual MDX exists, generate minimal frontmatter + imports + generated content. + */ +export function mergeMdx({ + manualMdxPath, + generatedContent, + operation, +}: { + manualMdxPath: string; + generatedContent: string; + operation: ParsedOperation; +}): string { + if (existsSync(manualMdxPath)) { + // Read manual MDX and append generated content + const manualContent = readFileSync(manualMdxPath, "utf-8"); + + // Check if all imports already exist + const hasAllImports = + manualContent.includes("DynamicParamField") && + manualContent.includes("DynamicResponseField") && + manualContent.includes("DynamicResponseExample"); + + // If manual content has frontmatter but missing imports, add them after frontmatter + if (!hasAllImports) { + const frontmatterMatch = manualContent.match(/^---\n[\s\S]*?\n---\n/); + if (frontmatterMatch) { + const frontmatter = frontmatterMatch[0]; + const restContent = manualContent.slice(frontmatter.length).trim(); + return `${frontmatter}\n${IMPORTS}\n\n${restContent}\n\n${generatedContent}`; + } + } + + return `${manualContent.trim()}\n\n${generatedContent}`; + } + + // Generate minimal frontmatter + const title = + operation.summary ?? formatOperationIdAsTitle(operation.operationId); + const frontmatter = `--- +title: "${title}" +openapi: "openapi ${operation.method} ${operation.path}" +---`; + + return `${frontmatter}\n\n${IMPORTS}\n\n${generatedContent}`; +} + +/** + * Convert operationId to a human-readable title. + * e.g., "getOrCreate" -> "Get Or Create" + */ +function formatOperationIdAsTitle(operationId: string): string { + // Split on camelCase boundaries + const words = operationId + .replace(/([a-z])([A-Z])/g, "$1 $2") + .split(/[\s_-]+/); + + // Capitalize first letter of each word + return words + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "); +} diff --git a/shared/api/_openapi/utils/apiReferenceGenerator/parseOpenApi.ts b/shared/api/_openapi/utils/apiReferenceGenerator/parseOpenApi.ts new file mode 100644 index 000000000..35fbdb1f9 --- /dev/null +++ b/shared/api/_openapi/utils/apiReferenceGenerator/parseOpenApi.ts @@ -0,0 +1,626 @@ +import { readFileSync } from "node:fs"; +import yaml from "yaml"; + +export interface SchemaField { + name: string; + type: string; + description?: string; + required: boolean; + children?: SchemaField[]; + enumValues?: string[]; +} + +export interface ParsedOperation { + operationId: string; + tag: string; + method: string; + path: string; + summary?: string; + description?: string; + requestBody?: SchemaField[]; + responses?: { + [statusCode: string]: SchemaField[]; + }; + /** Raw response schema for generating sample JSON */ + responseSchemas?: { + [statusCode: string]: Record; + }; + /** Response examples extracted from the OpenAPI spec (already in snake_case) */ + responseExamples?: { + [statusCode: string]: unknown; + }; + /** Reference to all schemas for sample JSON generation */ + allSchemas?: Record; +} + +interface OpenApiDocument { + components?: { + schemas?: Record; + }; + paths?: Record>; +} + +/** + * Parse an OpenAPI YAML file and extract operation details. + */ +export function parseOpenApi({ + openApiPath, +}: { + openApiPath: string; +}): ParsedOperation[] { + const content = readFileSync(openApiPath, "utf-8"); + const doc = yaml.parse(content) as OpenApiDocument; + + const operations: ParsedOperation[] = []; + const schemas = doc.components?.schemas ?? {}; + + for (const [path, pathItem] of Object.entries(doc.paths ?? {})) { + for (const [method, operationObj] of Object.entries(pathItem)) { + if (method === "parameters" || method === "$ref") continue; + + const operation = operationObj as Record; + const operationId = operation.operationId as string | undefined; + const tags = operation.tags as string[] | undefined; + const tag = tags?.[0] ?? "misc"; + + if (!operationId) continue; + + const parsed: ParsedOperation = { + operationId, + tag, + method: method.toUpperCase(), + path, + summary: operation.summary as string | undefined, + description: operation.description as string | undefined, + }; + + // Parse request body + const requestBody = operation.requestBody as + | Record + | undefined; + if (requestBody) { + const content = requestBody.content as + | Record + | undefined; + const jsonContent = content?.["application/json"] as + | Record + | undefined; + const schema = jsonContent?.schema as + | Record + | undefined; + + if (schema) { + parsed.requestBody = parseSchema({ + schema, + schemas, + requiredFields: (schema.required as string[]) ?? [], + }); + } + } + + // Parse responses + const responses = operation.responses as + | Record + | undefined; + if (responses) { + parsed.responses = {}; + parsed.responseSchemas = {}; + parsed.responseExamples = {}; + + for (const [statusCode, responseObj] of Object.entries(responses)) { + const response = responseObj as Record; + const content = response.content as + | Record + | undefined; + const jsonContent = content?.["application/json"] as + | Record + | undefined; + const schema = jsonContent?.schema as + | Record + | undefined; + + if (schema) { + parsed.responses[statusCode] = parseSchema({ + schema, + schemas, + requiredFields: (schema.required as string[]) ?? [], + }); + // Store raw schema for sample JSON generation + parsed.responseSchemas[statusCode] = schema; + } + + // Extract response example (could be at content level or schema level) + const example = + jsonContent?.example ?? + jsonContent?.examples?.[0] ?? + resolveSchemaExample({ schema: schema ?? {}, schemas }); + if (example) { + parsed.responseExamples[statusCode] = example; + } + } + } + + // Store reference to all schemas for sample JSON generation + parsed.allSchemas = schemas; + + operations.push(parsed); + } + } + + return operations; +} + +/** + * Resolves an example from a schema, following $ref if needed. + */ +function resolveSchemaExample({ + schema, + schemas, +}: { + schema: Record; + schemas: Record; +}): unknown { + // Check for examples array + if ( + schema.examples && + Array.isArray(schema.examples) && + schema.examples.length > 0 + ) { + return schema.examples[0]; + } + + // Check for single example + if (schema.example !== undefined) { + return schema.example; + } + + // Follow $ref + if (schema.$ref && typeof schema.$ref === "string") { + const refName = schema.$ref.replace("#/components/schemas/", ""); + const refSchema = schemas[refName] as Record | undefined; + if (refSchema) { + return resolveSchemaExample({ schema: refSchema, schemas }); + } + } + + return undefined; +} + +/** + * Parse a schema and return a list of fields. + */ +function parseSchema({ + schema, + schemas, + requiredFields, + visited = new Set(), +}: { + schema: Record; + schemas: Record; + requiredFields: string[]; + visited?: Set; +}): SchemaField[] { + // Handle $ref + if (schema.$ref) { + const refPath = schema.$ref as string; + const refName = refPath.replace("#/components/schemas/", ""); + + // Prevent infinite recursion + if (visited.has(refName)) { + return []; + } + visited.add(refName); + + const refSchema = schemas[refName] as Record | undefined; + if (refSchema) { + return parseSchema({ + schema: refSchema, + schemas, + requiredFields: (refSchema.required as string[]) ?? [], + visited, + }); + } + return []; + } + + // Handle anyOf/oneOf (common for nullable types) + if (schema.anyOf || schema.oneOf) { + const variants = (schema.anyOf ?? schema.oneOf) as Record< + string, + unknown + >[]; + // Find the non-null variant + const nonNullVariant = variants.find( + (v) => v.type !== "null" && !v.$ref?.toString().includes("null"), + ); + if (nonNullVariant) { + return parseSchema({ + schema: nonNullVariant, + schemas, + requiredFields, + visited, + }); + } + return []; + } + + // Handle object type + if (schema.type === "object" && schema.properties) { + const properties = schema.properties as Record; + const fields: SchemaField[] = []; + + for (const [propName, propSchema] of Object.entries(properties)) { + const prop = propSchema as Record; + const field = parseField({ + name: propName, + schema: prop, + schemas, + required: requiredFields.includes(propName), + visited: new Set(visited), + }); + if (field) { + fields.push(field); + } + } + + return fields; + } + + // Handle array type - return the items as a single field + if (schema.type === "array" && schema.items) { + const items = schema.items as Record; + const itemFields = parseSchema({ + schema: items, + schemas, + requiredFields: (items.required as string[]) ?? [], + visited, + }); + + // Return array items as children of a virtual "items" field + if (itemFields.length > 0) { + return [ + { + name: "items", + type: "object", + description: "Array item", + required: false, + children: itemFields, + }, + ]; + } + } + + return []; +} + +/** + * Parse a single field from a schema property. + */ +function parseField({ + name, + schema, + schemas, + required, + visited, +}: { + name: string; + schema: Record; + schemas: Record; + required: boolean; + visited: Set; +}): SchemaField | null { + let type = resolveType(schema, schemas); + let description = schema.description as string | undefined; + let children: SchemaField[] | undefined; + let enumValues: string[] | undefined; + + // Handle $ref + if (schema.$ref) { + const refPath = schema.$ref as string; + const refName = refPath.replace("#/components/schemas/", ""); + + if (visited.has(refName)) { + return { name, type: refName, description, required }; + } + visited.add(refName); + + const refSchema = schemas[refName] as Record | undefined; + if (refSchema) { + type = resolveType(refSchema, schemas); + description = + description ?? (refSchema.description as string | undefined); + + // Check for enum + if (refSchema.enum) { + enumValues = refSchema.enum as string[]; + } + + // Check for nested object + if (refSchema.type === "object" && refSchema.properties) { + children = parseSchema({ + schema: refSchema, + schemas, + requiredFields: (refSchema.required as string[]) ?? [], + visited, + }); + } + } + } + + // Handle anyOf/oneOf (nullable types) + if (schema.anyOf || schema.oneOf) { + const variants = (schema.anyOf ?? schema.oneOf) as Record< + string, + unknown + >[]; + const hasNull = variants.some((v) => v.type === "null"); + const nonNullVariant = variants.find((v) => v.type !== "null"); + + if (nonNullVariant) { + const innerField = parseField({ + name, + schema: nonNullVariant, + schemas, + required, + visited, + }); + + if (innerField) { + // Append "| null" if nullable + if (hasNull) { + innerField.type = `${innerField.type} | null`; + } + // Preserve description from parent schema if inner doesn't have one + if (!innerField.description && description) { + innerField.description = description; + } + return innerField; + } + } + + return { + name, + type: hasNull ? "any | null" : "any", + description, + required, + }; + } + + // Handle enum + if (schema.enum) { + enumValues = schema.enum as string[]; + } + + // Handle nested object + if (schema.type === "object" && schema.properties) { + children = parseSchema({ + schema, + schemas, + requiredFields: (schema.required as string[]) ?? [], + visited, + }); + } + + // Handle array + if (schema.type === "array" && schema.items) { + const items = schema.items as Record; + const itemType = resolveType(items, schemas); + type = `${itemType}[]`; + + // Check if array items have properties + if (items.type === "object" && items.properties) { + children = parseSchema({ + schema: items, + schemas, + requiredFields: (items.required as string[]) ?? [], + visited, + }); + } else if (items.$ref) { + const refPath = items.$ref as string; + const refName = refPath.replace("#/components/schemas/", ""); + const refSchema = schemas[refName] as Record | undefined; + + if (refSchema && refSchema.type === "object" && refSchema.properties) { + children = parseSchema({ + schema: refSchema, + schemas, + requiredFields: (refSchema.required as string[]) ?? [], + visited: new Set(visited), + }); + } + } + } + + return { + name, + type, + description, + required, + children, + enumValues, + }; +} + +/** + * Resolve the type string for a schema. + */ +function resolveType( + schema: Record, + schemas: Record, +): string { + if (schema.$ref) { + const refPath = schema.$ref as string; + const refName = refPath.replace("#/components/schemas/", ""); + const refSchema = schemas[refName] as Record | undefined; + + if (refSchema) { + // If it's an enum, return "enum" + if (refSchema.enum) { + return "enum"; + } + // Otherwise return the underlying type + return resolveType(refSchema, schemas); + } + return refName; + } + + if (schema.anyOf || schema.oneOf) { + const variants = (schema.anyOf ?? schema.oneOf) as Record< + string, + unknown + >[]; + const nonNullVariant = variants.find((v) => v.type !== "null"); + if (nonNullVariant) { + return resolveType(nonNullVariant, schemas); + } + return "any"; + } + + if (schema.type === "array") { + const items = schema.items as Record | undefined; + if (items) { + return `${resolveType(items, schemas)}[]`; + } + return "array"; + } + + return (schema.type as string) ?? "any"; +} + +/** + * Generate a sample JSON object from a schema for documentation examples. + * Returns a simplified sample that shows the structure without excessive nesting. + */ +export function generateSampleJson({ + schema, + schemas, + visited = new Set(), + depth = 0, +}: { + schema: Record; + schemas: Record; + visited?: Set; + depth?: number; +}): unknown { + // Prevent infinite recursion and excessive depth + // For deep nesting, return placeholder to keep output manageable + if (depth > 3) { + return "..."; + } + + // Check for examples defined on the schema (use first example if available) + if ( + schema.examples && + Array.isArray(schema.examples) && + schema.examples.length > 0 + ) { + return schema.examples[0]; + } + + // Check for single example + if (schema.example !== undefined) { + return schema.example; + } + + // Handle $ref + if (schema.$ref) { + const refPath = schema.$ref as string; + const refName = refPath.replace("#/components/schemas/", ""); + + if (visited.has(refName)) { + return "..."; // Circular reference placeholder + } + const newVisited = new Set(visited); + newVisited.add(refName); + + const refSchema = schemas[refName] as Record | undefined; + if (refSchema) { + return generateSampleJson({ + schema: refSchema, + schemas, + visited: newVisited, + depth: depth + 1, + }); + } + return null; + } + + // Handle anyOf/oneOf (pick non-null variant) + if (schema.anyOf || schema.oneOf) { + const variants = (schema.anyOf ?? schema.oneOf) as Record< + string, + unknown + >[]; + const nonNullVariant = variants.find( + (v) => v.type !== "null" && !("const" in v && v.const === null), + ); + if (nonNullVariant) { + return generateSampleJson({ + schema: nonNullVariant, + schemas, + visited, + depth, + }); + } + return null; + } + + // Handle enum - return first value + if (schema.enum) { + const enumValues = schema.enum as unknown[]; + return enumValues[0] ?? null; + } + + // Handle const + if ("const" in schema) { + return schema.const; + } + + // Handle object type + if (schema.type === "object") { + const properties = schema.properties as Record | undefined; + if (!properties) { + return {}; + } + + const result: Record = {}; + for (const [propName, propSchema] of Object.entries(properties)) { + result[propName] = generateSampleJson({ + schema: propSchema as Record, + schemas, + visited: new Set(visited), // Fresh set for each property to avoid false positives + depth: depth + 1, + }); + } + return result; + } + + // Handle array type + if (schema.type === "array") { + const items = schema.items as Record | undefined; + if (items) { + return [ + generateSampleJson({ + schema: items, + schemas, + visited: new Set(visited), + depth: depth + 1, + }), + ]; + } + return []; + } + + // Handle primitive types with example values + switch (schema.type) { + case "string": + return ""; + case "number": + case "integer": + return 123; + case "boolean": + return true; + default: + return null; + } +} diff --git a/shared/api/_openapi/utils/mintlifyTransform.ts b/shared/api/_openapi/utils/mintlifyTransform.ts new file mode 100644 index 000000000..59a45ba7d --- /dev/null +++ b/shared/api/_openapi/utils/mintlifyTransform.ts @@ -0,0 +1,178 @@ +import yaml from "yaml"; + +/** + * Strips JSDoc tags from a description string. + * Returns content up to the first @ tag (trimmed). + */ +function stripJsDocTags(description: string): string { + // Find the first @ tag that starts a line (common JSDoc tags) + const tagPatterns = [ + /@example\b/, + /@param\b/, + /@see\b/, + /@returns?\b/, + /@throws?\b/, + /@deprecated\b/, + /@since\b/, + /@version\b/, + /@author\b/, + /@link\b/, + /@type\b/, + /@typedef\b/, + /@property\b/, + /@default\b/, + ]; + + let cutIndex = description.length; + + for (const pattern of tagPatterns) { + const match = description.match(pattern); + if (match && match.index !== undefined && match.index < cutIndex) { + cutIndex = match.index; + } + } + + return description.slice(0, cutIndex).trim(); +} + +/** + * Transforms SDK code sample from Speakeasy format to autumn-js format. + */ +function transformCodeSample(source: string): string { + // Replace import + let result = source.replace( + /import \{ Autumn \} from "@useautumn\/sdk";/g, + "import { Autumn } from 'autumn-js'" + ); + + // Replace initialization with simpler version + result = result.replace( + /const autumn = new Autumn\(\{[\s\S]*?\}\);/g, + "const autumn = new Autumn()" + ); + + // Remove async wrapper function - extract the inner content + const asyncWrapperMatch = result.match( + /async function run\(\) \{([\s\S]*?)\}\s*\n\s*run\(\);/ + ); + if (asyncWrapperMatch) { + const innerContent = asyncWrapperMatch[1] + .split("\n") + .map((line) => { + // Remove 2 spaces of indentation from the wrapper + if (line.startsWith(" ")) { + return line.slice(2); + } + return line; + }) + .join("\n") + .trim(); + result = result.replace(asyncWrapperMatch[0], innerContent); + } + + // Remove console.log + result = result.replace(/\s*console\.log\(result\);?/g, ""); + + // Clean up extra blank lines + result = result.replace(/\n{3,}/g, "\n\n").trim(); + + return result; +} + +/** + * Recursively walks the OpenAPI document and applies transformations. + */ +function transformNode(node: unknown, schemas?: Record): void { + if (Array.isArray(node)) { + for (const item of node) { + transformNode(item, schemas); + } + return; + } + + if (typeof node !== "object" || node === null) { + return; + } + + const record = node as Record; + + // Transform descriptions to strip JSDoc tags + if (typeof record.description === "string") { + record.description = stripJsDocTags(record.description); + } + + // Transform code samples + if (Array.isArray(record["x-codeSamples"])) { + for (const sample of record["x-codeSamples"]) { + if ( + typeof sample === "object" && + sample !== null && + typeof (sample as Record).source === "string" + ) { + const sampleRecord = sample as Record; + sampleRecord.source = transformCodeSample(sampleRecord.source as string); + } + } + } + + // Copy schema examples to response content level for Mintlify + if (schemas && record.content) { + const content = record.content as Record; + const jsonContent = content["application/json"] as Record | undefined; + if (jsonContent?.schema && !jsonContent.example && !jsonContent.examples) { + const schema = jsonContent.schema as Record; + const example = resolveSchemaExample(schema, schemas); + if (example) { + jsonContent.example = example; + } + } + } + + // Recurse into nested objects + for (const value of Object.values(record)) { + transformNode(value, schemas); + } +} + +/** + * Resolves an example from a schema, following $ref if needed. + */ +function resolveSchemaExample( + schema: Record, + schemas: Record +): unknown { + // Check for examples array + if (schema.examples && Array.isArray(schema.examples) && schema.examples.length > 0) { + return schema.examples[0]; + } + + // Check for single example + if (schema.example !== undefined) { + return schema.example; + } + + // Follow $ref + if (schema.$ref && typeof schema.$ref === "string") { + const refName = schema.$ref.replace("#/components/schemas/", ""); + const refSchema = schemas[refName] as Record | undefined; + if (refSchema) { + return resolveSchemaExample(refSchema, schemas); + } + } + + return undefined; +} + +/** + * Transforms an OpenAPI YAML document for Mintlify consumption. + * + * - Strips JSDoc tags from descriptions + * - Transforms Speakeasy code samples to use autumn-js format + * - Copies schema examples to response content level + */ +export function transformOpenApiForMintlify(yamlContent: string): string { + const doc = yaml.parse(yamlContent) as Record; + const schemas = (doc.components as Record)?.schemas as Record | undefined; + transformNode(doc, schemas); + return yaml.stringify(doc); +} diff --git a/shared/api/_openapi/utils/registerInternalSchemas.ts b/shared/api/_openapi/utils/registerInternalSchemas.ts new file mode 100644 index 000000000..d63a5c763 --- /dev/null +++ b/shared/api/_openapi/utils/registerInternalSchemas.ts @@ -0,0 +1,200 @@ +import { JSON_SCHEMA_INPUT_REGISTRY } from "@orpc/zod/zod4"; +import type { z } from "zod/v4"; +import { globalRegistry } from "zod/v4/core"; + +/** + * Recursively walks a Zod schema and registers any schemas marked with + * `.meta({ internal: true })` in the JSON_SCHEMA_INPUT_REGISTRY with + * `x-internal: true`. This allows `removeInternalFields()` to strip them + * from the generated OpenAPI spec. + * + * Note: This approach has limitations with schema transformations like + * `.omit()`, `.extend()`, `.refine()` which create new schema instances. + * For reliable internal field removal, use the INTERNAL_FIELD_NAMES + * list in openapi2.1.ts which removes fields by name. + */ +export function registerInternalSchemas(schema: z.ZodType): void { + const visited = new WeakSet(); + walkSchema(schema, visited); +} + +function walkSchema(schema: z.ZodType, visited: WeakSet): void { + if (visited.has(schema)) return; + visited.add(schema); + + // Check if this schema has internal: true in its metadata + const meta = globalRegistry.get(schema); + if (meta?.internal === true) { + // Register with x-internal so removeInternalFields() can find it + // biome-ignore lint/suspicious/noExplicitAny: TypeScript types are restrictive but runtime accepts arbitrary props + JSON_SCHEMA_INPUT_REGISTRY.add(schema, { "x-internal": true } as any); + } + + // Get the internal Zod definition to traverse nested schemas + // biome-ignore lint/suspicious/noExplicitAny: accessing Zod internals + const def = (schema as any)._zod?.def ?? (schema as any)._def; + if (!def) return; + + // Handle different Zod schema types + switch (def.type ?? def.typeName) { + case "object": + case "ZodObject": { + const shape = def.shape; + if (shape && typeof shape === "object") { + for (const fieldSchema of Object.values(shape)) { + if (isZodType(fieldSchema)) { + walkSchema(fieldSchema, visited); + } + } + } + break; + } + + case "array": + case "ZodArray": { + const element = def.element ?? def.type; + if (isZodType(element)) { + walkSchema(element, visited); + } + break; + } + + case "optional": + case "ZodOptional": + case "nullable": + case "ZodNullable": + case "readonly": + case "ZodReadonly": { + const innerType = def.innerType ?? def.unwrapped; + if (isZodType(innerType)) { + walkSchema(innerType, visited); + } + break; + } + + case "union": + case "ZodUnion": + case "discriminatedUnion": + case "ZodDiscriminatedUnion": { + const options = def.options; + if (Array.isArray(options)) { + for (const option of options) { + if (isZodType(option)) { + walkSchema(option, visited); + } + } + } + break; + } + + case "intersection": + case "ZodIntersection": { + if (isZodType(def.left)) walkSchema(def.left, visited); + if (isZodType(def.right)) walkSchema(def.right, visited); + break; + } + + case "tuple": + case "ZodTuple": { + const items = def.items; + if (Array.isArray(items)) { + for (const item of items) { + if (isZodType(item)) { + walkSchema(item, visited); + } + } + } + if (isZodType(def.rest)) { + walkSchema(def.rest, visited); + } + break; + } + + case "record": + case "ZodRecord": { + if (isZodType(def.keyType)) walkSchema(def.keyType, visited); + if (isZodType(def.valueType)) walkSchema(def.valueType, visited); + break; + } + + case "map": + case "ZodMap": { + if (isZodType(def.keyType)) walkSchema(def.keyType, visited); + if (isZodType(def.valueType)) walkSchema(def.valueType, visited); + break; + } + + case "set": + case "ZodSet": { + if (isZodType(def.valueType)) walkSchema(def.valueType, visited); + break; + } + + case "lazy": + case "ZodLazy": { + // For lazy schemas, we need to get the actual schema + const getter = def.getter; + if (typeof getter === "function") { + try { + const lazySchema = getter(); + if (isZodType(lazySchema)) { + walkSchema(lazySchema, visited); + } + } catch { + // Ignore errors from lazy evaluation + } + } + break; + } + + case "effects": + case "ZodEffects": + case "ZodPipeline": { + const innerSchema = def.schema ?? def.in; + if (isZodType(innerSchema)) { + walkSchema(innerSchema, visited); + } + break; + } + + case "default": + case "ZodDefault": + case "catch": + case "ZodCatch": { + const innerType = def.innerType; + if (isZodType(innerType)) { + walkSchema(innerType, visited); + } + break; + } + + case "branded": + case "ZodBranded": { + const brandedType = def.type; + if (isZodType(brandedType)) { + walkSchema(brandedType, visited); + } + break; + } + + case "promise": + case "ZodPromise": { + const promiseType = def.type; + if (isZodType(promiseType)) { + walkSchema(promiseType, visited); + } + break; + } + } +} + +function isZodType(value: unknown): value is z.ZodType { + if (!value || typeof value !== "object") return false; + // Check for Zod v4 structure + // biome-ignore lint/suspicious/noExplicitAny: checking Zod internals + const v = value as any; + return ( + (v._zod !== undefined && typeof v._zod === "object") || + (v._def !== undefined && typeof v._def === "object") + ); +} diff --git a/shared/api/_openapi/v2.1/contracts/customersContract.ts b/shared/api/_openapi/v2.1/contracts/customersContract.ts index 2891a6266..797615731 100644 --- a/shared/api/_openapi/v2.1/contracts/customersContract.ts +++ b/shared/api/_openapi/v2.1/contracts/customersContract.ts @@ -14,6 +14,13 @@ export const getOrCreateCustomerContract = oc .input( ExtCreateCustomerParamsSchema.meta({ title: "GetOrCreateCustomerParams", + examples: [ + { + customer_id: "cus_123", + name: "John Doe", + email: "john@example.com", + }, + ], }), ) .output(ApiCustomerV5Schema); diff --git a/shared/api/_openapi/v2.1/openapi2.1.ts b/shared/api/_openapi/v2.1/openapi2.1.ts index b92ffc835..bac31bcd1 100644 --- a/shared/api/_openapi/v2.1/openapi2.1.ts +++ b/shared/api/_openapi/v2.1/openapi2.1.ts @@ -1,7 +1,11 @@ import { writeFileSync } from "node:fs"; +import { registerInternalSchemas } from "@api/_openapi/utils/registerInternalSchemas.js"; +import { AttachParamsV0Schema } from "@api/billing/attachV2/attachParamsV0.js"; +import { BillingResponseSchema } from "@api/billing/common/billingResponse.js"; import { CustomerIdSchema } from "@api/common/customerId.js"; import { ApiCustomerV5Schema } from "@api/customers/apiCustomerV5.js"; import { CustomerExpandEnum } from "@api/customers/components/customerExpand/customerExpand.js"; +import { ExtCreateCustomerParamsSchema } from "@api/customers/crud/createCustomerParams.js"; import { CustomerDataSchema } from "@api/models.js"; import { ApiPlanV1Schema } from "@api/products/apiPlanV1.js"; import { OpenAPIGenerator } from "@orpc/openapi"; @@ -113,6 +117,32 @@ const applySpeakeasySettings = ({ }; }; +/** + * Fields that should be stripped from the public OpenAPI spec. + * These are internal fields marked with `.meta({ internal: true })` in schemas. + */ +const INTERNAL_FIELD_NAMES = new Set([ + // Customer params internal fields + "entity_id", + "entity_data", + "id", + "with_autumn_id", + "internal_options", + "processors", + // Customer feature internal fields + "feature_type", + "feature", + "display", + "usage_limit", + "config", + "created_at", + "entitlement_id", + "price_id", + "price_config", + // Customer response internal field + "autumn_id", +]); + const removeInternalFields = ({ openApiDocument, }: { @@ -157,10 +187,14 @@ const removeInternalFields = ({ : null; for (const [propertyName, propertySchema] of Object.entries(properties)) { - if (!isInternalNode(propertySchema)) continue; - - delete properties[propertyName]; - requiredSet?.delete(propertyName); + // Remove fields marked with x-internal or internal, OR fields in the internal names list + if ( + isInternalNode(propertySchema) || + INTERNAL_FIELD_NAMES.has(propertyName) + ) { + delete properties[propertyName]; + requiredSet?.delete(propertyName); + } } if (requiredSet) { @@ -189,6 +223,15 @@ export const writeOpenApi_2_1_0 = async ({ }: { outputFilePath: string; }) => { + // Register internal schemas before generation so they get x-internal: true + // in the OpenAPI output, which removeInternalFields() will then strip + registerInternalSchemas(ExtCreateCustomerParamsSchema); + registerInternalSchemas(AttachParamsV0Schema); + registerInternalSchemas(BillingResponseSchema); + registerInternalSchemas(ApiCustomerV5Schema); + registerInternalSchemas(ApiPlanV1Schema); + registerInternalSchemas(CustomerDataSchema); + const openApiDocument = (await generator.generate(v2_1ContractRouter, { info: { title: "Autumn API", diff --git a/shared/api/api.ts b/shared/api/api.ts index 93157703b..b5a8b87a5 100644 --- a/shared/api/api.ts +++ b/shared/api/api.ts @@ -1,7 +1,9 @@ import { execSync } from "node:child_process"; -import { mkdirSync } from "node:fs"; +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { generateApiReference } from "./_openapi/utils/apiReferenceGenerator/index.js"; +import { transformOpenApiForMintlify } from "./_openapi/utils/mintlifyTransform.js"; // Dynamic imports to avoid duplicate schema registration when supporting multiple versions @@ -57,7 +59,7 @@ if (process.env.NODE_ENV !== "production") { currentDirPath, "../../apps/docs/mintlify/api", ); - const docsOpenApiLocalPath = path.join(docsApiDirPath, "openapi-local.yml"); + const docsOpenApiPath = path.join(docsApiDirPath, "openapi.yml"); mkdirSync(outputDirPath, { recursive: true }); mkdirSync(docsApiDirPath, { recursive: true }); @@ -115,13 +117,33 @@ if (process.env.NODE_ENV !== "production") { console.log("Applying Speakeasy code samples to OpenAPI for docs..."); execSync( - `bunx speakeasy overlay apply --schema .speakeasy/out.openapi.yaml --overlay .speakeasy/code-samples.overlay.yaml --out ${JSON.stringify(docsOpenApiLocalPath)}`, + `bunx speakeasy overlay apply --schema .speakeasy/out.openapi.yaml --overlay .speakeasy/code-samples.overlay.yaml --out ${JSON.stringify(docsOpenApiPath)}`, { stdio: "inherit", cwd: speakeasySdkDirPath, }, ); - console.log(`Docs OpenAPI written to ${docsOpenApiLocalPath}`); + console.log(`Docs OpenAPI written to ${docsOpenApiPath}`); + + // Transform OpenAPI for Mintlify (strip JSDoc tags, fix code samples) + console.log("Transforming OpenAPI for Mintlify docs..."); + const yamlContent = readFileSync(docsOpenApiPath, "utf-8"); + const transformedYaml = transformOpenApiForMintlify(yamlContent); + writeFileSync(docsOpenApiPath, transformedYaml); + console.log("Mintlify transformation complete"); + + // Generate API reference MDX files with dynamic parameter fields + console.log("Generating API reference MDX files..."); + const manualMdxDir = path.resolve( + docsApiDirPath, + "../../api-reference-generator", + ); + const outputMdxDir = path.resolve(docsApiDirPath, "../api-reference"); + await generateApiReference({ + openApiPath: docsOpenApiPath, + manualMdxDir, + outputDir: outputMdxDir, + }); } else { console.log( `Skipping Speakeasy generation for OpenAPI ${version}; only 2.1.0 is wired to SDK generation`, diff --git a/shared/api/customers/apiCustomerV5.ts b/shared/api/customers/apiCustomerV5.ts index 47f169077..79d476b28 100644 --- a/shared/api/customers/apiCustomerV5.ts +++ b/shared/api/customers/apiCustomerV5.ts @@ -7,6 +7,38 @@ import { ApiSubscriptionV1Schema, } from "./cusPlans/apiSubscriptionV1.js"; +export const API_CUSTOMER_V5_EXAMPLE = { + id: "cus_123", + created_at: 1717000000, + name: "John Doe", + email: "john@example.com", + fingerprint: "1234567890", + stripe_id: "cus_123", + env: "sandbox", + metadata: {}, + subscriptions: [ + { + id: "sub_123", + created_at: 1717000000, + plan_id: "plan_123", + status: "active", + quantity: 1, + interval: "month", + interval_count: 1, + }, + ], + purchases: [], + balances: { + balance_1: { + id: "balance_1", + amount: 100, + currency: "USD", + created_at: 1717000000, + updated_at: 1717000000, + }, + }, +}; + // V5 base customer - uses V1 subscriptions (single array with status field) and V1 balances export const BaseApiCustomerV5Schema = BaseApiCustomerSchema.extend({ subscriptions: z.array(ApiSubscriptionV1Schema), @@ -16,7 +48,9 @@ export const BaseApiCustomerV5Schema = BaseApiCustomerSchema.extend({ export const ApiCustomerV5Schema = BaseApiCustomerV5Schema.extend( ApiCusExpandSchema.shape, -); +).meta({ + examples: [API_CUSTOMER_V5_EXAMPLE], +}); export type ApiCustomerV5 = z.infer; export type BaseApiCustomerV5 = z.infer; diff --git a/shared/api/customers/baseApiCustomer.ts b/shared/api/customers/baseApiCustomer.ts index 57a5032f9..947590400 100644 --- a/shared/api/customers/baseApiCustomer.ts +++ b/shared/api/customers/baseApiCustomer.ts @@ -5,15 +5,34 @@ export const BaseApiCustomerSchema = z.object({ autumn_id: z.string().optional().meta({ internal: true, }), - id: z.string().nullable(), - name: z.string().nullable(), - email: z.string().nullable(), - created_at: z.number(), - fingerprint: z.string().nullable(), - stripe_id: z.string().nullable(), - env: z.enum(AppEnv), - metadata: z.record(z.any(), z.any()), - send_email_receipts: z.boolean(), + id: z.string().nullable().meta({ + description: "Your unique identifier for the customer.", + }), + name: z.string().nullable().meta({ + description: "The name of the customer.", + }), + email: z.string().nullable().meta({ + description: "The email address of the customer.", + }), + created_at: z.number().meta({ + description: "Timestamp of customer creation in milliseconds since epoch.", + }), + fingerprint: z.string().nullable().meta({ + description: + "A unique identifier (eg. serial number) to de-duplicate customers across devices or browsers. For example: apple device ID.", + }), + stripe_id: z.string().nullable().meta({ + description: "Stripe customer ID.", + }), + env: z.enum(AppEnv).meta({ + description: "The environment this customer was created in.", + }), + metadata: z.record(z.any(), z.any()).meta({ + description: "The metadata for the customer.", + }), + send_email_receipts: z.boolean().meta({ + description: "Whether to send email receipts to the customer.", + }), }); export type BaseApiCustomer = z.infer; diff --git a/shared/api/customers/crud/createCustomerParams.ts b/shared/api/customers/crud/createCustomerParams.ts index a40b4b9d1..ccf03aee9 100644 --- a/shared/api/customers/crud/createCustomerParams.ts +++ b/shared/api/customers/crud/createCustomerParams.ts @@ -22,8 +22,9 @@ export const CreateCustomerQuerySchema = z.object({ export const ExtCreateCustomerParamsSchema = z .object({ customer_id: CustomerIdSchema.nullable(), + ...CustomerDataSchema.shape, }) - .extend(CustomerDataSchema.shape) + .extend({ expand: CustomerExpandArraySchema.optional(), diff --git a/shared/openapi/openapi.yml b/shared/openapi/openapi.yml index 00c6d18e9..4ca5f7c2a 100644 --- a/shared/openapi/openapi.yml +++ b/shared/openapi/openapi.yml @@ -50,39 +50,9 @@ components: auto_enable_plan_id: type: string description: The ID of the free plan to auto-enable for the customer - processors: - anyOf: - - type: object - properties: - vercel: - type: object - properties: - installation_id: - type: string - access_token: - type: string - account_id: - type: string - custom_payment_method_id: - type: string - required: - - installation_id - - access_token - - account_id - - type: "null" - description: External processors for the customer send_email_receipts: type: boolean description: Whether to send email receipts to this customer - internal_options: - type: object - properties: - default_group: - type: string - description: The group of products to attach to the customer - disable_defaults: - type: boolean - description: Whether to disable default products title: CustomerData description: Customer details to set when creating a customer CustomerExpand: @@ -100,40 +70,40 @@ components: Customer: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" name: anyOf: - type: string - type: "null" + description: The name of the customer. email: anyOf: - type: string - type: "null" - created_at: - type: number + description: The email address of the customer. fingerprint: anyOf: - type: string - type: "null" + description: "A unique identifier (eg. serial number) to de-duplicate customers + across devices or browsers. For example: apple device ID." stripe_id: anyOf: - type: string - type: "null" + description: Stripe customer ID. env: enum: - sandbox - live + description: The environment this customer was created in. metadata: type: object propertyNames: {} additionalProperties: {} + description: The metadata for the customer. send_email_receipts: type: boolean + description: Whether to send email receipts to the customer. subscriptions: type: array items: @@ -222,55 +192,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - name: - type: string - type: - enum: - - boolean - - metered - - credit_system - consumable: - type: boolean - event_names: - type: array - items: - type: string - credit_schema: - type: array - items: - type: object - properties: - metered_feature_id: - type: string - credit_cost: - type: number - required: - - metered_feature_id - - credit_cost - display: - type: object - properties: - singular: - anyOf: - - type: string - - type: "null" - plural: - anyOf: - - type: string - - type: "null" - archived: - type: boolean - required: - - id - - name - - type - - consumable - - archived granted: type: number remaining: @@ -295,9 +216,6 @@ components: items: type: object properties: - id: - type: string - default: "" plan_id: anyOf: - type: string @@ -431,9 +349,6 @@ components: currency: type: string description: The currency code for the invoice - created_at: - type: number - description: Timestamp when the invoice was created hosted_invoice_url: anyOf: - type: string @@ -445,19 +360,11 @@ components: - status - total - currency - - created_at entities: type: array items: type: object properties: - autumn_id: - type: string - id: - anyOf: - - type: string - - type: "null" - description: The unique identifier of the entity name: anyOf: - type: string @@ -473,18 +380,13 @@ components: - type: string - type: "null" description: The feature ID this entity belongs to - created_at: - type: number - description: Unix timestamp when the entity was created env: enum: - sandbox - live description: The environment (sandbox/live) required: - - id - name - - created_at - env trials_used: type: array @@ -511,9 +413,6 @@ components: items: type: object properties: - id: - type: string - description: The unique identifier for this discount name: type: string description: The name of the discount or coupon @@ -565,7 +464,6 @@ components: - type: "null" description: Total amount saved from this discount required: - - id - name - type - discount_value @@ -584,8 +482,6 @@ components: customer: type: object properties: - id: - type: string name: anyOf: - type: string @@ -594,26 +490,20 @@ components: anyOf: - type: string - type: "null" - required: - - id + required: [] reward_applied: type: boolean - created_at: - type: number required: - program_id - customer - reward_applied - - created_at payment_method: anyOf: - {} - type: "null" required: - - id - name - email - - created_at - fingerprint - stripe_id - env @@ -622,11 +512,34 @@ components: - subscriptions - purchases - balances + examples: + - id: cus_123 + created_at: 1717000000 + name: John Doe + email: john@example.com + fingerprint: "1234567890" + stripe_id: cus_123 + env: sandbox + metadata: {} + subscriptions: + - id: sub_123 + created_at: 1717000000 + plan_id: plan_123 + status: active + quantity: 1 + interval: month + interval_count: 1 + purchases: [] + balances: + balance_1: + id: balance_1 + amount: 100 + currency: USD + created_at: 1717000000 + updated_at: 1717000000 Plan: type: object properties: - id: - type: string name: type: string description: @@ -659,15 +572,6 @@ components: - year interval_count: type: number - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text required: - amount - interval @@ -679,66 +583,6 @@ components: properties: feature_id: type: string - feature: - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like - /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type included: type: number unlimited: @@ -809,15 +653,6 @@ components: - billing_method - max_purchase - type: "null" - display: - type: object - properties: - primary_text: - type: string - secondary_text: - type: string - required: - - primary_text rollover: type: object properties: @@ -872,8 +707,6 @@ components: - duration_length - duration_type - card_required - created_at: - type: number env: enum: - sandbox @@ -903,7 +736,6 @@ components: required: - scenario required: - - id - name - description - group @@ -912,7 +744,6 @@ components: - auto_enable - price - items - - created_at - env - archived - base_variant_id @@ -995,67 +826,21 @@ paths: auto_enable_plan_id: type: string description: The ID of the free plan to auto-enable for the customer - processors: - anyOf: - - type: object - properties: - vercel: - type: object - properties: - installation_id: - type: string - access_token: - type: string - account_id: - type: string - custom_payment_method_id: - type: string - required: - - installation_id - - access_token - - account_id - - type: "null" - description: External processors for the customer send_email_receipts: type: boolean description: Whether to send email receipts to this customer - internal_options: - type: object - properties: - default_group: - type: string - description: The group of products to attach to the customer - disable_defaults: - type: boolean - description: Whether to disable default products expand: type: array items: $ref: "#/components/schemas/CustomerExpand" description: Customer expand options - entity_id: - type: string - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id - id: - anyOf: - - $ref: "#/components/schemas/CustomerId" - - type: "null" - with_autumn_id: - type: boolean - default: false required: - customer_id title: GetOrCreateCustomerParams + examples: + - customer_id: cus_123 + name: John Doe + email: john@example.com responses: "200": description: OK @@ -1106,21 +891,6 @@ paths: schema: type: object properties: - entity_id: - anyOf: - - type: string - - type: "null" - entity_data: - type: object - properties: - feature_id: - type: string - description: The feature ID that this entity is associated with - name: - type: string - description: Name of the entity - required: - - feature_id options: anyOf: - type: array @@ -1176,76 +946,6 @@ paths: - type: "null" description: The feature ID of the product item. Should be null for fixed price items. - feature_type: - anyOf: - - enum: - - single_use - - continuous_use - - boolean - - static - - type: "null" - feature: - anyOf: - - type: object - properties: - id: - type: string - description: The ID of the feature, used to refer to it in other API calls like - /track or /check. - name: - anyOf: - - type: string - - type: "null" - description: The name of the feature. - type: - enum: - - static - - boolean - - single_use - - continuous_use - - credit_system - description: The type of the feature - display: - anyOf: - - type: object - properties: - singular: - type: string - description: The singular display name for the feature. - plural: - type: string - description: The plural display name for the feature. - required: - - singular - - plural - - type: "null" - description: Singular and plural display names for the feature. - credit_schema: - anyOf: - - type: array - items: - type: object - properties: - metered_feature_id: - type: string - description: The ID of the metered feature (should be a single_use feature). - credit_cost: - type: number - description: The credit cost of the metered feature. - required: - - metered_feature_id - - credit_cost - - type: "null" - description: Credit cost schema for credit system features. - archived: - anyOf: - - type: boolean - - type: "null" - description: Whether or not the feature is archived. - required: - - id - - type - - type: "null" included_usage: anyOf: - anyOf: @@ -1323,80 +1023,6 @@ paths: - type: boolean - type: "null" description: Whether the usage should be reset when the product is enabled. - display: - anyOf: - - type: object - properties: - primary_text: - type: string - secondary_text: - anyOf: - - type: string - - type: "null" - required: - - primary_text - - type: "null" - usage_limit: - anyOf: - - type: number - - type: "null" - config: - anyOf: - - type: object - properties: - on_increase: - anyOf: - - enum: - - bill_immediately - - prorate_immediately - - prorate_next_cycle - - bill_next_cycle - - type: "null" - on_decrease: - anyOf: - - enum: - - prorate - - prorate_immediately - - prorate_next_cycle - - none - - no_prorations - - type: "null" - rollover: - anyOf: - - type: object - properties: - max: - anyOf: - - type: number - - type: "null" - duration: - enum: - - month - - forever - default: month - length: - type: number - required: - - max - - length - - type: "null" - - type: "null" - created_at: - anyOf: - - type: number - - type: "null" - entitlement_id: - anyOf: - - type: string - - type: "null" - price_id: - anyOf: - - type: string - - type: "null" - price_config: - anyOf: - - {} - - type: "null" product_id: type: string invoice: @@ -1437,8 +1063,6 @@ paths: properties: customer_id: type: string - entity_id: - type: string invoice: type: object properties: