@revstackhq/cli 0.0.0-dev-20260226064743 → 0.0.0-dev-20260227092523

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/templates/starter.ts
4
+ var starter = {
5
+ features: `import { defineFeature } from "@revstackhq/core";
6
+
7
+ export const features = {
8
+ seats: defineFeature({ name: "Seats", type: "static", unit_type: "count" }),
9
+ priority_support: defineFeature({ name: "Priority Support", type: "boolean", unit_type: "custom" }),
10
+ };
11
+ `,
12
+ addons: `import { defineAddon } from "@revstackhq/core";
13
+ import { features } from "./features";
14
+
15
+ export const addons = {
16
+ extra_seats: defineAddon<typeof features>({
17
+ name: "5 Extra Seats",
18
+ description: "Add 5 more team members to your workspace.",
19
+ type: "recurring",
20
+ prices: [
21
+ { amount: 1500, currency: "USD", billing_interval: "monthly" }
22
+ ],
23
+ features: {
24
+ seats: { value_limit: 5, type: "increment", is_hard_limit: false },
25
+ }
26
+ }),
27
+ vip_support: defineAddon<typeof features>({
28
+ name: "Priority Support",
29
+ description: "24/7 Slack channel support.",
30
+ type: "recurring",
31
+ prices: [
32
+ { amount: 9900, currency: "USD", billing_interval: "monthly" }
33
+ ],
34
+ features: {
35
+ priority_support: { has_access: true },
36
+ }
37
+ })
38
+ };
39
+ `,
40
+ plans: `import { definePlan } from "@revstackhq/core";
41
+ import { features } from "./features";
42
+
43
+ export const plans = {
44
+ // DO NOT DELETE: Automatically created default plan for guests.
45
+ default: definePlan<typeof features>({
46
+ name: "Default",
47
+ description: "Automatically created default plan for guests.",
48
+ is_default: true,
49
+ is_public: false,
50
+ type: "free",
51
+ features: {},
52
+ }),
53
+ pro: definePlan<typeof features>({
54
+ name: "Pro",
55
+ description: "For professional teams.",
56
+ is_default: false,
57
+ is_public: true,
58
+ type: "paid",
59
+ available_addons: ["extra_seats", "vip_support"],
60
+ prices: [
61
+ { amount: 2900, currency: "USD", billing_interval: "monthly", trial_period_days: 14 }
62
+ ],
63
+ features: {
64
+ seats: { value_limit: 5, is_hard_limit: true },
65
+ },
66
+ }),
67
+ };
68
+ `,
69
+ index: `import { defineConfig } from "@revstackhq/core";
70
+ import { features } from "./features";
71
+ import { addons } from "./addons";
72
+ import { plans } from "./plans";
73
+
74
+ export default defineConfig({
75
+ features,
76
+ addons,
77
+ plans,
78
+ });
79
+ `,
80
+ root: `import config from "./revstack";
81
+
82
+ export default config;
83
+ `
84
+ };
85
+ export {
86
+ starter
87
+ };
88
+ //# sourceMappingURL=starter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/commands/templates/starter.ts"],"sourcesContent":["export interface TemplateConfig {\r\n features: string;\r\n addons: string;\r\n plans: string;\r\n index: string;\r\n root: string;\r\n}\r\n\r\nexport const starter: TemplateConfig = {\r\n features: `import { defineFeature } from \"@revstackhq/core\";\r\n\r\nexport const features = {\r\n seats: defineFeature({ name: \"Seats\", type: \"static\", unit_type: \"count\" }),\r\n priority_support: defineFeature({ name: \"Priority Support\", type: \"boolean\", unit_type: \"custom\" }),\r\n};\r\n`,\r\n addons: `import { defineAddon } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\n\r\nexport const addons = {\r\n extra_seats: defineAddon<typeof features>({\r\n name: \"5 Extra Seats\",\r\n description: \"Add 5 more team members to your workspace.\",\r\n type: \"recurring\",\r\n prices: [\r\n { amount: 1500, currency: \"USD\", billing_interval: \"monthly\" }\r\n ],\r\n features: {\r\n seats: { value_limit: 5, type: \"increment\", is_hard_limit: false },\r\n }\r\n }),\r\n vip_support: defineAddon<typeof features>({\r\n name: \"Priority Support\",\r\n description: \"24/7 Slack channel support.\",\r\n type: \"recurring\",\r\n prices: [\r\n { amount: 9900, currency: \"USD\", billing_interval: \"monthly\" }\r\n ],\r\n features: {\r\n priority_support: { has_access: true },\r\n }\r\n })\r\n};\r\n`,\r\n plans: `import { definePlan } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\n\r\nexport const plans = {\r\n // DO NOT DELETE: Automatically created default plan for guests.\r\n default: definePlan<typeof features>({\r\n name: \"Default\",\r\n description: \"Automatically created default plan for guests.\",\r\n is_default: true,\r\n is_public: false,\r\n type: \"free\",\r\n features: {},\r\n }),\r\n pro: definePlan<typeof features>({\r\n name: \"Pro\",\r\n description: \"For professional teams.\",\r\n is_default: false,\r\n is_public: true,\r\n type: \"paid\",\r\n available_addons: [\"extra_seats\", \"vip_support\"],\r\n prices: [\r\n { amount: 2900, currency: \"USD\", billing_interval: \"monthly\", trial_period_days: 14 }\r\n ],\r\n features: {\r\n seats: { value_limit: 5, is_hard_limit: true },\r\n },\r\n }),\r\n};\r\n`,\r\n index: `import { defineConfig } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\nimport { addons } from \"./addons\";\r\nimport { plans } from \"./plans\";\r\n\r\nexport default defineConfig({\r\n features,\r\n addons,\r\n plans,\r\n});\r\n`,\r\n root: `import config from \"./revstack\";\r\n\r\nexport default config;\r\n`,\r\n};\r\n"],"mappings":";;;AAQO,IAAM,UAA0B;AAAA,EACrC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BR,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWP,MAAM;AAAA;AAAA;AAAA;AAIR;","names":[]}
@@ -0,0 +1,5 @@
1
+ import { TemplateConfig } from './starter.js';
2
+
3
+ declare const usageBased: TemplateConfig;
4
+
5
+ export { usageBased };
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/templates/usage-based.ts
4
+ var usageBased = {
5
+ features: `import { defineFeature } from "@revstackhq/core";
6
+
7
+ export const features = {
8
+ api_requests: defineFeature({ name: "API Requests", type: "metered", unit_type: "requests" }),
9
+ storage_gb: defineFeature({ name: "Storage (GB)", type: "metered", unit_type: "custom" }),
10
+ };
11
+ `,
12
+ addons: `import { defineAddon } from "@revstackhq/core";
13
+ import { features } from "./features";
14
+
15
+ export const addons = {
16
+ premium_support: defineAddon<typeof features>({
17
+ name: "Premium Support",
18
+ description: "24/7 dedicated support.",
19
+ type: "recurring",
20
+ prices: [
21
+ { amount: 20000, currency: "USD", billing_interval: "monthly" }
22
+ ],
23
+ features: {}
24
+ })
25
+ };
26
+ `,
27
+ plans: `import { definePlan } from "@revstackhq/core";
28
+ import { features } from "./features";
29
+
30
+ export const plans = {
31
+ default: definePlan<typeof features>({
32
+ name: "Default",
33
+ description: "Automatically created default plan for guests.",
34
+ is_default: true,
35
+ is_public: false,
36
+ type: "free",
37
+ features: {},
38
+ }),
39
+ pay_as_you_go: definePlan<typeof features>({
40
+ name: "Pay As You Go",
41
+ description: "Flexible usage-based pricing.",
42
+ is_default: false,
43
+ is_public: true,
44
+ type: "paid",
45
+ available_addons: ["premium_support"],
46
+ prices: [
47
+ { amount: 0, currency: "USD", billing_interval: "monthly" } // Base platform fee
48
+ ],
49
+ features: {
50
+ api_requests: { value_limit: 10000, is_hard_limit: false, reset_period: "monthly" }, // 10k free requests per month
51
+ storage_gb: { value_limit: 5, is_hard_limit: false, reset_period: "never" }, // 5GB free storage lifetime
52
+ },
53
+ }),
54
+ };
55
+ `,
56
+ index: `import { defineConfig } from "@revstackhq/core";
57
+ import { features } from "./features";
58
+ import { addons } from "./addons";
59
+ import { plans } from "./plans";
60
+
61
+ export default defineConfig({
62
+ features,
63
+ addons,
64
+ plans,
65
+ });
66
+ `,
67
+ root: `import config from "./revstack";
68
+
69
+ export default config;
70
+ `
71
+ };
72
+ export {
73
+ usageBased
74
+ };
75
+ //# sourceMappingURL=usage-based.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/commands/templates/usage-based.ts"],"sourcesContent":["import { TemplateConfig } from \"./starter\";\r\n\r\nexport const usageBased: TemplateConfig = {\r\n features: `import { defineFeature } from \"@revstackhq/core\";\r\n\r\nexport const features = {\r\n api_requests: defineFeature({ name: \"API Requests\", type: \"metered\", unit_type: \"requests\" }),\r\n storage_gb: defineFeature({ name: \"Storage (GB)\", type: \"metered\", unit_type: \"custom\" }),\r\n};\r\n`,\r\n addons: `import { defineAddon } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\n\r\nexport const addons = {\r\n premium_support: defineAddon<typeof features>({\r\n name: \"Premium Support\",\r\n description: \"24/7 dedicated support.\",\r\n type: \"recurring\",\r\n prices: [\r\n { amount: 20000, currency: \"USD\", billing_interval: \"monthly\" }\r\n ],\r\n features: {}\r\n })\r\n};\r\n`,\r\n plans: `import { definePlan } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\n\r\nexport const plans = {\r\n default: definePlan<typeof features>({\r\n name: \"Default\",\r\n description: \"Automatically created default plan for guests.\",\r\n is_default: true,\r\n is_public: false,\r\n type: \"free\",\r\n features: {},\r\n }),\r\n pay_as_you_go: definePlan<typeof features>({\r\n name: \"Pay As You Go\",\r\n description: \"Flexible usage-based pricing.\",\r\n is_default: false,\r\n is_public: true,\r\n type: \"paid\",\r\n available_addons: [\"premium_support\"],\r\n prices: [\r\n { amount: 0, currency: \"USD\", billing_interval: \"monthly\" } // Base platform fee\r\n ],\r\n features: {\r\n api_requests: { value_limit: 10000, is_hard_limit: false, reset_period: \"monthly\" }, // 10k free requests per month\r\n storage_gb: { value_limit: 5, is_hard_limit: false, reset_period: \"never\" }, // 5GB free storage lifetime\r\n },\r\n }),\r\n};\r\n`,\r\n index: `import { defineConfig } from \"@revstackhq/core\";\r\nimport { features } from \"./features\";\r\nimport { addons } from \"./addons\";\r\nimport { plans } from \"./plans\";\r\n\r\nexport default defineConfig({\r\n features,\r\n addons,\r\n plans,\r\n});\r\n`,\r\n root: `import config from \"./revstack\";\r\n\r\nexport default config;\r\n`,\r\n};\r\n"],"mappings":";;;AAEO,IAAM,aAA6B;AAAA,EACxC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeR,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWP,MAAM;AAAA;AAAA;AAAA;AAIR;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revstackhq/cli",
3
- "version": "0.0.0-dev-20260226064743",
3
+ "version": "0.0.0-dev-20260227092523",
4
4
  "description": "The official CLI for Revstack — Billing as Code",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,7 +14,8 @@
14
14
  "execa": "^9.6.1",
15
15
  "jiti": "^2.4.2",
16
16
  "ora": "^8.2.0",
17
- "prompts": "^2.4.2"
17
+ "prompts": "^2.4.2",
18
+ "@revstackhq/core": "0.0.0-dev-20260226062415"
18
19
  },
19
20
  "devDependencies": {
20
21
  "@types/node": "^20.11.0",
@@ -13,81 +13,29 @@ import { spawnSync } from "node:child_process";
13
13
  import { fileURLToPath } from "node:url";
14
14
  import ora from "ora";
15
15
 
16
- const STARTER_FEATURES = `import { defineFeature } from "@revstackhq/core";
17
-
18
- export const features = {
19
- seats: defineFeature({
20
- name: "Seats",
21
- type: "static",
22
- unit_type: "count",
23
- }),
24
- ai_tokens: defineFeature({
25
- name: "AI Tokens",
26
- type: "metered",
27
- unit_type: "count",
28
- }),
29
- };
30
- `;
31
-
32
- const STARTER_PLANS = `import { definePlan } from "@revstackhq/core";
33
- import { features } from "./features";
34
-
35
- export const plans = {
36
- // DO NOT DELETE: Automatically created default plan for guests.
37
- default: definePlan<typeof features>({
38
- name: "Default",
39
- description: "Automatically created default plan for guests.",
40
- is_default: true,
41
- is_public: false,
42
- type: "free",
43
- features: {},
44
- }),
45
- pro: definePlan<typeof features>({
46
- name: "Pro",
47
- description: "For professional teams.",
48
- is_default: false,
49
- is_public: true,
50
- type: "paid",
51
- prices: [
52
- {
53
- amount: 2900,
54
- currency: "USD",
55
- billing_interval: "monthly",
56
- trial_period_days: 14,
57
- },
58
- {
59
- amount: 29000,
60
- currency: "USD",
61
- billing_interval: "yearly",
62
- trial_period_days: 14,
63
- }
64
- ],
65
- features: {
66
- seats: { value_limit: 5, is_hard_limit: true },
67
- ai_tokens: { value_limit: 1000, reset_period: "monthly" },
68
- },
69
- }),
70
- };
71
- `;
72
-
73
- const STARTER_CONFIG = `import { defineConfig } from "@revstackhq/core";
74
- import { features } from "./revstack/features";
75
- import { plans } from "./revstack/plans";
76
-
77
- export default defineConfig({
78
- features,
79
- plans,
80
- });
81
- `;
16
+ import { TEMPLATES } from "./templates/index";
82
17
 
83
18
  export const initCommand = new Command("init")
84
19
  .description("Scaffold a new revstack.config.ts in the current directory")
85
- .action(async () => {
20
+ .option(
21
+ "-t, --template <name>",
22
+ "Choose a starting template (starter, b2b-saas, usage-based)",
23
+ "starter",
24
+ )
25
+ .action(async (options) => {
26
+ const templateName = options.template || "starter";
27
+ const template = TEMPLATES[templateName];
28
+
29
+ if (!template) {
30
+ console.log(
31
+ chalk.red(
32
+ `\n ✖ Unknown template "${templateName}". Available templates: ${Object.keys(TEMPLATES).join(", ")}\n`,
33
+ ),
34
+ );
35
+ process.exit(1);
36
+ }
86
37
  const cwd = process.cwd();
87
38
  const configPath = path.resolve(cwd, "revstack.config.ts");
88
- const revstackDir = path.resolve(cwd, "revstack");
89
- const featuresPath = path.resolve(revstackDir, "features.ts");
90
- const plansPath = path.resolve(revstackDir, "plans.ts");
91
39
 
92
40
  if (fs.existsSync(configPath)) {
93
41
  console.log(
@@ -98,13 +46,33 @@ export const initCommand = new Command("init")
98
46
  process.exit(1);
99
47
  }
100
48
 
101
- // Step 1: Create revstack directory and files
49
+ // Step 1: Create revstack directory and config files
50
+ const revstackDir = path.resolve(cwd, "revstack");
102
51
  if (!fs.existsSync(revstackDir)) {
103
52
  fs.mkdirSync(revstackDir, { recursive: true });
104
53
  }
105
- fs.writeFileSync(featuresPath, STARTER_FEATURES, "utf-8");
106
- fs.writeFileSync(plansPath, STARTER_PLANS, "utf-8");
107
- fs.writeFileSync(configPath, STARTER_CONFIG, "utf-8");
54
+
55
+ fs.writeFileSync(
56
+ path.resolve(revstackDir, "features.ts"),
57
+ template.features,
58
+ "utf-8",
59
+ );
60
+ fs.writeFileSync(
61
+ path.resolve(revstackDir, "addons.ts"),
62
+ template.addons,
63
+ "utf-8",
64
+ );
65
+ fs.writeFileSync(
66
+ path.resolve(revstackDir, "plans.ts"),
67
+ template.plans,
68
+ "utf-8",
69
+ );
70
+ fs.writeFileSync(
71
+ path.resolve(revstackDir, "index.ts"),
72
+ template.index,
73
+ "utf-8",
74
+ );
75
+ fs.writeFileSync(configPath, template.root, "utf-8");
108
76
 
109
77
  // Step 2: Detect package manager & verify package.json
110
78
  let packageManager = "npm";
@@ -11,6 +11,7 @@ import prompts from "prompts";
11
11
  import ora from "ora";
12
12
  import { getApiKey } from "@/utils/auth";
13
13
  import { loadLocalConfig } from "@/utils/config-loader";
14
+ import { validateConfig, RevstackValidationError } from "@revstackhq/core";
14
15
 
15
16
  // ─── Types ───────────────────────────────────────────────────
16
17
 
@@ -91,7 +92,44 @@ export const pushCommand = new Command("push")
91
92
  const apiKey = requireAuth();
92
93
  const config = await loadLocalConfig(process.cwd());
93
94
 
94
- // ── Step 1: Compute diff ──────────────────────────────────
95
+ // ── Step 1: Validate config ────────────────────────────────
96
+
97
+ const validationSpinner = ora({
98
+ text: "Validating billing configuration...",
99
+ prefixText: " ",
100
+ }).start();
101
+
102
+ try {
103
+ validateConfig(config as any); // cast to match RevstackConfig expected by validateConfig
104
+ validationSpinner.succeed("Configuration validated");
105
+ } catch (error: any) {
106
+ if (
107
+ error instanceof RevstackValidationError ||
108
+ error?.name === "RevstackValidationError"
109
+ ) {
110
+ validationSpinner.fail("Configuration invalid");
111
+ console.error(
112
+ chalk.red(
113
+ "\n ✖ The billing configuration contains business logic errors:\n",
114
+ ),
115
+ );
116
+ for (const err of error.errors || []) {
117
+ console.error(chalk.red(` • ${err}`));
118
+ }
119
+ console.log();
120
+ process.exit(1);
121
+ }
122
+
123
+ validationSpinner.fail("Validation failed");
124
+ console.error(
125
+ chalk.red(
126
+ `\n An unexpected error occurred during validation: ${error?.message || String(error)}\n`,
127
+ ),
128
+ );
129
+ process.exit(1);
130
+ }
131
+
132
+ // ── Step 2: Compute diff ──────────────────────────────────
95
133
 
96
134
  const spinner = ora({
97
135
  text: "Calculating diff...",
@@ -0,0 +1,99 @@
1
+ import { TemplateConfig } from "./starter";
2
+
3
+ export const b2bSaas: TemplateConfig = {
4
+ features: `import { defineFeature } from "@revstackhq/core";
5
+
6
+ export const features = {
7
+ active_users: defineFeature({ name: "Active Users", type: "static", unit_type: "count" }),
8
+ api_access: defineFeature({ name: "API Access", type: "boolean", unit_type: "custom" }),
9
+ custom_domain: defineFeature({ name: "Custom Domain", type: "boolean", unit_type: "custom" }),
10
+ };
11
+ `,
12
+ addons: `import { defineAddon } from "@revstackhq/core";
13
+ import { features } from "./features";
14
+
15
+ export const addons = {
16
+ extra_users: defineAddon<typeof features>({
17
+ name: "10 Extra Users",
18
+ description: "Add 10 more active users to your workspace.",
19
+ type: "recurring",
20
+ prices: [
21
+ { amount: 5000, currency: "USD", billing_interval: "monthly" }
22
+ ],
23
+ features: {
24
+ active_users: { value_limit: 10, type: "increment", is_hard_limit: true },
25
+ }
26
+ }),
27
+ dedicated_support: defineAddon<typeof features>({
28
+ name: "Dedicated Support",
29
+ description: "Enterprise SLA with 1-hour response time.",
30
+ type: "recurring",
31
+ prices: [
32
+ { amount: 49900, currency: "USD", billing_interval: "monthly" }
33
+ ],
34
+ features: {}
35
+ })
36
+ };
37
+ `,
38
+ plans: `import { definePlan } from "@revstackhq/core";
39
+ import { features } from "./features";
40
+
41
+ export const plans = {
42
+ default: definePlan<typeof features>({
43
+ name: "Default",
44
+ description: "Automatically created default plan for guests.",
45
+ is_default: true,
46
+ is_public: false,
47
+ type: "free",
48
+ features: {},
49
+ }),
50
+ startup: definePlan<typeof features>({
51
+ name: "Startup",
52
+ description: "For small teams getting started.",
53
+ is_default: false,
54
+ is_public: true,
55
+ type: "paid",
56
+ available_addons: ["extra_users"],
57
+ prices: [
58
+ { amount: 9900, currency: "USD", billing_interval: "monthly" }
59
+ ],
60
+ features: {
61
+ active_users: { value_limit: 10, is_hard_limit: true },
62
+ api_access: { value_bool: false },
63
+ custom_domain: { value_bool: false },
64
+ },
65
+ }),
66
+ enterprise: definePlan<typeof features>({
67
+ name: "Enterprise",
68
+ description: "Advanced features for scale.",
69
+ is_default: false,
70
+ is_public: true,
71
+ type: "paid",
72
+ available_addons: ["extra_users", "dedicated_support"],
73
+ prices: [
74
+ { amount: 49900, currency: "USD", billing_interval: "monthly" }
75
+ ],
76
+ features: {
77
+ active_users: { value_limit: 100, is_hard_limit: false },
78
+ api_access: { value_bool: true },
79
+ custom_domain: { value_bool: true },
80
+ },
81
+ }),
82
+ };
83
+ `,
84
+ index: `import { defineConfig } from "@revstackhq/core";
85
+ import { features } from "./features";
86
+ import { addons } from "./addons";
87
+ import { plans } from "./plans";
88
+
89
+ export default defineConfig({
90
+ features,
91
+ addons,
92
+ plans,
93
+ });
94
+ `,
95
+ root: `import config from "./revstack";
96
+
97
+ export default config;
98
+ `,
99
+ };
@@ -0,0 +1,12 @@
1
+ import { starter } from "./starter";
2
+ import { b2bSaas } from "./b2b-saas";
3
+ import { usageBased } from "./usage-based";
4
+ import type { TemplateConfig } from "./starter";
5
+
6
+ export const TEMPLATES: Record<string, TemplateConfig> = {
7
+ starter: starter,
8
+ "b2b-saas": b2bSaas,
9
+ "usage-based": usageBased,
10
+ };
11
+
12
+ export type { TemplateConfig };
@@ -0,0 +1,89 @@
1
+ export interface TemplateConfig {
2
+ features: string;
3
+ addons: string;
4
+ plans: string;
5
+ index: string;
6
+ root: string;
7
+ }
8
+
9
+ export const starter: TemplateConfig = {
10
+ features: `import { defineFeature } from "@revstackhq/core";
11
+
12
+ export const features = {
13
+ seats: defineFeature({ name: "Seats", type: "static", unit_type: "count" }),
14
+ priority_support: defineFeature({ name: "Priority Support", type: "boolean", unit_type: "custom" }),
15
+ };
16
+ `,
17
+ addons: `import { defineAddon } from "@revstackhq/core";
18
+ import { features } from "./features";
19
+
20
+ export const addons = {
21
+ extra_seats: defineAddon<typeof features>({
22
+ name: "5 Extra Seats",
23
+ description: "Add 5 more team members to your workspace.",
24
+ type: "recurring",
25
+ prices: [
26
+ { amount: 1500, currency: "USD", billing_interval: "monthly" }
27
+ ],
28
+ features: {
29
+ seats: { value_limit: 5, type: "increment", is_hard_limit: false },
30
+ }
31
+ }),
32
+ vip_support: defineAddon<typeof features>({
33
+ name: "Priority Support",
34
+ description: "24/7 Slack channel support.",
35
+ type: "recurring",
36
+ prices: [
37
+ { amount: 9900, currency: "USD", billing_interval: "monthly" }
38
+ ],
39
+ features: {
40
+ priority_support: { has_access: true },
41
+ }
42
+ })
43
+ };
44
+ `,
45
+ plans: `import { definePlan } from "@revstackhq/core";
46
+ import { features } from "./features";
47
+
48
+ export const plans = {
49
+ // DO NOT DELETE: Automatically created default plan for guests.
50
+ default: definePlan<typeof features>({
51
+ name: "Default",
52
+ description: "Automatically created default plan for guests.",
53
+ is_default: true,
54
+ is_public: false,
55
+ type: "free",
56
+ features: {},
57
+ }),
58
+ pro: definePlan<typeof features>({
59
+ name: "Pro",
60
+ description: "For professional teams.",
61
+ is_default: false,
62
+ is_public: true,
63
+ type: "paid",
64
+ available_addons: ["extra_seats", "vip_support"],
65
+ prices: [
66
+ { amount: 2900, currency: "USD", billing_interval: "monthly", trial_period_days: 14 }
67
+ ],
68
+ features: {
69
+ seats: { value_limit: 5, is_hard_limit: true },
70
+ },
71
+ }),
72
+ };
73
+ `,
74
+ index: `import { defineConfig } from "@revstackhq/core";
75
+ import { features } from "./features";
76
+ import { addons } from "./addons";
77
+ import { plans } from "./plans";
78
+
79
+ export default defineConfig({
80
+ features,
81
+ addons,
82
+ plans,
83
+ });
84
+ `,
85
+ root: `import config from "./revstack";
86
+
87
+ export default config;
88
+ `,
89
+ };
@@ -0,0 +1,70 @@
1
+ import { TemplateConfig } from "./starter";
2
+
3
+ export const usageBased: TemplateConfig = {
4
+ features: `import { defineFeature } from "@revstackhq/core";
5
+
6
+ export const features = {
7
+ api_requests: defineFeature({ name: "API Requests", type: "metered", unit_type: "requests" }),
8
+ storage_gb: defineFeature({ name: "Storage (GB)", type: "metered", unit_type: "custom" }),
9
+ };
10
+ `,
11
+ addons: `import { defineAddon } from "@revstackhq/core";
12
+ import { features } from "./features";
13
+
14
+ export const addons = {
15
+ premium_support: defineAddon<typeof features>({
16
+ name: "Premium Support",
17
+ description: "24/7 dedicated support.",
18
+ type: "recurring",
19
+ prices: [
20
+ { amount: 20000, currency: "USD", billing_interval: "monthly" }
21
+ ],
22
+ features: {}
23
+ })
24
+ };
25
+ `,
26
+ plans: `import { definePlan } from "@revstackhq/core";
27
+ import { features } from "./features";
28
+
29
+ export const plans = {
30
+ default: definePlan<typeof features>({
31
+ name: "Default",
32
+ description: "Automatically created default plan for guests.",
33
+ is_default: true,
34
+ is_public: false,
35
+ type: "free",
36
+ features: {},
37
+ }),
38
+ pay_as_you_go: definePlan<typeof features>({
39
+ name: "Pay As You Go",
40
+ description: "Flexible usage-based pricing.",
41
+ is_default: false,
42
+ is_public: true,
43
+ type: "paid",
44
+ available_addons: ["premium_support"],
45
+ prices: [
46
+ { amount: 0, currency: "USD", billing_interval: "monthly" } // Base platform fee
47
+ ],
48
+ features: {
49
+ api_requests: { value_limit: 10000, is_hard_limit: false, reset_period: "monthly" }, // 10k free requests per month
50
+ storage_gb: { value_limit: 5, is_hard_limit: false, reset_period: "never" }, // 5GB free storage lifetime
51
+ },
52
+ }),
53
+ };
54
+ `,
55
+ index: `import { defineConfig } from "@revstackhq/core";
56
+ import { features } from "./features";
57
+ import { addons } from "./addons";
58
+ import { plans } from "./plans";
59
+
60
+ export default defineConfig({
61
+ features,
62
+ addons,
63
+ plans,
64
+ });
65
+ `,
66
+ root: `import config from "./revstack";
67
+
68
+ export default config;
69
+ `,
70
+ };