owosk 0.2.3 → 0.3.0
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/README.md +7 -7
- package/dist/index.js +217 -140
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install -g owosk
|
|
|
13
13
|
Or use it directly with npx:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npx
|
|
16
|
+
npx owosk --help
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Commands
|
|
@@ -23,7 +23,7 @@ npx owo --help
|
|
|
23
23
|
Initialize a new Owostack project with a default configuration file (`owo.config.ts` or `owo.config.js`). JavaScript configs use ESM `import`/`export` syntax.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npx
|
|
26
|
+
npx owosk init
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
### `sync`
|
|
@@ -31,7 +31,7 @@ npx owo init
|
|
|
31
31
|
Push your local catalog configuration to the Owostack cloud.
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npx
|
|
34
|
+
npx owosk sync
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
### `pull`
|
|
@@ -39,7 +39,7 @@ npx owo sync
|
|
|
39
39
|
Pull existing plans and features from the cloud into your local configuration.
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
npx
|
|
42
|
+
npx owosk pull
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
### `diff`
|
|
@@ -47,7 +47,7 @@ npx owo pull
|
|
|
47
47
|
Preview changes by comparing your local configuration with the cloud.
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
npx
|
|
50
|
+
npx owosk diff
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
### `validate`
|
|
@@ -55,7 +55,7 @@ npx owo diff
|
|
|
55
55
|
Check your local configuration for errors without applying changes.
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
npx
|
|
58
|
+
npx owosk validate
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
### `connect`
|
|
@@ -63,7 +63,7 @@ npx owo validate
|
|
|
63
63
|
Authenticate and connect your local environment to an organization.
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
npx
|
|
66
|
+
npx owosk connect
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
## Features
|
package/dist/index.js
CHANGED
|
@@ -231,19 +231,51 @@ async function fetchCreditPacks(apiKey, apiUrl) {
|
|
|
231
231
|
// src/lib/diff.ts
|
|
232
232
|
import pc2 from "picocolors";
|
|
233
233
|
import * as p from "@clack/prompts";
|
|
234
|
-
function
|
|
234
|
+
function normalizeReset(reset) {
|
|
235
|
+
switch (reset) {
|
|
236
|
+
case "hour":
|
|
237
|
+
return "hourly";
|
|
238
|
+
case "day":
|
|
239
|
+
return "daily";
|
|
240
|
+
case "week":
|
|
241
|
+
return "weekly";
|
|
242
|
+
case "month":
|
|
243
|
+
return "monthly";
|
|
244
|
+
case "quarter":
|
|
245
|
+
return "quarterly";
|
|
246
|
+
case "year":
|
|
247
|
+
case "annually":
|
|
248
|
+
return "yearly";
|
|
249
|
+
default:
|
|
250
|
+
return reset || "monthly";
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function normalizeOverage(usageModel, overage) {
|
|
254
|
+
if (usageModel === "usage_based") return "charge";
|
|
255
|
+
return overage === "charge" ? "charge" : "block";
|
|
256
|
+
}
|
|
257
|
+
function normalizeFeature(pf, creditSystemSlugs) {
|
|
258
|
+
const usageModel = pf.usageModel || "included";
|
|
259
|
+
const isCreditSystemFeature = creditSystemSlugs.has(pf.slug);
|
|
235
260
|
return {
|
|
236
261
|
slug: pf.slug,
|
|
237
262
|
enabled: pf.enabled,
|
|
238
263
|
limit: pf.limit ?? null,
|
|
239
264
|
// Handle both SDK 'reset' and API 'resetInterval'
|
|
240
|
-
reset: pf.reset || pf.resetInterval
|
|
265
|
+
reset: normalizeReset(pf.reset || pf.resetInterval),
|
|
266
|
+
usageModel: isCreditSystemFeature ? "included" : usageModel,
|
|
267
|
+
pricePerUnit: isCreditSystemFeature ? null : pf.pricePerUnit ?? null,
|
|
268
|
+
billingUnits: isCreditSystemFeature ? 1 : pf.billingUnits ?? 1,
|
|
269
|
+
ratingModel: isCreditSystemFeature ? "package" : pf.ratingModel || "package",
|
|
270
|
+
tiers: isCreditSystemFeature ? null : pf.tiers ?? null,
|
|
241
271
|
// Handle both SDK 'overage' and API 'overage' (same name)
|
|
242
|
-
overage: pf.overage
|
|
243
|
-
overagePrice: pf.overagePrice ?? null
|
|
272
|
+
overage: normalizeOverage(usageModel, pf.overage),
|
|
273
|
+
overagePrice: isCreditSystemFeature ? null : pf.overagePrice ?? null,
|
|
274
|
+
maxOverageUnits: isCreditSystemFeature ? null : pf.maxOverageUnits ?? null,
|
|
275
|
+
creditCost: isCreditSystemFeature ? 0 : pf.creditCost ?? 0
|
|
244
276
|
};
|
|
245
277
|
}
|
|
246
|
-
function normalizePlan(plan) {
|
|
278
|
+
function normalizePlan(plan, creditSystemSlugs) {
|
|
247
279
|
return {
|
|
248
280
|
slug: plan.slug,
|
|
249
281
|
name: plan.name ?? null,
|
|
@@ -255,7 +287,18 @@ function normalizePlan(plan) {
|
|
|
255
287
|
trialDays: plan.trialDays ?? 0,
|
|
256
288
|
isAddon: plan.isAddon ?? false,
|
|
257
289
|
autoEnable: plan.autoEnable ?? false,
|
|
258
|
-
features: (plan.features || []).map(normalizeFeature).sort((a, b) => a.slug.localeCompare(b.slug))
|
|
290
|
+
features: (plan.features || []).map((feature) => normalizeFeature(feature, creditSystemSlugs)).sort((a, b) => a.slug.localeCompare(b.slug))
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function normalizeCreditSystem(cs) {
|
|
294
|
+
return {
|
|
295
|
+
slug: cs.slug,
|
|
296
|
+
name: cs.name ?? null,
|
|
297
|
+
description: cs.description ?? null,
|
|
298
|
+
features: (cs.features || []).map((feature) => ({
|
|
299
|
+
feature: feature.feature,
|
|
300
|
+
creditCost: feature.creditCost ?? 0
|
|
301
|
+
})).sort((a, b) => a.feature.localeCompare(b.feature))
|
|
259
302
|
};
|
|
260
303
|
}
|
|
261
304
|
function normalizeCreditPack(pack) {
|
|
@@ -271,10 +314,18 @@ function normalizeCreditPack(pack) {
|
|
|
271
314
|
};
|
|
272
315
|
}
|
|
273
316
|
function diffPlans(localPlans, remotePlans, localCreditSystems = [], remoteCreditSystems = [], localCreditPacks = [], remoteCreditPacks = []) {
|
|
317
|
+
const creditSystemSlugs = /* @__PURE__ */ new Set([
|
|
318
|
+
...localCreditSystems.map((cs) => cs.slug),
|
|
319
|
+
...remoteCreditSystems.map((cs) => cs.slug)
|
|
320
|
+
]);
|
|
274
321
|
const localMap = /* @__PURE__ */ new Map();
|
|
275
322
|
const remoteMap = /* @__PURE__ */ new Map();
|
|
276
|
-
for (const p9 of localPlans)
|
|
277
|
-
|
|
323
|
+
for (const p9 of localPlans) {
|
|
324
|
+
localMap.set(p9.slug, normalizePlan(p9, creditSystemSlugs));
|
|
325
|
+
}
|
|
326
|
+
for (const p9 of remotePlans) {
|
|
327
|
+
remoteMap.set(p9.slug, normalizePlan(p9, creditSystemSlugs));
|
|
328
|
+
}
|
|
278
329
|
const onlyLocal = [];
|
|
279
330
|
const onlyRemote = [];
|
|
280
331
|
const changed = [];
|
|
@@ -328,8 +379,15 @@ function diffPlans(localPlans, remotePlans, localCreditSystems = [], remoteCredi
|
|
|
328
379
|
"enabled",
|
|
329
380
|
"limit",
|
|
330
381
|
"reset",
|
|
382
|
+
"usageModel",
|
|
383
|
+
"pricePerUnit",
|
|
384
|
+
"billingUnits",
|
|
385
|
+
"ratingModel",
|
|
386
|
+
"tiers",
|
|
331
387
|
"overage",
|
|
332
|
-
"overagePrice"
|
|
388
|
+
"overagePrice",
|
|
389
|
+
"maxOverageUnits",
|
|
390
|
+
"creditCost"
|
|
333
391
|
];
|
|
334
392
|
for (const ff of featureFields) {
|
|
335
393
|
if (JSON.stringify(lf[ff]) !== JSON.stringify(rf[ff])) {
|
|
@@ -353,8 +411,12 @@ function diffPlans(localPlans, remotePlans, localCreditSystems = [], remoteCredi
|
|
|
353
411
|
}
|
|
354
412
|
const localCsMap = /* @__PURE__ */ new Map();
|
|
355
413
|
const remoteCsMap = /* @__PURE__ */ new Map();
|
|
356
|
-
for (const cs of localCreditSystems)
|
|
357
|
-
|
|
414
|
+
for (const cs of localCreditSystems) {
|
|
415
|
+
localCsMap.set(cs.slug, normalizeCreditSystem(cs));
|
|
416
|
+
}
|
|
417
|
+
for (const cs of remoteCreditSystems) {
|
|
418
|
+
remoteCsMap.set(cs.slug, normalizeCreditSystem(cs));
|
|
419
|
+
}
|
|
358
420
|
const csOnlyLocal = [];
|
|
359
421
|
const csOnlyRemote = [];
|
|
360
422
|
const csChanged = [];
|
|
@@ -779,7 +841,10 @@ import * as p3 from "@clack/prompts";
|
|
|
779
841
|
import pc4 from "picocolors";
|
|
780
842
|
import { existsSync as existsSync3 } from "fs";
|
|
781
843
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
782
|
-
import { resolve as resolve2,
|
|
844
|
+
import { resolve as resolve2, isAbsolute as isAbsolute2 } from "path";
|
|
845
|
+
|
|
846
|
+
// src/lib/catalog-import.ts
|
|
847
|
+
import { extname as extname2 } from "path";
|
|
783
848
|
|
|
784
849
|
// src/lib/generate.ts
|
|
785
850
|
function slugToIdentifier(slug, used) {
|
|
@@ -834,6 +899,28 @@ function slugToIdentifier(slug, used) {
|
|
|
834
899
|
used.add(candidate);
|
|
835
900
|
return candidate;
|
|
836
901
|
}
|
|
902
|
+
function normalizeResetForCodegen(reset) {
|
|
903
|
+
switch (reset) {
|
|
904
|
+
case void 0:
|
|
905
|
+
case null:
|
|
906
|
+
return void 0;
|
|
907
|
+
case "hour":
|
|
908
|
+
return "hourly";
|
|
909
|
+
case "day":
|
|
910
|
+
return "daily";
|
|
911
|
+
case "week":
|
|
912
|
+
return "weekly";
|
|
913
|
+
case "month":
|
|
914
|
+
return "monthly";
|
|
915
|
+
case "quarter":
|
|
916
|
+
return "quarterly";
|
|
917
|
+
case "year":
|
|
918
|
+
case "annually":
|
|
919
|
+
return "yearly";
|
|
920
|
+
default:
|
|
921
|
+
return reset;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
837
924
|
function generateConfig(plans, creditSystems = [], creditPacks = [], defaultProvider, format = "ts") {
|
|
838
925
|
const isTs = format === "ts";
|
|
839
926
|
const creditSystemSlugs = new Set(creditSystems.map((cs) => cs.slug));
|
|
@@ -925,8 +1012,12 @@ function generateConfig(plans, creditSystems = [], creditPacks = [], defaultProv
|
|
|
925
1012
|
const csVar = creditSystemVars.get(pf.slug);
|
|
926
1013
|
if (csVar && pf.enabled) {
|
|
927
1014
|
const opts = [];
|
|
928
|
-
|
|
929
|
-
|
|
1015
|
+
const creditReset = normalizeResetForCodegen(
|
|
1016
|
+
pf.resetInterval || pf.reset
|
|
1017
|
+
);
|
|
1018
|
+
if (creditReset !== void 0) {
|
|
1019
|
+
opts.push(`reset: "${creditReset}"`);
|
|
1020
|
+
}
|
|
930
1021
|
if (pf.overage) opts.push(`overage: "${pf.overage}"`);
|
|
931
1022
|
if (opts.length > 0) {
|
|
932
1023
|
featureEntries.push(
|
|
@@ -950,11 +1041,23 @@ function generateConfig(plans, creditSystems = [], creditPacks = [], defaultProv
|
|
|
950
1041
|
if (pf.enabled === false) {
|
|
951
1042
|
const config2 = { enabled: false };
|
|
952
1043
|
if (pf.limit !== void 0) config2.limit = pf.limit;
|
|
953
|
-
|
|
954
|
-
|
|
1044
|
+
const disabledReset = normalizeResetForCodegen(
|
|
1045
|
+
pf.resetInterval || pf.reset
|
|
1046
|
+
);
|
|
1047
|
+
if (disabledReset !== void 0) config2.reset = disabledReset;
|
|
1048
|
+
if (pf.usageModel) config2.usageModel = pf.usageModel;
|
|
1049
|
+
if (pf.pricePerUnit !== void 0)
|
|
1050
|
+
config2.pricePerUnit = pf.pricePerUnit;
|
|
1051
|
+
if (pf.ratingModel) config2.ratingModel = pf.ratingModel;
|
|
1052
|
+
if (pf.tiers !== void 0) config2.tiers = pf.tiers;
|
|
1053
|
+
if (pf.billingUnits !== void 0)
|
|
1054
|
+
config2.billingUnits = pf.billingUnits;
|
|
955
1055
|
if (pf.overage) config2.overage = pf.overage;
|
|
956
1056
|
if (pf.overagePrice !== void 0)
|
|
957
1057
|
config2.overagePrice = pf.overagePrice;
|
|
1058
|
+
if (pf.maxOverageUnits !== void 0)
|
|
1059
|
+
config2.maxOverageUnits = pf.maxOverageUnits;
|
|
1060
|
+
if (pf.creditCost !== void 0) config2.creditCost = pf.creditCost;
|
|
958
1061
|
featureEntries.push(`${varName}.config(${JSON.stringify(config2)})`);
|
|
959
1062
|
continue;
|
|
960
1063
|
}
|
|
@@ -962,11 +1065,21 @@ function generateConfig(plans, creditSystems = [], creditPacks = [], defaultProv
|
|
|
962
1065
|
const config = {};
|
|
963
1066
|
if (pf.limit !== void 0) config.limit = pf.limit;
|
|
964
1067
|
if (!isEntityFeature) {
|
|
965
|
-
const reset =
|
|
966
|
-
|
|
1068
|
+
const reset = normalizeResetForCodegen(
|
|
1069
|
+
pf.resetInterval || pf.reset || "monthly"
|
|
1070
|
+
);
|
|
1071
|
+
if (reset !== void 0) config.reset = reset;
|
|
967
1072
|
}
|
|
1073
|
+
if (pf.usageModel) config.usageModel = pf.usageModel;
|
|
1074
|
+
if (pf.pricePerUnit !== void 0) config.pricePerUnit = pf.pricePerUnit;
|
|
1075
|
+
if (pf.ratingModel) config.ratingModel = pf.ratingModel;
|
|
1076
|
+
if (pf.tiers !== void 0) config.tiers = pf.tiers;
|
|
1077
|
+
if (pf.billingUnits !== void 0) config.billingUnits = pf.billingUnits;
|
|
968
1078
|
if (pf.overage) config.overage = pf.overage;
|
|
969
1079
|
if (pf.overagePrice !== void 0) config.overagePrice = pf.overagePrice;
|
|
1080
|
+
if (pf.maxOverageUnits !== void 0)
|
|
1081
|
+
config.maxOverageUnits = pf.maxOverageUnits;
|
|
1082
|
+
if (pf.creditCost !== void 0) config.creditCost = pf.creditCost;
|
|
970
1083
|
const configKeys = Object.keys(config);
|
|
971
1084
|
const hasExtras = configKeys.some((k) => k !== "limit");
|
|
972
1085
|
if (config.limit === null && !hasExtras) {
|
|
@@ -1045,8 +1158,8 @@ function generateConfig(plans, creditSystems = [], creditPacks = [], defaultProv
|
|
|
1045
1158
|
].filter(Boolean).join("\n");
|
|
1046
1159
|
}
|
|
1047
1160
|
|
|
1048
|
-
// src/
|
|
1049
|
-
function
|
|
1161
|
+
// src/lib/catalog-import.ts
|
|
1162
|
+
function determineConfigFormat(fullPath) {
|
|
1050
1163
|
const ext = extname2(fullPath);
|
|
1051
1164
|
if (ext === ".ts" || ext === ".mts" || ext === ".cts") return "ts";
|
|
1052
1165
|
if (ext === ".mjs") return "esm";
|
|
@@ -1058,6 +1171,32 @@ function determineFormat(fullPath) {
|
|
|
1058
1171
|
if (ext === ".js") return "esm";
|
|
1059
1172
|
return "ts";
|
|
1060
1173
|
}
|
|
1174
|
+
async function buildRemoteCatalogSnapshot(params) {
|
|
1175
|
+
const plans = await fetchPlans({
|
|
1176
|
+
apiKey: params.apiKey,
|
|
1177
|
+
apiUrl: params.apiUrl,
|
|
1178
|
+
...params.filters || {}
|
|
1179
|
+
});
|
|
1180
|
+
const creditSystems = await fetchCreditSystems(params.apiKey, params.apiUrl);
|
|
1181
|
+
const creditPacks = await fetchCreditPacks(params.apiKey, params.apiUrl);
|
|
1182
|
+
const providers = new Set(plans.map((plan) => plan.provider).filter(Boolean));
|
|
1183
|
+
const defaultProvider = providers.size === 1 ? Array.from(providers)[0] : void 0;
|
|
1184
|
+
return {
|
|
1185
|
+
plans,
|
|
1186
|
+
creditSystems,
|
|
1187
|
+
creditPacks,
|
|
1188
|
+
defaultProvider,
|
|
1189
|
+
configContent: generateConfig(
|
|
1190
|
+
plans,
|
|
1191
|
+
creditSystems,
|
|
1192
|
+
creditPacks,
|
|
1193
|
+
defaultProvider,
|
|
1194
|
+
params.format
|
|
1195
|
+
)
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// src/commands/pull.ts
|
|
1061
1200
|
async function runPull(options) {
|
|
1062
1201
|
p3.intro(pc4.bgYellow(pc4.black(" pull ")));
|
|
1063
1202
|
let fullPath;
|
|
@@ -1080,105 +1219,53 @@ async function runPull(options) {
|
|
|
1080
1219
|
const filters = configSettings.filters || {};
|
|
1081
1220
|
let format;
|
|
1082
1221
|
try {
|
|
1083
|
-
format =
|
|
1222
|
+
format = determineConfigFormat(fullPath);
|
|
1084
1223
|
} catch (e) {
|
|
1085
1224
|
p3.log.error(pc4.red(e.message));
|
|
1086
1225
|
process.exit(1);
|
|
1087
1226
|
}
|
|
1088
1227
|
const s = p3.spinner();
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
plans
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
const configContent = generateConfig(
|
|
1110
|
-
plans,
|
|
1111
|
-
creditSystems,
|
|
1112
|
-
creditPacks,
|
|
1113
|
-
defaultProvider,
|
|
1114
|
-
format
|
|
1228
|
+
const modeLabel = options.prod ? "prod" : "sandbox";
|
|
1229
|
+
const modeMessage = options.prod ? pc4.magenta("Production Mode: Pulling from PROD environment") : pc4.cyan("Sandbox Mode: Pulling from SANDBOX environment");
|
|
1230
|
+
const apiUrl = `${options.prod ? liveUrl : testUrl}/api/v1`;
|
|
1231
|
+
p3.log.step(modeMessage);
|
|
1232
|
+
s.start(`Fetching remote catalog from ${pc4.dim(modeLabel)}...`);
|
|
1233
|
+
const snapshot = await buildRemoteCatalogSnapshot({
|
|
1234
|
+
apiKey,
|
|
1235
|
+
apiUrl,
|
|
1236
|
+
format,
|
|
1237
|
+
filters
|
|
1238
|
+
});
|
|
1239
|
+
s.stop(
|
|
1240
|
+
`Fetched ${snapshot.plans.length} plans, ${snapshot.creditSystems.length} credit systems, and ${snapshot.creditPacks.length} credit packs from ${modeLabel}`
|
|
1241
|
+
);
|
|
1242
|
+
if (options.dryRun) {
|
|
1243
|
+
p3.note(snapshot.configContent, "Generated Config (Dry Run)");
|
|
1244
|
+
printPullSummary(
|
|
1245
|
+
snapshot.plans,
|
|
1246
|
+
snapshot.creditSystems,
|
|
1247
|
+
snapshot.creditPacks
|
|
1115
1248
|
);
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
const confirm4 = await p3.confirm({
|
|
1124
|
-
message: `Config file already exists at ${fullPath}. Overwrite?`,
|
|
1125
|
-
initialValue: false
|
|
1126
|
-
});
|
|
1127
|
-
if (p3.isCancel(confirm4) || !confirm4) {
|
|
1128
|
-
p3.outro(pc4.yellow("Operation cancelled"));
|
|
1129
|
-
process.exit(0);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
await writeFile2(fullPath, configContent, "utf8");
|
|
1133
|
-
p3.log.success(pc4.green(`Wrote configuration to ${fullPath}`));
|
|
1134
|
-
printPullSummary(plans, creditSystems, creditPacks);
|
|
1135
|
-
} else {
|
|
1136
|
-
p3.log.step(pc4.cyan("Sandbox Mode: Pulling from SANDBOX environment"));
|
|
1137
|
-
const apiUrl = `${testUrl}/api/v1`;
|
|
1138
|
-
s.start(`Fetching plans from ${pc4.dim("sandbox")}...`);
|
|
1139
|
-
const plans = await fetchPlans({
|
|
1140
|
-
apiKey,
|
|
1141
|
-
apiUrl,
|
|
1142
|
-
...filters
|
|
1249
|
+
p3.outro(pc4.yellow("Dry run complete. No changes made."));
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
if (existsSync3(fullPath) && !options.force) {
|
|
1253
|
+
const confirm4 = await p3.confirm({
|
|
1254
|
+
message: `Config file already exists${options.prod ? ` at ${fullPath}` : ""}. Overwrite?`,
|
|
1255
|
+
initialValue: false
|
|
1143
1256
|
});
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
s.stop(`Fetched ${creditSystems.length} credit systems`);
|
|
1148
|
-
s.start(`Fetching credit packs...`);
|
|
1149
|
-
const creditPacks = await fetchCreditPacks(apiKey, apiUrl);
|
|
1150
|
-
s.stop(`Fetched ${creditPacks.length} credit packs`);
|
|
1151
|
-
const providers = new Set(
|
|
1152
|
-
plans.map((p9) => p9.provider).filter(Boolean)
|
|
1153
|
-
);
|
|
1154
|
-
const defaultProvider = providers.size === 1 ? Array.from(providers)[0] : void 0;
|
|
1155
|
-
const configContent = generateConfig(
|
|
1156
|
-
plans,
|
|
1157
|
-
creditSystems,
|
|
1158
|
-
creditPacks,
|
|
1159
|
-
defaultProvider,
|
|
1160
|
-
format
|
|
1161
|
-
);
|
|
1162
|
-
if (options.dryRun) {
|
|
1163
|
-
p3.note(configContent, "Generated Config (Dry Run)");
|
|
1164
|
-
printPullSummary(plans, creditSystems, creditPacks);
|
|
1165
|
-
p3.outro(pc4.yellow("Dry run complete. No changes made."));
|
|
1166
|
-
return;
|
|
1167
|
-
}
|
|
1168
|
-
if (existsSync3(fullPath) && !options.force) {
|
|
1169
|
-
const confirm4 = await p3.confirm({
|
|
1170
|
-
message: `Config file already exists. Overwrite?`,
|
|
1171
|
-
initialValue: false
|
|
1172
|
-
});
|
|
1173
|
-
if (p3.isCancel(confirm4) || !confirm4) {
|
|
1174
|
-
p3.outro(pc4.yellow("Operation cancelled"));
|
|
1175
|
-
process.exit(0);
|
|
1176
|
-
}
|
|
1257
|
+
if (p3.isCancel(confirm4) || !confirm4) {
|
|
1258
|
+
p3.outro(pc4.yellow("Operation cancelled"));
|
|
1259
|
+
process.exit(0);
|
|
1177
1260
|
}
|
|
1178
|
-
await writeFile2(fullPath, configContent, "utf8");
|
|
1179
|
-
p3.log.success(pc4.green(`Wrote configuration to ${fullPath}`));
|
|
1180
|
-
printPullSummary(plans, creditSystems, creditPacks);
|
|
1181
1261
|
}
|
|
1262
|
+
await writeFile2(fullPath, snapshot.configContent, "utf8");
|
|
1263
|
+
p3.log.success(pc4.green(`Wrote configuration to ${fullPath}`));
|
|
1264
|
+
printPullSummary(
|
|
1265
|
+
snapshot.plans,
|
|
1266
|
+
snapshot.creditSystems,
|
|
1267
|
+
snapshot.creditPacks
|
|
1268
|
+
);
|
|
1182
1269
|
p3.outro(pc4.green("Pull complete! \u2728"));
|
|
1183
1270
|
}
|
|
1184
1271
|
function printPullSummary(plans, creditSystems, creditPacks = []) {
|
|
@@ -1332,7 +1419,7 @@ import * as p6 from "@clack/prompts";
|
|
|
1332
1419
|
import pc7 from "picocolors";
|
|
1333
1420
|
import { existsSync as existsSync4 } from "fs";
|
|
1334
1421
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
1335
|
-
import { join as join2, resolve as resolve3, isAbsolute as isAbsolute3
|
|
1422
|
+
import { join as join2, resolve as resolve3, isAbsolute as isAbsolute3 } from "path";
|
|
1336
1423
|
|
|
1337
1424
|
// src/lib/connect.ts
|
|
1338
1425
|
import * as p5 from "@clack/prompts";
|
|
@@ -1450,16 +1537,21 @@ async function runInit(options) {
|
|
|
1450
1537
|
}
|
|
1451
1538
|
}
|
|
1452
1539
|
const fullPath = isAbsolute3(targetPath) ? targetPath : resolve3(process.cwd(), targetPath);
|
|
1540
|
+
const configSettings = await loadConfigSettings(options.config);
|
|
1541
|
+
const testUrl = getTestApiUrl(
|
|
1542
|
+
configSettings.environments?.test || configSettings.apiUrl
|
|
1543
|
+
);
|
|
1544
|
+
const filters = configSettings.filters || {};
|
|
1453
1545
|
let apiKey = getApiKey(options.key);
|
|
1454
1546
|
if (!apiKey) {
|
|
1455
1547
|
p6.log.warn(
|
|
1456
1548
|
pc7.yellow("No API key found. Let's connect your account first.")
|
|
1457
1549
|
);
|
|
1458
1550
|
apiKey = await executeConnectFlow({
|
|
1459
|
-
apiUrl:
|
|
1460
|
-
dashboardUrl: getDashboardUrl(),
|
|
1551
|
+
apiUrl: testUrl,
|
|
1552
|
+
dashboardUrl: getDashboardUrl(configSettings.connect?.dashboardUrl),
|
|
1461
1553
|
noBrowser: false,
|
|
1462
|
-
timeout: 300
|
|
1554
|
+
timeout: configSettings.connect?.timeout || 300
|
|
1463
1555
|
}) || "";
|
|
1464
1556
|
if (!apiKey) {
|
|
1465
1557
|
p6.log.error(pc7.red("Could not obtain API key. Initialization aborted."));
|
|
@@ -1479,36 +1571,21 @@ async function runInit(options) {
|
|
|
1479
1571
|
const s = p6.spinner();
|
|
1480
1572
|
s.start("Generating project configuration...");
|
|
1481
1573
|
try {
|
|
1482
|
-
const
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
format = "esm";
|
|
1491
|
-
} else if (ext === ".cjs") {
|
|
1492
|
-
throw new Error(
|
|
1493
|
-
"CommonJS config files are not supported. Use owo.config.js or owo.config.ts."
|
|
1494
|
-
);
|
|
1495
|
-
} else if (ext === ".js") {
|
|
1496
|
-
format = "esm";
|
|
1497
|
-
}
|
|
1498
|
-
const configContent = generateConfig(
|
|
1499
|
-
plans,
|
|
1500
|
-
creditSystems,
|
|
1501
|
-
[],
|
|
1502
|
-
void 0,
|
|
1503
|
-
format
|
|
1504
|
-
);
|
|
1505
|
-
await writeFile3(fullPath, configContent, "utf8");
|
|
1574
|
+
const format = determineConfigFormat(fullPath);
|
|
1575
|
+
const snapshot = await buildRemoteCatalogSnapshot({
|
|
1576
|
+
apiKey,
|
|
1577
|
+
apiUrl: `${testUrl}/api/v1`,
|
|
1578
|
+
format,
|
|
1579
|
+
filters
|
|
1580
|
+
});
|
|
1581
|
+
await writeFile3(fullPath, snapshot.configContent, "utf8");
|
|
1506
1582
|
s.stop(pc7.green("Configuration created"));
|
|
1507
1583
|
p6.note(
|
|
1508
1584
|
`${pc7.dim("File:")} ${fullPath}
|
|
1509
1585
|
${pc7.dim("Format:")} ${format.toUpperCase()}
|
|
1510
|
-
${pc7.dim("Plans:")} ${plans.length} imported
|
|
1511
|
-
${pc7.dim("Credit Systems:")} ${creditSystems.length}
|
|
1586
|
+
${pc7.dim("Plans:")} ${snapshot.plans.length} imported
|
|
1587
|
+
${pc7.dim("Credit Systems:")} ${snapshot.creditSystems.length}
|
|
1588
|
+
${pc7.dim("Credit Packs:")} ${snapshot.creditPacks.length}`,
|
|
1512
1589
|
"\u2728 Project Initialized"
|
|
1513
1590
|
);
|
|
1514
1591
|
p6.outro(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "owosk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI for Owostack - sync catalog, manage billing infrastructure",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"commander": "^14.0.3",
|
|
25
25
|
"jiti": "^2.6.1",
|
|
26
26
|
"picocolors": "^1.1.1",
|
|
27
|
-
"@owostack/types": "0.
|
|
28
|
-
"owostack": "0.
|
|
27
|
+
"@owostack/types": "0.3.0",
|
|
28
|
+
"owostack": "0.3.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.19.10",
|