@revstackhq/cli 0.0.0-dev-20260226063200 → 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.
- package/.turbo/turbo-build.log +42 -30
- package/CHANGELOG.md +18 -0
- package/README.md +58 -38
- package/dist/cli.js +314 -43
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.js +279 -42
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +3 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.js +32 -0
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/templates/b2b-saas.d.ts +5 -0
- package/dist/commands/templates/b2b-saas.js +104 -0
- package/dist/commands/templates/b2b-saas.js.map +1 -0
- package/dist/commands/templates/index.d.ts +5 -0
- package/dist/commands/templates/index.js +264 -0
- package/dist/commands/templates/index.js.map +1 -0
- package/dist/commands/templates/starter.d.ts +10 -0
- package/dist/commands/templates/starter.js +88 -0
- package/dist/commands/templates/starter.js.map +1 -0
- package/dist/commands/templates/usage-based.d.ts +5 -0
- package/dist/commands/templates/usage-based.js +75 -0
- package/dist/commands/templates/usage-based.js.map +1 -0
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/config-loader.js.map +1 -1
- package/package.json +3 -2
- package/src/cli.ts +32 -32
- package/src/commands/init.ts +187 -210
- package/src/commands/login.ts +39 -39
- package/src/commands/logout.ts +27 -25
- package/src/commands/pull.ts +280 -280
- package/src/commands/push.ts +244 -206
- package/src/commands/templates/b2b-saas.ts +99 -0
- package/src/commands/templates/index.ts +12 -0
- package/src/commands/templates/starter.ts +89 -0
- package/src/commands/templates/usage-based.ts +70 -0
- package/src/utils/auth.ts +59 -59
- package/src/utils/config-loader.ts +57 -57
- package/tests/integration/init.test.ts +12 -2
- package/tests/integration/push.test.ts +20 -4
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,36 +1,48 @@
|
|
|
1
|
-
[?9001h[?1004h[?25l[2J[m[2;1H> @revstackhq/cli@0.0.0-dev-
|
|
2
|
-
> tsup[5;1H]0;C:\WINDOWS\system32\cmd.exe[?25h[34mCLI [mBuilding entry: src/cli.ts, src/commands/init.ts, src/commands/login.ts, src/commands/logout.ts, src/commands/pull.ts, src/commands/push.ts, src/utils/auth.ts, src/utils/config-loader.ts
|
|
1
|
+
[?9001h[?1004h[?25l[2J[m[2;1H> @revstackhq/cli@0.0.0-dev-20260227092523 build C:\Users\flava\OneDrive\Desktop\Work\revstack-os\packages\cli
|
|
2
|
+
> tsup[5;1H]0;C:\WINDOWS\system32\cmd.exe[?25h[34mCLI [mBuilding entry: src/cli.ts, src/commands/init.ts, src/commands/login.ts, src/commands/logout.ts, src/commands/pull.ts, src/commands/push.ts, src/utils/auth.ts, src/utils/config-loader.ts, src/commands/templates/b2b-saas.ts, src/commands/templates/index.ts, src/commands/templates/starter.ts, src/commands/templates/usage-based.ts
|
|
3
3
|
[34mCLI [mUsing tsconfig: tsconfig.json[34m
|
|
4
4
|
CLI [mtsup v8.5.1[34m
|
|
5
|
-
CLI [mUsing tsup config: C:\Users\flava\OneDrive\Desktop\Work\revstack-os\packages\cli\tsup.config.ts
|
|
6
|
-
|
|
5
|
+
CLI [mUsing tsup config: C:\Users\flava\OneDrive\Desktop\Work\revstack-os\packages\cli\tsup.config.ts
|
|
6
|
+
[34mCLI [mTarget: node18
|
|
7
7
|
[34mCLI [mCleaning output folder
|
|
8
8
|
[34mESM [mBuild start
|
|
9
|
-
[32mESM [m[1mdist\cli.js
|
|
10
|
-
[32mESM [m[1mdist\commands\
|
|
11
|
-
[32mESM [m[1mdist\commands\
|
|
12
|
-
[32mESM [m[1mdist\commands\
|
|
13
|
-
[32mESM [m[1mdist\utils\
|
|
14
|
-
[32mESM [m[1mdist\
|
|
15
|
-
[32mESM [m[1mdist\
|
|
16
|
-
[32mESM [m[1mdist\commands\
|
|
17
|
-
[32mESM [m[1mdist\
|
|
18
|
-
[32mESM [m[1mdist\commands\
|
|
19
|
-
[32mESM [m[1mdist\commands\
|
|
20
|
-
[32mESM [m[1mdist\commands\
|
|
21
|
-
[32mESM [m[1mdist\
|
|
22
|
-
[32mESM [m[1mdist\
|
|
23
|
-
[32mESM [m[1mdist\commands\
|
|
24
|
-
[32mESM [m[1mdist\commands\
|
|
25
|
-
[32mESM [m
|
|
9
|
+
[32mESM [m[1mdist\cli.js [32m[22m25.74 KB
|
|
10
|
+
[32mESM [m[1mdist\commands\templates\b2b-saas.js [32m[22m2.85 KB
|
|
11
|
+
[32mESM [m[1mdist\commands\login.js [32m[22m1.42 KB[K
|
|
12
|
+
[32mESM [m[1mdist\commands\init.js [32m[22m11.53 KB[K
|
|
13
|
+
[32mESM [m[1mdist\utils\config-loader.js [32m[22m1.05 KB[K
|
|
14
|
+
[32mESM [m[1mdist\utils\auth.js [32m[22m971.00 B[K
|
|
15
|
+
[32mESM [m[1mdist\commands\logout.js [32m[22m1.17 KB[K
|
|
16
|
+
[32mESM [m[1mdist\commands\pull.js [32m[22m6.22 KB[K
|
|
17
|
+
[32mESM [m[1mdist\commands\push.js [32m[22m6.27 KB[K
|
|
18
|
+
[32mESM [m[1mdist\commands\templates\starter.js [32m[22m2.27 KB[K
|
|
19
|
+
[32mESM [m[1mdist\commands\templates\usage-based.js [32m[22m2.02 KB[K
|
|
20
|
+
[32mESM [m[1mdist\commands\templates\index.js [32m[22m7.09 KB[K
|
|
21
|
+
[32mESM [m[1mdist\cli.js.map [32m[22m50.88 KB[K
|
|
22
|
+
[32mESM [m[1mdist\commands\login.js.map [32m[22m3.70 KB[K
|
|
23
|
+
[32mESM [m[1mdist\commands\templates\b2b-saas.js.map [32m[22m3.84 KB[K
|
|
24
|
+
[32mESM [m[1mdist\commands\init.js.map [32m[22m19.25 KB[K
|
|
25
|
+
[32mESM [m[1mdist\utils\config-loader.js.map [32m[22m2.55 KB[K
|
|
26
|
+
[32mESM [m[1mdist\commands\logout.js.map [32m[22m3.03 KB[K
|
|
27
|
+
[32mESM [m[1mdist\utils\auth.js.map [32m[22m2.24 KB[K
|
|
28
|
+
[32mESM [m[1mdist\commands\pull.js.map [32m[22m14.06 KB[K
|
|
29
|
+
[32mESM [m[1mdist\commands\templates\usage-based.js.map [32m[22m2.75 KB[K
|
|
30
|
+
[32mESM [m[1mdist\commands\templates\starter.js.map [32m[22m3.21 KB[K
|
|
31
|
+
[32mESM [m[1mdist\commands\push.js.map [32m[22m14.83 KB[K
|
|
32
|
+
[32mESM [m[1mdist\commands\templates\index.js.map [32m[22m10.15 KB[K
|
|
33
|
+
[32mESM [m⚡️ Build success in 81ms[K
|
|
26
34
|
[34mDTS [mBuild start
|
|
27
|
-
[32mDTS [m⚡️ Build success in
|
|
28
|
-
[32mDTS [m[1mdist\cli.d.ts
|
|
29
|
-
[32mDTS [m[1mdist\commands\init.d.ts
|
|
30
|
-
[32mDTS [m[1mdist\commands\login.d.ts
|
|
31
|
-
[32mDTS [m[1mdist\commands\logout.d.ts
|
|
32
|
-
[32mDTS [m[1mdist\commands\pull.d.ts
|
|
33
|
-
[32mDTS [m[1mdist\commands\push.d.ts
|
|
34
|
-
[32mDTS [m[1mdist\utils\auth.d.ts
|
|
35
|
-
[32mDTS [m[1mdist\utils\config-loader.d.ts
|
|
35
|
+
[32mDTS [m⚡️ Build success in 7779ms
|
|
36
|
+
[32mDTS [m[1mdist\cli.d.ts [32m[22m13.00 B
|
|
37
|
+
[32mDTS [m[1mdist\commands\init.d.ts [32m[22m353.00 B[K
|
|
38
|
+
[32mDTS [m[1mdist\commands\login.d.ts [32m[22m288.00 B[K
|
|
39
|
+
[32mDTS [m[1mdist\commands\logout.d.ts [32m[22m192.00 B[K
|
|
40
|
+
[32mDTS [m[1mdist\commands\pull.d.ts [32m[22m334.00 B[K
|
|
41
|
+
[32mDTS [m[1mdist\commands\push.d.ts [32m[22m328.00 B[K
|
|
42
|
+
[32mDTS [m[1mdist\utils\auth.d.ts [32m[22m637.00 B[K
|
|
43
|
+
[32mDTS [m[1mdist\utils\config-loader.d.ts [32m[22m566.00 B[K
|
|
44
|
+
[32mDTS [m[1mdist\commands\templates\b2b-saas.d.ts [32m[22m108.00 B[K
|
|
45
|
+
[32mDTS [m[1mdist\commands\templates\index.d.ts [32m[22m144.00 B[K
|
|
46
|
+
[32mDTS [m[1mdist\commands\templates\usage-based.d.ts [32m[22m114.00 B[K
|
|
47
|
+
[32mDTS [m[1mdist\commands\templates\starter.d.ts [32m[22m208.00 B[K
|
|
36
48
|
[?9001l[?1004l
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @revstackhq/cli
|
|
2
2
|
|
|
3
|
+
## 0.0.0-dev-20260227092523
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- implement modular enterprise configuration structure and interactive addons in init command
|
|
8
|
+
|
|
9
|
+
## 0.0.0-dev-20260226064743
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- fix: respect snapshot releases during core package scaffold
|
|
14
|
+
|
|
15
|
+
## 0.0.0-dev-20260226064458
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- fix: format console output line breaks correctly in init command
|
|
20
|
+
|
|
3
21
|
## 0.0.0-dev-20260226063200
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -32,12 +32,14 @@ Scaffold a new `revstack.config.ts` in your project root:
|
|
|
32
32
|
revstack init
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
This creates a starter config with example plans and features using
|
|
35
|
+
This creates a `revstack/` directory and a `revstack.config.ts` file in your project root, scaffolding a starter config with example plans and features using type-safe helpers from `@revstackhq/core`:
|
|
36
|
+
|
|
37
|
+
**`revstack/features.ts`**
|
|
36
38
|
|
|
37
39
|
```typescript
|
|
38
|
-
import {
|
|
40
|
+
import { defineFeature } from "@revstackhq/core";
|
|
39
41
|
|
|
40
|
-
const features = {
|
|
42
|
+
export const features = {
|
|
41
43
|
seats: defineFeature({
|
|
42
44
|
name: "Seats",
|
|
43
45
|
type: "static",
|
|
@@ -49,44 +51,62 @@ const features = {
|
|
|
49
51
|
unit_type: "count",
|
|
50
52
|
}),
|
|
51
53
|
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**`revstack/plans.ts`**
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { definePlan } from "@revstackhq/core";
|
|
60
|
+
import { features } from "./features";
|
|
61
|
+
|
|
62
|
+
export const plans = {
|
|
63
|
+
// DO NOT DELETE: Automatically created default plan for guests.
|
|
64
|
+
default: definePlan<typeof features>({
|
|
65
|
+
name: "Default",
|
|
66
|
+
description: "Automatically created default plan for guests.",
|
|
67
|
+
is_default: true,
|
|
68
|
+
is_public: false,
|
|
69
|
+
type: "free",
|
|
70
|
+
features: {},
|
|
71
|
+
}),
|
|
72
|
+
pro: definePlan<typeof features>({
|
|
73
|
+
name: "Pro",
|
|
74
|
+
description: "For professional teams.",
|
|
75
|
+
is_default: false,
|
|
76
|
+
is_public: true,
|
|
77
|
+
type: "paid",
|
|
78
|
+
prices: [
|
|
79
|
+
{
|
|
80
|
+
amount: 2900,
|
|
81
|
+
currency: "USD",
|
|
82
|
+
billing_interval: "monthly",
|
|
83
|
+
trial_period_days: 14,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
amount: 29000,
|
|
87
|
+
currency: "USD",
|
|
88
|
+
billing_interval: "yearly",
|
|
89
|
+
trial_period_days: 14,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
features: {
|
|
93
|
+
seats: { value_limit: 5, is_hard_limit: true },
|
|
94
|
+
ai_tokens: { value_limit: 1000, reset_period: "monthly" },
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**`revstack.config.ts`**
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { defineConfig } from "@revstackhq/core";
|
|
104
|
+
import { features } from "./revstack/features";
|
|
105
|
+
import { plans } from "./revstack/plans";
|
|
52
106
|
|
|
53
107
|
export default defineConfig({
|
|
54
108
|
features,
|
|
55
|
-
plans
|
|
56
|
-
default: definePlan<typeof features>({
|
|
57
|
-
name: "Default",
|
|
58
|
-
description: "Automatically created default plan for guests.",
|
|
59
|
-
is_default: true,
|
|
60
|
-
is_public: false,
|
|
61
|
-
type: "free",
|
|
62
|
-
features: {},
|
|
63
|
-
}),
|
|
64
|
-
pro: definePlan<typeof features>({
|
|
65
|
-
name: "Pro",
|
|
66
|
-
description: "For professional teams.",
|
|
67
|
-
is_default: false,
|
|
68
|
-
is_public: true,
|
|
69
|
-
type: "paid",
|
|
70
|
-
prices: [
|
|
71
|
-
{
|
|
72
|
-
amount: 2900,
|
|
73
|
-
currency: "USD",
|
|
74
|
-
billing_interval: "monthly",
|
|
75
|
-
trial_period_days: 14,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
amount: 29000,
|
|
79
|
-
currency: "USD",
|
|
80
|
-
billing_interval: "yearly",
|
|
81
|
-
trial_period_days: 14,
|
|
82
|
-
},
|
|
83
|
-
],
|
|
84
|
-
features: {
|
|
85
|
-
seats: { value_limit: 5, is_hard_limit: true },
|
|
86
|
-
ai_tokens: { value_limit: 1000, reset_period: "monthly" },
|
|
87
|
-
},
|
|
88
|
-
}),
|
|
89
|
-
},
|
|
109
|
+
plans,
|
|
90
110
|
});
|
|
91
111
|
```
|
|
92
112
|
|
package/dist/cli.js
CHANGED
|
@@ -75,7 +75,9 @@ var logoutCommand = new Command2("logout").description("Clear stored Revstack cr
|
|
|
75
75
|
}
|
|
76
76
|
clearApiKey();
|
|
77
77
|
console.log(
|
|
78
|
-
"\n" + chalk2.green(" \u2714 Successfully logged out.\n") + chalk2.dim(
|
|
78
|
+
"\n" + chalk2.green(" \u2714 Successfully logged out.\n") + chalk2.dim(
|
|
79
|
+
" Credentials removed from ~/.revstack/credentials.json\n"
|
|
80
|
+
)
|
|
79
81
|
);
|
|
80
82
|
});
|
|
81
83
|
|
|
@@ -85,23 +87,47 @@ import chalk3 from "chalk";
|
|
|
85
87
|
import fs2 from "fs";
|
|
86
88
|
import path2 from "path";
|
|
87
89
|
import { spawnSync } from "child_process";
|
|
90
|
+
import { fileURLToPath } from "url";
|
|
88
91
|
import ora from "ora";
|
|
89
|
-
|
|
92
|
+
|
|
93
|
+
// src/commands/templates/starter.ts
|
|
94
|
+
var starter = {
|
|
95
|
+
features: `import { defineFeature } from "@revstackhq/core";
|
|
90
96
|
|
|
91
97
|
export const features = {
|
|
92
|
-
seats: defineFeature({
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
seats: defineFeature({ name: "Seats", type: "static", unit_type: "count" }),
|
|
99
|
+
priority_support: defineFeature({ name: "Priority Support", type: "boolean", unit_type: "custom" }),
|
|
100
|
+
};
|
|
101
|
+
`,
|
|
102
|
+
addons: `import { defineAddon } from "@revstackhq/core";
|
|
103
|
+
import { features } from "./features";
|
|
104
|
+
|
|
105
|
+
export const addons = {
|
|
106
|
+
extra_seats: defineAddon<typeof features>({
|
|
107
|
+
name: "5 Extra Seats",
|
|
108
|
+
description: "Add 5 more team members to your workspace.",
|
|
109
|
+
type: "recurring",
|
|
110
|
+
prices: [
|
|
111
|
+
{ amount: 1500, currency: "USD", billing_interval: "monthly" }
|
|
112
|
+
],
|
|
113
|
+
features: {
|
|
114
|
+
seats: { value_limit: 5, type: "increment", is_hard_limit: false },
|
|
115
|
+
}
|
|
101
116
|
}),
|
|
117
|
+
vip_support: defineAddon<typeof features>({
|
|
118
|
+
name: "Priority Support",
|
|
119
|
+
description: "24/7 Slack channel support.",
|
|
120
|
+
type: "recurring",
|
|
121
|
+
prices: [
|
|
122
|
+
{ amount: 9900, currency: "USD", billing_interval: "monthly" }
|
|
123
|
+
],
|
|
124
|
+
features: {
|
|
125
|
+
priority_support: { has_access: true },
|
|
126
|
+
}
|
|
127
|
+
})
|
|
102
128
|
};
|
|
103
|
-
|
|
104
|
-
|
|
129
|
+
`,
|
|
130
|
+
plans: `import { definePlan } from "@revstackhq/core";
|
|
105
131
|
import { features } from "./features";
|
|
106
132
|
|
|
107
133
|
export const plans = {
|
|
@@ -120,54 +146,260 @@ export const plans = {
|
|
|
120
146
|
is_default: false,
|
|
121
147
|
is_public: true,
|
|
122
148
|
type: "paid",
|
|
149
|
+
available_addons: ["extra_seats", "vip_support"],
|
|
123
150
|
prices: [
|
|
124
|
-
{
|
|
125
|
-
amount: 2900,
|
|
126
|
-
currency: "USD",
|
|
127
|
-
billing_interval: "monthly",
|
|
128
|
-
trial_period_days: 14,
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
amount: 29000,
|
|
132
|
-
currency: "USD",
|
|
133
|
-
billing_interval: "yearly",
|
|
134
|
-
trial_period_days: 14,
|
|
135
|
-
}
|
|
151
|
+
{ amount: 2900, currency: "USD", billing_interval: "monthly", trial_period_days: 14 }
|
|
136
152
|
],
|
|
137
153
|
features: {
|
|
138
154
|
seats: { value_limit: 5, is_hard_limit: true },
|
|
139
|
-
ai_tokens: { value_limit: 1000, reset_period: "monthly" },
|
|
140
155
|
},
|
|
141
156
|
}),
|
|
142
157
|
};
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
import { features } from "./
|
|
146
|
-
import {
|
|
158
|
+
`,
|
|
159
|
+
index: `import { defineConfig } from "@revstackhq/core";
|
|
160
|
+
import { features } from "./features";
|
|
161
|
+
import { addons } from "./addons";
|
|
162
|
+
import { plans } from "./plans";
|
|
147
163
|
|
|
148
164
|
export default defineConfig({
|
|
149
165
|
features,
|
|
166
|
+
addons,
|
|
150
167
|
plans,
|
|
151
168
|
});
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
`,
|
|
170
|
+
root: `import config from "./revstack";
|
|
171
|
+
|
|
172
|
+
export default config;
|
|
173
|
+
`
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// src/commands/templates/b2b-saas.ts
|
|
177
|
+
var b2bSaas = {
|
|
178
|
+
features: `import { defineFeature } from "@revstackhq/core";
|
|
179
|
+
|
|
180
|
+
export const features = {
|
|
181
|
+
active_users: defineFeature({ name: "Active Users", type: "static", unit_type: "count" }),
|
|
182
|
+
api_access: defineFeature({ name: "API Access", type: "boolean", unit_type: "custom" }),
|
|
183
|
+
custom_domain: defineFeature({ name: "Custom Domain", type: "boolean", unit_type: "custom" }),
|
|
184
|
+
};
|
|
185
|
+
`,
|
|
186
|
+
addons: `import { defineAddon } from "@revstackhq/core";
|
|
187
|
+
import { features } from "./features";
|
|
188
|
+
|
|
189
|
+
export const addons = {
|
|
190
|
+
extra_users: defineAddon<typeof features>({
|
|
191
|
+
name: "10 Extra Users",
|
|
192
|
+
description: "Add 10 more active users to your workspace.",
|
|
193
|
+
type: "recurring",
|
|
194
|
+
prices: [
|
|
195
|
+
{ amount: 5000, currency: "USD", billing_interval: "monthly" }
|
|
196
|
+
],
|
|
197
|
+
features: {
|
|
198
|
+
active_users: { value_limit: 10, type: "increment", is_hard_limit: true },
|
|
199
|
+
}
|
|
200
|
+
}),
|
|
201
|
+
dedicated_support: defineAddon<typeof features>({
|
|
202
|
+
name: "Dedicated Support",
|
|
203
|
+
description: "Enterprise SLA with 1-hour response time.",
|
|
204
|
+
type: "recurring",
|
|
205
|
+
prices: [
|
|
206
|
+
{ amount: 49900, currency: "USD", billing_interval: "monthly" }
|
|
207
|
+
],
|
|
208
|
+
features: {}
|
|
209
|
+
})
|
|
210
|
+
};
|
|
211
|
+
`,
|
|
212
|
+
plans: `import { definePlan } from "@revstackhq/core";
|
|
213
|
+
import { features } from "./features";
|
|
214
|
+
|
|
215
|
+
export const plans = {
|
|
216
|
+
default: definePlan<typeof features>({
|
|
217
|
+
name: "Default",
|
|
218
|
+
description: "Automatically created default plan for guests.",
|
|
219
|
+
is_default: true,
|
|
220
|
+
is_public: false,
|
|
221
|
+
type: "free",
|
|
222
|
+
features: {},
|
|
223
|
+
}),
|
|
224
|
+
startup: definePlan<typeof features>({
|
|
225
|
+
name: "Startup",
|
|
226
|
+
description: "For small teams getting started.",
|
|
227
|
+
is_default: false,
|
|
228
|
+
is_public: true,
|
|
229
|
+
type: "paid",
|
|
230
|
+
available_addons: ["extra_users"],
|
|
231
|
+
prices: [
|
|
232
|
+
{ amount: 9900, currency: "USD", billing_interval: "monthly" }
|
|
233
|
+
],
|
|
234
|
+
features: {
|
|
235
|
+
active_users: { value_limit: 10, is_hard_limit: true },
|
|
236
|
+
api_access: { value_bool: false },
|
|
237
|
+
custom_domain: { value_bool: false },
|
|
238
|
+
},
|
|
239
|
+
}),
|
|
240
|
+
enterprise: definePlan<typeof features>({
|
|
241
|
+
name: "Enterprise",
|
|
242
|
+
description: "Advanced features for scale.",
|
|
243
|
+
is_default: false,
|
|
244
|
+
is_public: true,
|
|
245
|
+
type: "paid",
|
|
246
|
+
available_addons: ["extra_users", "dedicated_support"],
|
|
247
|
+
prices: [
|
|
248
|
+
{ amount: 49900, currency: "USD", billing_interval: "monthly" }
|
|
249
|
+
],
|
|
250
|
+
features: {
|
|
251
|
+
active_users: { value_limit: 100, is_hard_limit: false },
|
|
252
|
+
api_access: { value_bool: true },
|
|
253
|
+
custom_domain: { value_bool: true },
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
};
|
|
257
|
+
`,
|
|
258
|
+
index: `import { defineConfig } from "@revstackhq/core";
|
|
259
|
+
import { features } from "./features";
|
|
260
|
+
import { addons } from "./addons";
|
|
261
|
+
import { plans } from "./plans";
|
|
262
|
+
|
|
263
|
+
export default defineConfig({
|
|
264
|
+
features,
|
|
265
|
+
addons,
|
|
266
|
+
plans,
|
|
267
|
+
});
|
|
268
|
+
`,
|
|
269
|
+
root: `import config from "./revstack";
|
|
270
|
+
|
|
271
|
+
export default config;
|
|
272
|
+
`
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// src/commands/templates/usage-based.ts
|
|
276
|
+
var usageBased = {
|
|
277
|
+
features: `import { defineFeature } from "@revstackhq/core";
|
|
278
|
+
|
|
279
|
+
export const features = {
|
|
280
|
+
api_requests: defineFeature({ name: "API Requests", type: "metered", unit_type: "requests" }),
|
|
281
|
+
storage_gb: defineFeature({ name: "Storage (GB)", type: "metered", unit_type: "custom" }),
|
|
282
|
+
};
|
|
283
|
+
`,
|
|
284
|
+
addons: `import { defineAddon } from "@revstackhq/core";
|
|
285
|
+
import { features } from "./features";
|
|
286
|
+
|
|
287
|
+
export const addons = {
|
|
288
|
+
premium_support: defineAddon<typeof features>({
|
|
289
|
+
name: "Premium Support",
|
|
290
|
+
description: "24/7 dedicated support.",
|
|
291
|
+
type: "recurring",
|
|
292
|
+
prices: [
|
|
293
|
+
{ amount: 20000, currency: "USD", billing_interval: "monthly" }
|
|
294
|
+
],
|
|
295
|
+
features: {}
|
|
296
|
+
})
|
|
297
|
+
};
|
|
298
|
+
`,
|
|
299
|
+
plans: `import { definePlan } from "@revstackhq/core";
|
|
300
|
+
import { features } from "./features";
|
|
301
|
+
|
|
302
|
+
export const plans = {
|
|
303
|
+
default: definePlan<typeof features>({
|
|
304
|
+
name: "Default",
|
|
305
|
+
description: "Automatically created default plan for guests.",
|
|
306
|
+
is_default: true,
|
|
307
|
+
is_public: false,
|
|
308
|
+
type: "free",
|
|
309
|
+
features: {},
|
|
310
|
+
}),
|
|
311
|
+
pay_as_you_go: definePlan<typeof features>({
|
|
312
|
+
name: "Pay As You Go",
|
|
313
|
+
description: "Flexible usage-based pricing.",
|
|
314
|
+
is_default: false,
|
|
315
|
+
is_public: true,
|
|
316
|
+
type: "paid",
|
|
317
|
+
available_addons: ["premium_support"],
|
|
318
|
+
prices: [
|
|
319
|
+
{ amount: 0, currency: "USD", billing_interval: "monthly" } // Base platform fee
|
|
320
|
+
],
|
|
321
|
+
features: {
|
|
322
|
+
api_requests: { value_limit: 10000, is_hard_limit: false, reset_period: "monthly" }, // 10k free requests per month
|
|
323
|
+
storage_gb: { value_limit: 5, is_hard_limit: false, reset_period: "never" }, // 5GB free storage lifetime
|
|
324
|
+
},
|
|
325
|
+
}),
|
|
326
|
+
};
|
|
327
|
+
`,
|
|
328
|
+
index: `import { defineConfig } from "@revstackhq/core";
|
|
329
|
+
import { features } from "./features";
|
|
330
|
+
import { addons } from "./addons";
|
|
331
|
+
import { plans } from "./plans";
|
|
332
|
+
|
|
333
|
+
export default defineConfig({
|
|
334
|
+
features,
|
|
335
|
+
addons,
|
|
336
|
+
plans,
|
|
337
|
+
});
|
|
338
|
+
`,
|
|
339
|
+
root: `import config from "./revstack";
|
|
340
|
+
|
|
341
|
+
export default config;
|
|
342
|
+
`
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// src/commands/templates/index.ts
|
|
346
|
+
var TEMPLATES = {
|
|
347
|
+
starter,
|
|
348
|
+
"b2b-saas": b2bSaas,
|
|
349
|
+
"usage-based": usageBased
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
// src/commands/init.ts
|
|
353
|
+
var initCommand = new Command3("init").description("Scaffold a new revstack.config.ts in the current directory").option(
|
|
354
|
+
"-t, --template <name>",
|
|
355
|
+
"Choose a starting template (starter, b2b-saas, usage-based)",
|
|
356
|
+
"starter"
|
|
357
|
+
).action(async (options) => {
|
|
358
|
+
const templateName = options.template || "starter";
|
|
359
|
+
const template = TEMPLATES[templateName];
|
|
360
|
+
if (!template) {
|
|
361
|
+
console.log(
|
|
362
|
+
chalk3.red(
|
|
363
|
+
`
|
|
364
|
+
\u2716 Unknown template "${templateName}". Available templates: ${Object.keys(TEMPLATES).join(", ")}
|
|
365
|
+
`
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
154
370
|
const cwd = process.cwd();
|
|
155
371
|
const configPath = path2.resolve(cwd, "revstack.config.ts");
|
|
156
|
-
const revstackDir = path2.resolve(cwd, "revstack");
|
|
157
|
-
const featuresPath = path2.resolve(revstackDir, "features.ts");
|
|
158
|
-
const plansPath = path2.resolve(revstackDir, "plans.ts");
|
|
159
372
|
if (fs2.existsSync(configPath)) {
|
|
160
373
|
console.log(
|
|
161
374
|
"\n" + chalk3.yellow(" \u26A0 revstack.config.ts already exists.\n") + chalk3.dim(" Delete it first if you want to start fresh.\n")
|
|
162
375
|
);
|
|
163
376
|
process.exit(1);
|
|
164
377
|
}
|
|
378
|
+
const revstackDir = path2.resolve(cwd, "revstack");
|
|
165
379
|
if (!fs2.existsSync(revstackDir)) {
|
|
166
380
|
fs2.mkdirSync(revstackDir, { recursive: true });
|
|
167
381
|
}
|
|
168
|
-
fs2.writeFileSync(
|
|
169
|
-
|
|
170
|
-
|
|
382
|
+
fs2.writeFileSync(
|
|
383
|
+
path2.resolve(revstackDir, "features.ts"),
|
|
384
|
+
template.features,
|
|
385
|
+
"utf-8"
|
|
386
|
+
);
|
|
387
|
+
fs2.writeFileSync(
|
|
388
|
+
path2.resolve(revstackDir, "addons.ts"),
|
|
389
|
+
template.addons,
|
|
390
|
+
"utf-8"
|
|
391
|
+
);
|
|
392
|
+
fs2.writeFileSync(
|
|
393
|
+
path2.resolve(revstackDir, "plans.ts"),
|
|
394
|
+
template.plans,
|
|
395
|
+
"utf-8"
|
|
396
|
+
);
|
|
397
|
+
fs2.writeFileSync(
|
|
398
|
+
path2.resolve(revstackDir, "index.ts"),
|
|
399
|
+
template.index,
|
|
400
|
+
"utf-8"
|
|
401
|
+
);
|
|
402
|
+
fs2.writeFileSync(configPath, template.root, "utf-8");
|
|
171
403
|
let packageManager = "npm";
|
|
172
404
|
if (fs2.existsSync(path2.resolve(cwd, "pnpm-lock.yaml"))) {
|
|
173
405
|
packageManager = "pnpm";
|
|
@@ -186,8 +418,15 @@ var initCommand = new Command3("init").description("Scaffold a new revstack.conf
|
|
|
186
418
|
const spinner = ora("Installing @revstackhq/core...").start();
|
|
187
419
|
let installFailed = false;
|
|
188
420
|
try {
|
|
189
|
-
const
|
|
190
|
-
const
|
|
421
|
+
const cliDir = path2.dirname(fileURLToPath(import.meta.url));
|
|
422
|
+
const pkgJsonPath = path2.resolve(cliDir, "../../package.json");
|
|
423
|
+
let cliVersion = "dev";
|
|
424
|
+
try {
|
|
425
|
+
const pkgData = fs2.readFileSync(pkgJsonPath, "utf-8");
|
|
426
|
+
cliVersion = JSON.parse(pkgData).version;
|
|
427
|
+
} catch (e) {
|
|
428
|
+
}
|
|
429
|
+
const tag = cliVersion.includes("dev") ? `@${cliVersion}` : "@latest";
|
|
191
430
|
const pkgName = `@revstackhq/core${tag}`;
|
|
192
431
|
const installArgs = packageManager === "yarn" ? ["add", pkgName] : packageManager === "pnpm" ? ["add", pkgName] : ["install", pkgName];
|
|
193
432
|
let result = spawnSync(packageManager, installArgs, { cwd, shell: true });
|
|
@@ -217,9 +456,9 @@ var initCommand = new Command3("init").description("Scaffold a new revstack.conf
|
|
|
217
456
|
);
|
|
218
457
|
}
|
|
219
458
|
console.log(
|
|
220
|
-
"\n" + chalk3.green(" \u2714 Created revstack config structure\n") + "\n" + chalk3.dim(" Includes the ") + chalk3.white("Default Guest Plan") + chalk3.dim(" (required by Revstack).\n") + "
|
|
221
|
-
"Run " + chalk3.bold(packageManager + " install @revstackhq/core") + " manually
|
|
222
|
-
) : "") + chalk3.dim(" 1. ") + chalk3.white("Edit the config to match your billing model
|
|
459
|
+
"\n" + chalk3.green(" \u2714 Created revstack config structure\n") + "\n" + chalk3.dim(" Includes the ") + chalk3.white("Default Guest Plan") + chalk3.dim(" (required by Revstack).\n") + "\n" + chalk3.dim(" Next steps:\n") + (installFailed ? chalk3.dim(" 0. ") + chalk3.white(
|
|
460
|
+
"Run " + chalk3.bold(packageManager + " install @revstackhq/core") + " manually\n"
|
|
461
|
+
) : "") + chalk3.dim(" 1. ") + chalk3.white("Edit the config to match your billing model\n") + chalk3.dim(" 2. ") + chalk3.white("Run ") + chalk3.bold("revstack login") + chalk3.white(" to authenticate\n") + chalk3.dim(" 3. ") + chalk3.white("Run ") + chalk3.bold("revstack push") + chalk3.white(" to deploy\n")
|
|
223
462
|
);
|
|
224
463
|
});
|
|
225
464
|
|
|
@@ -258,6 +497,7 @@ async function loadLocalConfig(cwd) {
|
|
|
258
497
|
}
|
|
259
498
|
|
|
260
499
|
// src/commands/push.ts
|
|
500
|
+
import { validateConfig, RevstackValidationError } from "@revstackhq/core";
|
|
261
501
|
var API_BASE = "https://app.revstack.dev";
|
|
262
502
|
var DIFF_ICONS = {
|
|
263
503
|
added: chalk5.green(" + "),
|
|
@@ -300,6 +540,37 @@ function requireAuth() {
|
|
|
300
540
|
var pushCommand = new Command4("push").description("Push your local billing config to Revstack Cloud").option("-e, --env <environment>", "Target environment", "test").action(async (options) => {
|
|
301
541
|
const apiKey = requireAuth();
|
|
302
542
|
const config = await loadLocalConfig(process.cwd());
|
|
543
|
+
const validationSpinner = ora2({
|
|
544
|
+
text: "Validating billing configuration...",
|
|
545
|
+
prefixText: " "
|
|
546
|
+
}).start();
|
|
547
|
+
try {
|
|
548
|
+
validateConfig(config);
|
|
549
|
+
validationSpinner.succeed("Configuration validated");
|
|
550
|
+
} catch (error) {
|
|
551
|
+
if (error instanceof RevstackValidationError || error?.name === "RevstackValidationError") {
|
|
552
|
+
validationSpinner.fail("Configuration invalid");
|
|
553
|
+
console.error(
|
|
554
|
+
chalk5.red(
|
|
555
|
+
"\n \u2716 The billing configuration contains business logic errors:\n"
|
|
556
|
+
)
|
|
557
|
+
);
|
|
558
|
+
for (const err of error.errors || []) {
|
|
559
|
+
console.error(chalk5.red(` \u2022 ${err}`));
|
|
560
|
+
}
|
|
561
|
+
console.log();
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
564
|
+
validationSpinner.fail("Validation failed");
|
|
565
|
+
console.error(
|
|
566
|
+
chalk5.red(
|
|
567
|
+
`
|
|
568
|
+
An unexpected error occurred during validation: ${error?.message || String(error)}
|
|
569
|
+
`
|
|
570
|
+
)
|
|
571
|
+
);
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
303
574
|
const spinner = ora2({
|
|
304
575
|
text: "Calculating diff...",
|
|
305
576
|
prefixText: " "
|