diff --git a/atmn/src/commands/push/validate.ts b/atmn/src/commands/push/validate.ts index 92ae82a..95117b8 100644 --- a/atmn/src/commands/push/validate.ts +++ b/atmn/src/commands/push/validate.ts @@ -83,6 +83,15 @@ function validatePlanFeature( }); } + // Cannot have both top-level reset AND price (with amount/tiers) + // These are conflicting billing models: reset = free allocation, price = paid + if (hasTopLevelReset && planFeature.price && (planFeature.price.amount !== undefined || planFeature.price.tiers)) { + errors.push({ + path: basePath, + message: `Cannot have both "reset" and "price" with an amount/tiers. "reset" is for free allocations that reset periodically. For paid usage, remove "reset" and use "price: { interval: '...', amount: ..., billing_method: '...' }" instead.`, + }); + } + // ========== FEATURE TYPE VALIDATIONS ========== if (featureDefinition) { // Boolean features cannot have reset diff --git a/atmn/src/compose/builders/builderFunctions.ts b/atmn/src/compose/builders/builderFunctions.ts index 3d73457..97579e7 100644 --- a/atmn/src/compose/builders/builderFunctions.ts +++ b/atmn/src/compose/builders/builderFunctions.ts @@ -5,7 +5,7 @@ import type { Plan, PlanFeature, FreeTrial } from "../models/planModels.js"; import type { Feature } from "../models/featureModels.js"; -type PlanInput = Omit & Partial>; +type PlanInput = Omit & Partial>; /** * Define a pricing plan in your Autumn configuration @@ -17,7 +17,6 @@ type PlanInput = Omit * export const pro = plan({ * id: 'pro', * name: 'Pro Plan', - * description: 'For growing teams', * items: [ * planFeature({ feature_id: seats.id, included: 10 }), * planFeature({ @@ -32,7 +31,6 @@ type PlanInput = Omit export const plan = (params: PlanInput): Plan => { return { ...params, - description: params.description ?? null, add_on: params.add_on ?? false, auto_enable: params.auto_enable ?? false, group: params.group ?? "" diff --git a/atmn/src/compose/models/planModels.ts b/atmn/src/compose/models/planModels.ts index 88944a5..5a21127 100644 --- a/atmn/src/compose/models/planModels.ts +++ b/atmn/src/compose/models/planModels.ts @@ -227,9 +227,6 @@ export type Plan = { /** Display name for the plan */ name: string; - /** Optional description explaining what this plan offers */ - description?: string | null; - /** Grouping identifier for organizing related plans */ group?: string; diff --git a/atmn/src/constants.ts b/atmn/src/constants.ts index 5f015d1..b0ea3cc 100644 --- a/atmn/src/constants.ts +++ b/atmn/src/constants.ts @@ -31,7 +31,6 @@ export const messages = feature({ export const pro = plan({ id: 'pro', name: 'Pro', - description: 'Professional plan for growing teams', add_on: false, auto_enable: false, price: { diff --git a/atmn/src/lib/transforms/apiToSdk/Transformer.test.ts b/atmn/src/lib/transforms/apiToSdk/Transformer.test.ts index fa633b7..72a2929 100644 --- a/atmn/src/lib/transforms/apiToSdk/Transformer.test.ts +++ b/atmn/src/lib/transforms/apiToSdk/Transformer.test.ts @@ -70,7 +70,6 @@ describe("Transformer", () => { const apiPlan: any = { id: "pro", name: "Pro Plan", - description: "Professional tier", auto_enable: true, items: [], }; diff --git a/atmn/src/lib/transforms/apiToSdk/plan.ts b/atmn/src/lib/transforms/apiToSdk/plan.ts index 338bef4..d2e0c07 100644 --- a/atmn/src/lib/transforms/apiToSdk/plan.ts +++ b/atmn/src/lib/transforms/apiToSdk/plan.ts @@ -7,7 +7,7 @@ import { createTransformer } from "./Transformer.js"; * Declarative plan transformer - replaces 57 lines with ~20 lines of config */ export const planTransformer = createTransformer({ - copy: ["id", "name", "description", "group", "add_on", "auto_enable", "free_trial"], + copy: ["id", "name", "group", "add_on", "auto_enable", "free_trial"], // Swap null to undefined for these fields (API → SDK direction) // When pulling from API: null becomes undefined (cleaner, won't show in generated code) diff --git a/atmn/src/lib/transforms/sdkToApi/plan.ts b/atmn/src/lib/transforms/sdkToApi/plan.ts index 2e79ac0..7713e94 100644 --- a/atmn/src/lib/transforms/sdkToApi/plan.ts +++ b/atmn/src/lib/transforms/sdkToApi/plan.ts @@ -6,7 +6,6 @@ import type { Plan, PlanFeature } from "../../../compose/models/index.js"; export interface ApiPlanParams { id: string; name: string; - description?: string | null; group?: string; add_on?: boolean; auto_enable?: boolean; @@ -137,10 +136,6 @@ export function transformPlanToApi(plan: Plan): ApiPlanParams { name: plan.name, }; - if (plan.description !== undefined) { - result.description = plan.description; - } - if (plan.group !== undefined) { result.group = plan.group; } diff --git a/atmn/src/lib/transforms/sdkToCode/plan.ts b/atmn/src/lib/transforms/sdkToCode/plan.ts index 1b6fdf8..2dc7a30 100644 --- a/atmn/src/lib/transforms/sdkToCode/plan.ts +++ b/atmn/src/lib/transforms/sdkToCode/plan.ts @@ -21,11 +21,6 @@ export function buildPlanCode( lines.push(`\tid: '${plan.id}',`); lines.push(`\tname: '${plan.name}',`); - // Add description - if (plan.description !== undefined && plan.description !== null) { - lines.push(`\tdescription: '${plan.description}',`); - } - // Add group (only if it has a non-empty string value) // undefined and null both mean "no group" and should be omitted from generated code if (plan.group !== undefined && plan.group !== null && plan.group !== "") { diff --git a/typegen/typeConfigs.ts b/typegen/typeConfigs.ts index b07c46f..c876dbf 100644 --- a/typegen/typeConfigs.ts +++ b/typegen/typeConfigs.ts @@ -649,7 +649,6 @@ export function getAtmnTypeConfigs( paramType: "Plan", targetFile: path.join(buildersDir, "builderFunctions.ts"), defaults: { - description: null, add_on: false, auto_enable: false, group: "", @@ -664,7 +663,6 @@ export function getAtmnTypeConfigs( * export const pro = plan({ * id: 'pro', * name: 'Pro Plan', - * description: 'For growing teams', * items: [ * planFeature({ feature_id: seats.id, included: 10 }), * planFeature({