atmn 1.0.0-beta.2 → 1.0.0-beta.3
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/dist/{chunk-UM3AMTOI.js → chunk-HILICWQ7.js} +5 -38
- package/dist/{chunk-PKRTTZCX.js → chunk-NBLVYKWE.js} +28 -15
- package/dist/chunk-TBJ5X4CL.js +234 -0
- package/dist/chunk-W6GJPEQT.js +136 -0
- package/dist/cli.cjs +900 -191
- package/dist/cli.js +831 -139
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +16 -139
- package/dist/index.d.ts +16 -139
- package/dist/index.js +1 -1
- package/dist/pull-7TNJV27W.js +2 -0
- package/dist/pull-OYMHOGNI.js +2 -0
- package/dist/source/compose/builders/builderFunctions.d.ts +82 -0
- package/dist/source/compose/index.d.ts +10 -0
- package/dist/source/compose/models/featureModels.d.ts +53 -0
- package/dist/source/compose/models/index.d.ts +2 -0
- package/dist/source/compose/models/planModels.d.ts +169 -0
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.js +52 -0
- package/dist/src/cli.js +131456 -0
- package/dist/{utils-GPT5AGIL.js → utils-ODRGTBFC.js} +1 -1
- package/dist/utils-U2K6DGVZ.js +1 -0
- package/package.json +26 -7
- package/readme.md +2 -2
- package/dist/pull-HKJ5B3AS.js +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isLocalFlag, readFromEnv } from './chunk-
|
|
1
|
+
import { isLocalFlag, readFromEnv } from './chunk-W6GJPEQT.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import axios, { AxiosError } from 'axios';
|
|
4
4
|
|
|
@@ -28,7 +28,7 @@ export const pro = plan({
|
|
|
28
28
|
name: 'Pro',
|
|
29
29
|
description: 'Professional plan for growing teams',
|
|
30
30
|
add_on: false,
|
|
31
|
-
|
|
31
|
+
auto_enable: false,
|
|
32
32
|
price: {
|
|
33
33
|
amount: 50,
|
|
34
34
|
interval: 'month',
|
|
@@ -48,16 +48,13 @@ export const pro = plan({
|
|
|
48
48
|
price: {
|
|
49
49
|
amount: 10,
|
|
50
50
|
interval: 'month',
|
|
51
|
-
|
|
51
|
+
billing_method: 'pay_per_use',
|
|
52
52
|
billing_units: 1,
|
|
53
53
|
},
|
|
54
54
|
}),
|
|
55
55
|
],
|
|
56
56
|
});
|
|
57
57
|
`;
|
|
58
|
-
|
|
59
|
-
// source/core/api.ts
|
|
60
|
-
var INTERNAL_BASE = BACKEND_URL;
|
|
61
58
|
var EXTERNAL_BASE = `${BACKEND_URL}/v1`;
|
|
62
59
|
async function request({
|
|
63
60
|
method,
|
|
@@ -72,7 +69,6 @@ async function request({
|
|
|
72
69
|
bypass
|
|
73
70
|
}) {
|
|
74
71
|
if (isLocalFlag()) {
|
|
75
|
-
INTERNAL_BASE = "http://localhost:8080";
|
|
76
72
|
EXTERNAL_BASE = "http://localhost:8080/v1";
|
|
77
73
|
if (base) {
|
|
78
74
|
base = base.replace(BACKEND_URL, "http://localhost:8080");
|
|
@@ -118,23 +114,6 @@ ${chalk.bgRed.white.bold(" API REQUEST FAILED ")}`);
|
|
|
118
114
|
process.exit(1);
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
|
-
async function internalRequest({
|
|
122
|
-
method,
|
|
123
|
-
path,
|
|
124
|
-
data,
|
|
125
|
-
headers,
|
|
126
|
-
customAuth
|
|
127
|
-
}) {
|
|
128
|
-
return await request({
|
|
129
|
-
method,
|
|
130
|
-
base: INTERNAL_BASE,
|
|
131
|
-
path,
|
|
132
|
-
data,
|
|
133
|
-
headers,
|
|
134
|
-
customAuth,
|
|
135
|
-
bypass: true
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
117
|
async function externalRequest({
|
|
139
118
|
method,
|
|
140
119
|
path,
|
|
@@ -171,18 +150,6 @@ async function deletePlan({
|
|
|
171
150
|
queryParams: { all_versions: !!allVersions }
|
|
172
151
|
});
|
|
173
152
|
}
|
|
174
|
-
async function updateCLIStripeKeys({
|
|
175
|
-
stripeSecretKey,
|
|
176
|
-
autumnSecretKey
|
|
177
|
-
}) {
|
|
178
|
-
return await request({
|
|
179
|
-
base: EXTERNAL_BASE,
|
|
180
|
-
method: "POST",
|
|
181
|
-
path: "/organization/stripe",
|
|
182
|
-
data: { secret_key: stripeSecretKey },
|
|
183
|
-
secretKey: autumnSecretKey
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
153
|
|
|
187
154
|
// source/core/pull.ts
|
|
188
155
|
async function getPlans(ids) {
|
|
@@ -236,7 +203,7 @@ async function getFeatures(params) {
|
|
|
236
203
|
path: "/features",
|
|
237
204
|
queryParams: { include_archived: params?.includeArchived ? true : false }
|
|
238
205
|
});
|
|
239
|
-
return list
|
|
206
|
+
return list;
|
|
240
207
|
}
|
|
241
208
|
var MAX_RECURSION_LIMIT = 500;
|
|
242
209
|
async function getCustomers(limit = 100, offset = 0) {
|
|
@@ -264,4 +231,4 @@ async function getCustomers(limit = 100, offset = 0) {
|
|
|
264
231
|
return customers;
|
|
265
232
|
}
|
|
266
233
|
|
|
267
|
-
export { DEFAULT_CONFIG, FRONTEND_URL, deleteFeature, deletePlan, externalRequest, getAllPlanVariants, getAllPlans, getCustomers, getFeatures, getPlans
|
|
234
|
+
export { BACKEND_URL, DEFAULT_CONFIG, FRONTEND_URL, deleteFeature, deletePlan, externalRequest, getAllPlanVariants, getAllPlans, getCustomers, getFeatures, getPlans };
|
|
@@ -4,16 +4,28 @@ import dotenv from 'dotenv';
|
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import yoctoSpinner from 'yocto-spinner';
|
|
6
6
|
|
|
7
|
+
// source/core/utils.ts
|
|
8
|
+
|
|
9
|
+
// source/core/cliContext.ts
|
|
10
|
+
var context = {
|
|
11
|
+
prod: false,
|
|
12
|
+
local: false
|
|
13
|
+
};
|
|
14
|
+
function isProd() {
|
|
15
|
+
return context.prod;
|
|
16
|
+
}
|
|
17
|
+
function isLocal() {
|
|
18
|
+
return context.local;
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
// source/core/utils.ts
|
|
8
22
|
var notNullish = (value) => value !== null && value !== void 0;
|
|
9
23
|
var nullish = (value) => value === null || value === void 0;
|
|
10
24
|
var isProdFlag = () => {
|
|
11
|
-
|
|
12
|
-
return prodFlag;
|
|
25
|
+
return isProd();
|
|
13
26
|
};
|
|
14
27
|
var isLocalFlag = () => {
|
|
15
|
-
|
|
16
|
-
return localFlag;
|
|
28
|
+
return isLocal();
|
|
17
29
|
};
|
|
18
30
|
function snakeCaseToCamelCase(value) {
|
|
19
31
|
return value.replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
@@ -34,21 +46,22 @@ function idToVar({
|
|
|
34
46
|
async function upsertEnvVar(filePath, varName, newValue) {
|
|
35
47
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
36
48
|
const lines = content.split("\n");
|
|
37
|
-
let
|
|
49
|
+
let foundIndex = -1;
|
|
38
50
|
for (let i = 0; i < lines.length; i++) {
|
|
39
51
|
if (lines[i]?.startsWith(`${varName}=`)) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
default: false
|
|
43
|
-
});
|
|
44
|
-
if (shouldOverwrite) {
|
|
45
|
-
lines[i] = `${varName}=${newValue}`;
|
|
46
|
-
found = true;
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
52
|
+
foundIndex = i;
|
|
53
|
+
break;
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
|
-
if (
|
|
56
|
+
if (foundIndex !== -1) {
|
|
57
|
+
const shouldOverwrite = await confirm({
|
|
58
|
+
message: `${varName} already exists in .env. Overwrite?`,
|
|
59
|
+
default: false
|
|
60
|
+
});
|
|
61
|
+
if (shouldOverwrite) {
|
|
62
|
+
lines[foundIndex] = `${varName}=${newValue}`;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
52
65
|
lines.push(`${varName}=${newValue}`);
|
|
53
66
|
}
|
|
54
67
|
fs.writeFileSync(filePath, lines.join("\n"));
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { isLocalFlag, readFromEnv } from './chunk-NBLVYKWE.js';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import axios, { AxiosError } from 'axios';
|
|
4
|
+
|
|
5
|
+
// source/constants.ts
|
|
6
|
+
var FRONTEND_URL = "http://localhost:3000";
|
|
7
|
+
var BACKEND_URL = "http://localhost:8080";
|
|
8
|
+
var DEFAULT_CONFIG = `import {
|
|
9
|
+
feature,
|
|
10
|
+
plan,
|
|
11
|
+
planFeature,
|
|
12
|
+
} from 'atmn';
|
|
13
|
+
|
|
14
|
+
export const seats = feature({
|
|
15
|
+
id: 'seats',
|
|
16
|
+
name: 'Seats',
|
|
17
|
+
type: 'continuous_use',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const messages = feature({
|
|
21
|
+
id: 'messages',
|
|
22
|
+
name: 'Messages',
|
|
23
|
+
type: 'single_use',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const pro = plan({
|
|
27
|
+
id: 'pro',
|
|
28
|
+
name: 'Pro',
|
|
29
|
+
description: 'Professional plan for growing teams',
|
|
30
|
+
add_on: false,
|
|
31
|
+
auto_enable: false,
|
|
32
|
+
price: {
|
|
33
|
+
amount: 50,
|
|
34
|
+
interval: 'month',
|
|
35
|
+
},
|
|
36
|
+
features: [
|
|
37
|
+
// 500 messages per month
|
|
38
|
+
planFeature({
|
|
39
|
+
feature_id: messages.id,
|
|
40
|
+
granted: 500,
|
|
41
|
+
reset: { interval: 'month' },
|
|
42
|
+
}),
|
|
43
|
+
|
|
44
|
+
// $10 per seat per month
|
|
45
|
+
planFeature({
|
|
46
|
+
feature_id: seats.id,
|
|
47
|
+
granted: 1,
|
|
48
|
+
price: {
|
|
49
|
+
amount: 10,
|
|
50
|
+
interval: 'month',
|
|
51
|
+
billing_method: 'pay_per_use',
|
|
52
|
+
billing_units: 1,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
`;
|
|
58
|
+
var EXTERNAL_BASE = `${BACKEND_URL}/v1`;
|
|
59
|
+
async function request({
|
|
60
|
+
method,
|
|
61
|
+
base,
|
|
62
|
+
path,
|
|
63
|
+
data,
|
|
64
|
+
headers,
|
|
65
|
+
customAuth,
|
|
66
|
+
throwOnError = true,
|
|
67
|
+
secretKey,
|
|
68
|
+
queryParams,
|
|
69
|
+
bypass
|
|
70
|
+
}) {
|
|
71
|
+
if (isLocalFlag()) {
|
|
72
|
+
EXTERNAL_BASE = "http://localhost:8080/v1";
|
|
73
|
+
if (base) {
|
|
74
|
+
base = base.replace(BACKEND_URL, "http://localhost:8080");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const apiKey = secretKey || readFromEnv({ bypass });
|
|
78
|
+
try {
|
|
79
|
+
const response = await axios.request({
|
|
80
|
+
method,
|
|
81
|
+
url: `${base}${path}`,
|
|
82
|
+
data,
|
|
83
|
+
params: queryParams,
|
|
84
|
+
headers: {
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
"X-API-Version": "2.0.0",
|
|
87
|
+
...headers,
|
|
88
|
+
Authorization: customAuth || `Bearer ${apiKey}`
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return response.data;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (throwOnError) {
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
console.error(`
|
|
97
|
+
${chalk.bgRed.white.bold(" API REQUEST FAILED ")}`);
|
|
98
|
+
const methodPath = `${method.toUpperCase()} ${base}${path}`;
|
|
99
|
+
console.error(chalk.red(methodPath));
|
|
100
|
+
if (error instanceof AxiosError) {
|
|
101
|
+
const status = error.response?.status;
|
|
102
|
+
const data2 = error.response?.data;
|
|
103
|
+
const code = data2?.code || data2?.error || "unknown_error";
|
|
104
|
+
const message = data2?.message || error.message || "An unknown error occurred";
|
|
105
|
+
if (status) {
|
|
106
|
+
console.error(chalk.redBright(`[${status}] ${code}`));
|
|
107
|
+
}
|
|
108
|
+
console.error(chalk.red(message));
|
|
109
|
+
} else if (error instanceof Error) {
|
|
110
|
+
console.error(chalk.red(error.message));
|
|
111
|
+
} else {
|
|
112
|
+
console.error(chalk.red(String(error)));
|
|
113
|
+
}
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function externalRequest({
|
|
118
|
+
method,
|
|
119
|
+
path,
|
|
120
|
+
data,
|
|
121
|
+
headers,
|
|
122
|
+
customAuth,
|
|
123
|
+
throwOnError = false,
|
|
124
|
+
queryParams
|
|
125
|
+
}) {
|
|
126
|
+
return await request({
|
|
127
|
+
method,
|
|
128
|
+
base: EXTERNAL_BASE,
|
|
129
|
+
path,
|
|
130
|
+
data,
|
|
131
|
+
headers,
|
|
132
|
+
customAuth,
|
|
133
|
+
throwOnError,
|
|
134
|
+
queryParams
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async function deleteFeature({ id }) {
|
|
138
|
+
return await externalRequest({
|
|
139
|
+
method: "DELETE",
|
|
140
|
+
path: `/features/${id}`
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async function deletePlan({
|
|
144
|
+
id,
|
|
145
|
+
allVersions
|
|
146
|
+
}) {
|
|
147
|
+
return await externalRequest({
|
|
148
|
+
method: "DELETE",
|
|
149
|
+
path: `/products/${id}`,
|
|
150
|
+
queryParams: { all_versions: !!allVersions }
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// source/core/pull.ts
|
|
155
|
+
async function getPlans(ids) {
|
|
156
|
+
return await Promise.all(
|
|
157
|
+
ids.map(
|
|
158
|
+
(id) => externalRequest({
|
|
159
|
+
method: "GET",
|
|
160
|
+
path: `/products/${id}`
|
|
161
|
+
})
|
|
162
|
+
)
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
async function getAllPlans(params) {
|
|
166
|
+
const { list: plans } = await externalRequest({
|
|
167
|
+
method: "GET",
|
|
168
|
+
path: `/products`,
|
|
169
|
+
queryParams: { include_archived: params?.archived ? true : false }
|
|
170
|
+
});
|
|
171
|
+
return [...plans];
|
|
172
|
+
}
|
|
173
|
+
async function getAllPlanVariants() {
|
|
174
|
+
const { list } = await externalRequest({
|
|
175
|
+
method: "GET",
|
|
176
|
+
path: "/products"
|
|
177
|
+
});
|
|
178
|
+
const allPlans = [];
|
|
179
|
+
allPlans.push(
|
|
180
|
+
...list.flatMap((plan) => {
|
|
181
|
+
if (plan.version > 1) {
|
|
182
|
+
return Array.from({ length: plan.version }, (_, i) => ({
|
|
183
|
+
id: plan.id,
|
|
184
|
+
name: plan.name,
|
|
185
|
+
version: i + 1
|
|
186
|
+
}));
|
|
187
|
+
} else {
|
|
188
|
+
return [
|
|
189
|
+
{
|
|
190
|
+
id: plan.id,
|
|
191
|
+
name: plan.name,
|
|
192
|
+
version: plan.version
|
|
193
|
+
}
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
return allPlans;
|
|
199
|
+
}
|
|
200
|
+
async function getFeatures(params) {
|
|
201
|
+
const { list } = await externalRequest({
|
|
202
|
+
method: "GET",
|
|
203
|
+
path: "/features",
|
|
204
|
+
queryParams: { include_archived: params?.includeArchived ? true : false }
|
|
205
|
+
});
|
|
206
|
+
return list;
|
|
207
|
+
}
|
|
208
|
+
var MAX_RECURSION_LIMIT = 500;
|
|
209
|
+
async function getCustomers(limit = 100, offset = 0) {
|
|
210
|
+
const { list, total } = await externalRequest({
|
|
211
|
+
method: "GET",
|
|
212
|
+
path: `/customers?limit=${limit}&offset=${offset}`
|
|
213
|
+
});
|
|
214
|
+
const customers = list.map(
|
|
215
|
+
(customer) => ({
|
|
216
|
+
id: customer.id,
|
|
217
|
+
text: customer.name || customer.email || customer.id
|
|
218
|
+
})
|
|
219
|
+
);
|
|
220
|
+
if (offset + limit < total && offset < MAX_RECURSION_LIMIT) {
|
|
221
|
+
const remainingCustomers = await getCustomers(limit, offset + limit);
|
|
222
|
+
return [...customers, ...remainingCustomers];
|
|
223
|
+
} else if (offset >= MAX_RECURSION_LIMIT) {
|
|
224
|
+
console.log(
|
|
225
|
+
chalk.red(
|
|
226
|
+
`Reached maximum recursion limit of ${MAX_RECURSION_LIMIT} customers. Exiting.`
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
return customers;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export { BACKEND_URL, DEFAULT_CONFIG, FRONTEND_URL, deleteFeature, deletePlan, externalRequest, getAllPlanVariants, getAllPlans, getCustomers, getFeatures, getPlans };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import yoctoSpinner from 'yocto-spinner';
|
|
6
|
+
|
|
7
|
+
// source/core/utils.ts
|
|
8
|
+
|
|
9
|
+
// source/core/cliContext.ts
|
|
10
|
+
var context = {
|
|
11
|
+
prod: false,
|
|
12
|
+
local: false
|
|
13
|
+
};
|
|
14
|
+
function isProd() {
|
|
15
|
+
return context.prod;
|
|
16
|
+
}
|
|
17
|
+
function isLocal() {
|
|
18
|
+
return context.local;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// source/core/utils.ts
|
|
22
|
+
var notNullish = (value) => value !== null && value !== void 0;
|
|
23
|
+
var nullish = (value) => value === null || value === void 0;
|
|
24
|
+
var isProdFlag = () => {
|
|
25
|
+
return isProd();
|
|
26
|
+
};
|
|
27
|
+
var isLocalFlag = () => {
|
|
28
|
+
return isLocal();
|
|
29
|
+
};
|
|
30
|
+
function snakeCaseToCamelCase(value) {
|
|
31
|
+
return value.replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
32
|
+
}
|
|
33
|
+
function idToVar({
|
|
34
|
+
id,
|
|
35
|
+
prefix = "product"
|
|
36
|
+
}) {
|
|
37
|
+
const processed = id.replace(/[-_](.)/g, (_, letter) => letter.toUpperCase()).replace(/[^a-zA-Z0-9_$]/g, "");
|
|
38
|
+
if (/^[0-9]/.test(processed)) {
|
|
39
|
+
return `${prefix}${processed}`;
|
|
40
|
+
}
|
|
41
|
+
if (/^[^a-zA-Z_$]/.test(processed)) {
|
|
42
|
+
return `${prefix}${processed}`;
|
|
43
|
+
}
|
|
44
|
+
return processed;
|
|
45
|
+
}
|
|
46
|
+
async function upsertEnvVar(filePath, varName, newValue) {
|
|
47
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
48
|
+
const lines = content.split("\n");
|
|
49
|
+
let foundIndex = -1;
|
|
50
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51
|
+
if (lines[i]?.startsWith(`${varName}=`)) {
|
|
52
|
+
foundIndex = i;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (foundIndex !== -1) {
|
|
57
|
+
const shouldOverwrite = await confirm({
|
|
58
|
+
message: `${varName} already exists in .env. Overwrite?`,
|
|
59
|
+
default: false
|
|
60
|
+
});
|
|
61
|
+
if (shouldOverwrite) {
|
|
62
|
+
lines[foundIndex] = `${varName}=${newValue}`;
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
lines.push(`${varName}=${newValue}`);
|
|
66
|
+
}
|
|
67
|
+
fs.writeFileSync(filePath, lines.join("\n"));
|
|
68
|
+
}
|
|
69
|
+
async function storeToEnv(prodKey, sandboxKey) {
|
|
70
|
+
const envPath = `${process.cwd()}/.env`;
|
|
71
|
+
const envLocalPath = `${process.cwd()}/.env.local`;
|
|
72
|
+
const envVars = `AUTUMN_PROD_SECRET_KEY=${prodKey}
|
|
73
|
+
AUTUMN_SECRET_KEY=${sandboxKey}
|
|
74
|
+
`;
|
|
75
|
+
if (fs.existsSync(envPath)) {
|
|
76
|
+
await upsertEnvVar(envPath, "AUTUMN_PROD_SECRET_KEY", prodKey);
|
|
77
|
+
await upsertEnvVar(envPath, "AUTUMN_SECRET_KEY", sandboxKey);
|
|
78
|
+
console.log(chalk.green(".env file found. Updated keys."));
|
|
79
|
+
} else if (fs.existsSync(envLocalPath)) {
|
|
80
|
+
fs.writeFileSync(envPath, envVars);
|
|
81
|
+
console.log(
|
|
82
|
+
chalk.green(
|
|
83
|
+
".env.local found but .env not found. Created new .env file and wrote keys."
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
fs.writeFileSync(envPath, envVars);
|
|
88
|
+
console.log(
|
|
89
|
+
chalk.green(
|
|
90
|
+
"No .env or .env.local file found. Created new .env file and wrote keys."
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function getEnvVar(parsed, prodFlag) {
|
|
96
|
+
return parsed["AUTUMN_SECRET_KEY"];
|
|
97
|
+
}
|
|
98
|
+
function readFromEnv(options) {
|
|
99
|
+
const envPath = `${process.cwd()}/.env`;
|
|
100
|
+
const envLocalPath = `${process.cwd()}/.env.local`;
|
|
101
|
+
if (process.env["AUTUMN_SECRET_KEY"]) {
|
|
102
|
+
return process.env["AUTUMN_SECRET_KEY"];
|
|
103
|
+
}
|
|
104
|
+
let secretKey;
|
|
105
|
+
if (fs.existsSync(envPath) && !secretKey)
|
|
106
|
+
secretKey = getEnvVar(
|
|
107
|
+
dotenv.parse(fs.readFileSync(envPath, "utf-8")));
|
|
108
|
+
if (fs.existsSync(envLocalPath) && !secretKey)
|
|
109
|
+
secretKey = getEnvVar(
|
|
110
|
+
dotenv.parse(fs.readFileSync(envLocalPath, "utf-8")));
|
|
111
|
+
if (!secretKey && !options?.bypass) {
|
|
112
|
+
{
|
|
113
|
+
console.error(
|
|
114
|
+
"[Error] atmn uses the AUTUMN_SECRET_KEY to call the Autumn sandbox API. Please add it to your .env (or .env.local) file or run `atmn login` to authenticate."
|
|
115
|
+
);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return secretKey;
|
|
120
|
+
}
|
|
121
|
+
function initSpinner(message) {
|
|
122
|
+
const spinner = yoctoSpinner({
|
|
123
|
+
text: message
|
|
124
|
+
});
|
|
125
|
+
spinner.start();
|
|
126
|
+
return spinner;
|
|
127
|
+
}
|
|
128
|
+
async function isSandboxKey(apiKey) {
|
|
129
|
+
const prefix = apiKey.split("am_sk_")[1]?.split("_")[0];
|
|
130
|
+
if (prefix === "live") {
|
|
131
|
+
return false;
|
|
132
|
+
} else if (prefix === "test") return true;
|
|
133
|
+
else throw new Error("Invalid API key");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { idToVar, initSpinner, isLocalFlag, isProdFlag, isSandboxKey, notNullish, nullish, readFromEnv, snakeCaseToCamelCase, storeToEnv };
|