@dk/jolly 0.1.4 → 0.1.6

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/bun.lock CHANGED
@@ -5,7 +5,7 @@
5
5
  "": {
6
6
  "name": "@saleor/jolly",
7
7
  "dependencies": {
8
- "dotenv": "^17.4.0",
8
+ "@dotenvx/dotenvx": "^1.59.1",
9
9
  "yargs": "^17.7.2",
10
10
  },
11
11
  "devDependencies": {
@@ -16,6 +16,16 @@
16
16
  },
17
17
  },
18
18
  "packages": {
19
+ "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.59.1", "", { "dependencies": { "commander": "^11.1.0", "dotenv": "^17.2.1", "eciesjs": "^0.4.10", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "picomatch": "^4.0.2", "which": "^4.0.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-Qg+meC+XFxliuVSDlEPkKnaUjdaJKK6FNx/Wwl2UxhQR8pyPIuLhMavsF7ePdB9qFZUWV1jEK3ckbJir/WmF4w=="],
20
+
21
+ "@ecies/ciphers": ["@ecies/ciphers@0.2.6", "", { "peerDependencies": { "@noble/ciphers": "^1.0.0" } }, "sha512-patgsRPKGkhhoBjETV4XxD0En4ui5fbX0hzayqI3M8tvNMGUoUvmyYAIWwlxBc1KX5cturfqByYdj5bYGRpN9g=="],
22
+
23
+ "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
24
+
25
+ "@noble/curves": ["@noble/curves@1.9.7", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw=="],
26
+
27
+ "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
28
+
19
29
  "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
20
30
 
21
31
  "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
@@ -34,26 +44,70 @@
34
44
 
35
45
  "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
36
46
 
47
+ "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
48
+
49
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
50
+
37
51
  "dotenv": ["dotenv@17.4.0", "", {}, "sha512-kCKF62fwtzwYm0IGBNjRUjtJgMfGapII+FslMHIjMR5KTnwEmBmWLDRSnc3XSNP8bNy34tekgQyDT0hr7pERRQ=="],
38
52
 
53
+ "eciesjs": ["eciesjs@0.4.18", "", { "dependencies": { "@ecies/ciphers": "^0.2.5", "@noble/ciphers": "^1.3.0", "@noble/curves": "^1.9.7", "@noble/hashes": "^1.8.0" } }, "sha512-wG99Zcfcys9fZux7Cft8BAX/YrOJLJSZ3jyYPfhZHqN2E+Ffx+QXBDsv3gubEgPtV6dTzJMSQUwk1H98/t/0wQ=="],
54
+
39
55
  "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
40
56
 
41
57
  "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
42
58
 
59
+ "execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
60
+
61
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
62
+
43
63
  "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
44
64
 
65
+ "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
66
+
67
+ "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
68
+
69
+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
70
+
45
71
  "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
46
72
 
73
+ "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
74
+
75
+ "isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
76
+
77
+ "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
78
+
79
+ "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
80
+
81
+ "npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
82
+
83
+ "object-treeify": ["object-treeify@1.1.33", "", {}, "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A=="],
84
+
85
+ "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
86
+
87
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
88
+
89
+ "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
90
+
47
91
  "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
48
92
 
93
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
94
+
95
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
96
+
97
+ "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
98
+
49
99
  "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
50
100
 
51
101
  "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
52
102
 
103
+ "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
104
+
53
105
  "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
54
106
 
55
107
  "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
56
108
 
109
+ "which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
110
+
57
111
  "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
58
112
 
59
113
  "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
@@ -61,5 +115,9 @@
61
115
  "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
62
116
 
63
117
  "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
118
+
119
+ "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
120
+
121
+ "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
64
122
  }
65
123
  }
package/dist/bootstrap.js CHANGED
@@ -51,13 +51,19 @@ class SaleorCloudClient {
51
51
  }
52
52
 
53
53
  // src/api/auth.ts
54
- import { config } from "dotenv";
54
+ import { config } from "@dotenvx/dotenvx";
55
55
  config();
56
56
  function requireToken() {
57
57
  const token = process.env.SALEOR_CLOUD_TOKEN;
58
58
  if (!token) {
59
- console.error("Error: SALEOR_CLOUD_TOKEN environment variable is required");
60
- console.error("Get your token at: https://cloud.saleor.io/settings/api-tokens");
59
+ console.error(`
60
+ \uD83D\uDD11 Saleor Cloud Token Required`);
61
+ console.error(` Get your token at: https://cloud.saleor.io/settings/api-tokens
62
+ `);
63
+ console.error("Or create a .env file with: SALEOR_CLOUD_TOKEN=your-token");
64
+ console.error(`
65
+ To set token: export SALEOR_CLOUD_TOKEN=your-token
66
+ `);
61
67
  process.exit(1);
62
68
  }
63
69
  return token;
@@ -119,14 +125,14 @@ function info(msg) {
119
125
  async function createStore(name, region) {
120
126
  const token = requireToken();
121
127
  const client = new SaleorCloudClient(token);
122
- info(`Creating store: ${name} in ${region}...`);
128
+ console.log(info(`Creating store: ${name} in ${region}...`));
123
129
  try {
124
130
  const result = await client.createStore(name, region);
125
- success(`Store created successfully!`);
126
- info(`Store ID: ${result.store.id}`);
127
- info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`);
131
+ console.log(success(`Store created successfully!`));
132
+ console.log(info(`Store ID: ${result.store.id}`));
133
+ console.log(info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`));
128
134
  } catch (err) {
129
- error(`Failed to create store: ${err}`);
135
+ console.log(error(`Failed to create store: ${err}`));
130
136
  process.exit(1);
131
137
  }
132
138
  }
package/dist/index.js CHANGED
@@ -73,17 +73,70 @@ class SaleorCloudClient {
73
73
  }
74
74
 
75
75
  // src/api/auth.ts
76
- import { config } from "dotenv";
76
+ import { config } from "@dotenvx/dotenvx";
77
+ import { writeFileSync, existsSync, readFileSync } from "fs";
78
+ import { join } from "path";
77
79
  config();
78
80
  function requireToken() {
79
81
  const token = process.env.SALEOR_CLOUD_TOKEN;
80
82
  if (!token) {
81
- console.error("Error: SALEOR_CLOUD_TOKEN environment variable is required");
82
- console.error("Get your token at: https://cloud.saleor.io/settings/api-tokens");
83
+ console.error(`
84
+ \uD83D\uDD11 Saleor Cloud Token Required`);
85
+ console.error(` Get your token at: https://cloud.saleor.io/settings/api-tokens
86
+ `);
87
+ console.error("Or create a .env file with: SALEOR_CLOUD_TOKEN=your-token");
88
+ console.error(`
89
+ To set token: export SALEOR_CLOUD_TOKEN=your-token
90
+ `);
83
91
  process.exit(1);
84
92
  }
85
93
  return token;
86
94
  }
95
+ async function promptAndSaveToken() {
96
+ console.log(`
97
+ \uD83D\uDD11 Saleor Cloud Token Required`);
98
+ console.log(` Get your token at: https://cloud.saleor.io/settings/api-tokens
99
+ `);
100
+ const readline = await import("readline");
101
+ const rl = readline.createInterface({
102
+ input: process.stdin,
103
+ output: process.stdout
104
+ });
105
+ return new Promise((resolve) => {
106
+ rl.question("Enter your SALEOR_CLOUD_TOKEN: ", (answer) => {
107
+ rl.close();
108
+ const token = answer.trim();
109
+ if (!token) {
110
+ console.error("Error: Token cannot be empty");
111
+ process.exit(1);
112
+ }
113
+ const envPath = join(process.cwd(), ".env");
114
+ const envLine = `SALEOR_CLOUD_TOKEN=${token}
115
+ `;
116
+ try {
117
+ let existingContent = "";
118
+ if (existsSync(envPath)) {
119
+ existingContent = readFileSync(envPath, "utf-8");
120
+ if (existingContent.includes("SALEOR_CLOUD_TOKEN=")) {
121
+ existingContent = existingContent.replace(/SALEOR_CLOUD_TOKEN=.*\n?/g, envLine);
122
+ } else {
123
+ existingContent += envLine;
124
+ }
125
+ } else {
126
+ existingContent = envLine;
127
+ }
128
+ writeFileSync(envPath, existingContent);
129
+ console.log(`
130
+ ✅ Token saved to .env file`);
131
+ } catch {
132
+ console.log(`
133
+ ⚠️ Could not save to .env, token will not persist`);
134
+ }
135
+ process.env.SALEOR_CLOUD_TOKEN = token;
136
+ resolve(token);
137
+ });
138
+ });
139
+ }
87
140
 
88
141
  // src/tui/theme.ts
89
142
  var theme = {
@@ -141,29 +194,29 @@ function info(msg) {
141
194
  async function createStore(name, region) {
142
195
  const token = requireToken();
143
196
  const client = new SaleorCloudClient(token);
144
- info(`Creating store: ${name} in ${region}...`);
197
+ console.log(info(`Creating store: ${name} in ${region}...`));
145
198
  try {
146
199
  const result = await client.createStore(name, region);
147
- success(`Store created successfully!`);
148
- info(`Store ID: ${result.store.id}`);
149
- info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`);
200
+ console.log(success(`Store created successfully!`));
201
+ console.log(info(`Store ID: ${result.store.id}`));
202
+ console.log(info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`));
150
203
  } catch (err) {
151
- error(`Failed to create store: ${err}`);
204
+ console.log(error(`Failed to create store: ${err}`));
152
205
  process.exit(1);
153
206
  }
154
207
  }
155
208
  async function listStores() {
156
209
  const token = requireToken();
157
210
  const client = new SaleorCloudClient(token);
158
- info("Fetching stores...");
211
+ console.log(info("Fetching stores..."));
159
212
  try {
160
213
  const result = await client.getStores();
161
214
  if (result.stores.length === 0) {
162
- info("No stores found. Create one with: jolly store create --name <name>");
215
+ console.log(info("No stores found. Create one with: jolly store create --name <name>"));
163
216
  return;
164
217
  }
165
- success(`Found ${result.stores.length} store(s):
166
- `);
218
+ console.log(success(`Found ${result.stores.length} store(s):
219
+ `));
167
220
  for (const store of result.stores) {
168
221
  console.log(` ${store.name} (${store.id})`);
169
222
  console.log(` Region: ${store.region}`);
@@ -171,26 +224,31 @@ async function listStores() {
171
224
  console.log();
172
225
  }
173
226
  } catch (err) {
174
- error(`Failed to list stores: ${err}`);
227
+ console.log(error(`Failed to list stores: ${err}`));
175
228
  process.exit(1);
176
229
  }
177
230
  }
178
231
  async function createEnvironment(storeId, name) {
179
232
  const token = requireToken();
180
233
  const client = new SaleorCloudClient(token);
181
- info(`Creating environment: ${name} for store ${storeId}...`);
234
+ console.log(info(`Creating environment: ${name} for store ${storeId}...`));
182
235
  try {
183
236
  const result = await client.createEnvironment(storeId, name);
184
- success(`Environment created successfully!`);
185
- info(`Environment ID: ${result.environment.id}`);
186
- info(`API URL will be available at: https://${result.environment.id}.saleor.cloud`);
237
+ console.log(success(`Environment created successfully!`));
238
+ console.log(info(`Environment ID: ${result.environment.id}`));
239
+ console.log(info(`API URL will be available at: https://${result.environment.id}.saleor.cloud`));
187
240
  } catch (err) {
188
- error(`Failed to create environment: ${err}`);
241
+ console.log(error(`Failed to create environment: ${err}`));
189
242
  process.exit(1);
190
243
  }
191
244
  }
192
245
 
193
246
  // src/cli/commands/store.ts
247
+ async function ensureToken() {
248
+ if (!process.env.SALEOR_CLOUD_TOKEN) {
249
+ await promptAndSaveToken();
250
+ }
251
+ }
194
252
  var storeCommands = {
195
253
  command: "store <action>",
196
254
  describe: "Manage Saleor Cloud stores",
@@ -209,6 +267,7 @@ var storeCommands = {
209
267
  default: "us-east-1"
210
268
  }),
211
269
  handler: async (argv) => {
270
+ await ensureToken();
212
271
  await createStore(argv.name, argv.region);
213
272
  }
214
273
  }).command({
@@ -216,6 +275,7 @@ var storeCommands = {
216
275
  describe: "List your Saleor Cloud stores",
217
276
  builder: (yargs2) => yargs2,
218
277
  handler: async () => {
278
+ await ensureToken();
219
279
  await listStores();
220
280
  }
221
281
  }).command({
@@ -236,6 +296,7 @@ var storeCommands = {
236
296
  demandOption: true
237
297
  }),
238
298
  handler: async (argv) => {
299
+ await ensureToken();
239
300
  await createEnvironment(argv.store, argv.name);
240
301
  }
241
302
  })
@@ -262,26 +323,26 @@ var PAYMENT_APP_URLS = {
262
323
  stripe: "https://stripe-payment.saleor.io"
263
324
  };
264
325
  async function createApp(name, type, environmentId, provider) {
265
- info(`Creating ${type} app: ${name}`);
326
+ console.log(info(`Creating ${type} app: ${name}`));
266
327
  if (type === "payment") {
267
328
  const paymentProvider = provider || "dummy";
268
- info(`Payment provider: ${paymentProvider}`);
269
- info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`);
329
+ console.log(info(`Payment provider: ${paymentProvider}`));
330
+ console.log(info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`));
270
331
  if (environmentId) {
271
332
  await registerHostedApp(environmentId, name, paymentProvider);
272
333
  } else {
273
- success(`
274
- Payment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`);
275
- info(`
276
- To complete setup:`);
277
- info(`1. Go to your dashboard at https://cloud.saleor.io`);
278
- info(`2. Navigate to Apps > Third party apps`);
279
- info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`);
334
+ console.log(success(`
335
+ Payment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`));
336
+ console.log(info(`
337
+ To complete setup:`));
338
+ console.log(info(`1. Go to your dashboard at https://cloud.saleor.io`));
339
+ console.log(info(`2. Navigate to Apps > Third party apps`));
340
+ console.log(info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`));
280
341
  }
281
342
  return;
282
343
  }
283
344
  const template = APP_TEMPLATES[type];
284
- info(`Cloning template from: ${template.repo}`);
345
+ console.log(info(`Cloning template from: ${template.repo}`));
285
346
  try {
286
347
  const { spawn } = await import("child_process");
287
348
  const child = spawn("git", ["clone", template.repo, name], {
@@ -289,39 +350,39 @@ To complete setup:`);
289
350
  });
290
351
  child.on("close", (code) => {
291
352
  if (code === 0) {
292
- success(`
293
- ${type} app "${name}" created successfully!`);
294
- info(`
295
- To get started:`);
296
- info(`cd ${name}`);
297
- info(`npm install`);
298
- info(`npm run dev`);
353
+ console.log(success(`
354
+ ${type} app "${name}" created successfully!`));
355
+ console.log(info(`
356
+ To get started:`));
357
+ console.log(info(`cd ${name}`));
358
+ console.log(info(`npm install`));
359
+ console.log(info(`npm run dev`));
299
360
  if (environmentId) {
300
- info(`
301
- Registering app with environment ${environmentId}...`);
361
+ console.log(info(`
362
+ Registering app with environment ${environmentId}...`));
302
363
  registerLocalApp(environmentId, name, type);
303
364
  }
304
365
  } else {
305
- error(`Failed to clone template (exit code: ${code})`);
366
+ console.log(error(`Failed to clone template (exit code: ${code})`));
306
367
  process.exit(1);
307
368
  }
308
369
  });
309
370
  } catch (err) {
310
- error(`Failed to create app: ${err}`);
371
+ console.log(error(`Failed to create app: ${err}`));
311
372
  process.exit(1);
312
373
  }
313
374
  }
314
375
  async function registerHostedApp(environmentId, name, provider) {
315
376
  const token = requireToken();
316
377
  const client = new SaleorCloudClient(token);
317
- info(`Registering hosted ${provider} payment app with environment...`);
378
+ console.log(info(`Registering hosted ${provider} payment app with environment...`));
318
379
  try {
319
380
  const result = await client.registerApp(environmentId, "payment", name);
320
- success(`Payment app registered successfully!`);
321
- info(`App ID: ${result.app.id}`);
322
- info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`);
381
+ console.log(success(`Payment app registered successfully!`));
382
+ console.log(info(`App ID: ${result.app.id}`));
383
+ console.log(info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`));
323
384
  } catch (err) {
324
- error(`Failed to register app: ${err}`);
385
+ console.log(error(`Failed to register app: ${err}`));
325
386
  process.exit(1);
326
387
  }
327
388
  }
@@ -330,11 +391,11 @@ async function registerLocalApp(environmentId, name, type) {
330
391
  const client = new SaleorCloudClient(token);
331
392
  try {
332
393
  const result = await client.registerApp(environmentId, type, name);
333
- success(`App registered with environment!`);
334
- info(`App ID: ${result.app.id}`);
394
+ console.log(success(`App registered with environment!`));
395
+ console.log(info(`App ID: ${result.app.id}`));
335
396
  } catch (err) {
336
- warning(`Could not register app automatically: ${err}`);
337
- info(`You can register manually in the dashboard.`);
397
+ console.log(warning(`Could not register app automatically: ${err}`));
398
+ console.log(info(`You can register manually in the dashboard.`));
338
399
  }
339
400
  }
340
401
  function warning(msg) {
@@ -342,6 +403,11 @@ function warning(msg) {
342
403
  }
343
404
 
344
405
  // src/cli/commands/app.ts
406
+ async function ensureToken2() {
407
+ if (!process.env.SALEOR_CLOUD_TOKEN) {
408
+ await promptAndSaveToken();
409
+ }
410
+ }
345
411
  var appCommands = {
346
412
  command: "app <action>",
347
413
  describe: "Scaffold Saleor apps",
@@ -371,15 +437,18 @@ var appCommands = {
371
437
  description: "Environment ID to register app with"
372
438
  }),
373
439
  handler: async (argv) => {
440
+ if (argv.environment) {
441
+ await ensureToken2();
442
+ }
374
443
  await createApp(argv.name, argv.type, argv.environment, argv.provider);
375
444
  }
376
445
  })
377
446
  };
378
447
 
379
448
  // src/agents/setup.ts
380
- import { writeFileSync, mkdirSync, existsSync } from "fs";
449
+ import { writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync2 } from "fs";
381
450
  import { spawnSync } from "child_process";
382
- import { join } from "path";
451
+ import { join as join2 } from "path";
383
452
  var AGENT_PATHS = {
384
453
  opencode: {
385
454
  skills: ".agents/skills",
@@ -457,12 +526,12 @@ function detectAgents(projectPath) {
457
526
  { name: "nanobot", file: ".nanobot" }
458
527
  ];
459
528
  for (const { name, file } of filesToCheck) {
460
- const fullPath = join(projectPath, file);
461
- if (existsSync(fullPath)) {
529
+ const fullPath = join2(projectPath, file);
530
+ if (existsSync2(fullPath)) {
462
531
  detected.push({
463
532
  name,
464
533
  path: fullPath,
465
- skillsPath: join(fullPath, "skills")
534
+ skillsPath: join2(fullPath, "skills")
466
535
  });
467
536
  }
468
537
  }
@@ -470,11 +539,11 @@ function detectAgents(projectPath) {
470
539
  }
471
540
  function installSkills(projectPath, agentName) {
472
541
  const agentPaths = AGENT_PATHS[agentName];
473
- const skillsDir = join(projectPath, agentPaths.skills);
542
+ const skillsDir = join2(projectPath, agentPaths.skills);
474
543
  mkdirSync(skillsDir, { recursive: true });
475
544
  info(` Installing skills to ${skillsDir}...`);
476
545
  const skillUrl = "https://github.com/saleor/agent-skills";
477
- const baseDir = join(skillsDir, "..");
546
+ const baseDir = join2(skillsDir, "..");
478
547
  try {
479
548
  const result = spawnSync("git", ["clone", "--depth", "1", skillUrl, "skills"], {
480
549
  cwd: baseDir,
@@ -540,8 +609,8 @@ Configure saleor-mcp for AI agent capabilities:
540
609
  }
541
610
  \`\`\`
542
611
  `;
543
- const agentsMdPath = join(projectPath, "AGENTS.md");
544
- writeFileSync(agentsMdPath, agentsMdContent);
612
+ const agentsMdPath = join2(projectPath, "AGENTS.md");
613
+ writeFileSync2(agentsMdPath, agentsMdContent);
545
614
  info(` Created AGENTS.md`);
546
615
  }
547
616
  function createMcpConfig(projectPath) {
@@ -552,8 +621,8 @@ function createMcpConfig(projectPath) {
552
621
  }
553
622
  }
554
623
  };
555
- const mcpPath = join(projectPath, ".mcp.json");
556
- writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2));
624
+ const mcpPath = join2(projectPath, ".mcp.json");
625
+ writeFileSync2(mcpPath, JSON.stringify(mcpConfig, null, 2));
557
626
  info(` Created .mcp.json`);
558
627
  }
559
628
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dk/jolly",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Saleor project bootstrapper and agent configurator",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,18 +9,18 @@
9
9
  "init-jolly": "./dist/agent.js"
10
10
  },
11
11
  "scripts": {
12
- "build": "bun build src/cli/index.ts --outdir=dist --target=node --external yargs --external dotenv && bun build src/cli/bootstrap.ts --outdir=dist --target=node --external yargs --external dotenv && bun build src/cli/agent.ts --outdir=dist --target=node --external yargs --external dotenv",
12
+ "build": "bun build src/cli/index.ts --outdir=dist --target=node --external yargs --external @dotenvx/dotenvx && bun build src/cli/bootstrap.ts --outdir=dist --target=node --external yargs --external @dotenvx/dotenvx && bun build src/cli/agent.ts --outdir=dist --target=node --external yargs --external @dotenvx/dotenvx",
13
13
  "prepublishOnly": "bun run build",
14
14
  "jolly": "bun src/cli/index.ts",
15
15
  "dev": "bun --watch src/cli/index.ts",
16
16
  "test": "bun test",
17
17
  "typecheck": "bun tsc --noEmit",
18
- "release": "npm version patch && npm publish",
19
- "release:minor": "npm version minor && npm publish",
20
- "release:major": "npm version major && npm publish"
18
+ "release": "npm version patch --no-git-tag-version && npm publish",
19
+ "release:minor": "npm version minor --no-git-tag-version && npm publish",
20
+ "release:major": "npm version major --no-git-tag-version && npm publish"
21
21
  },
22
22
  "dependencies": {
23
- "dotenv": "^17.4.0",
23
+ "@dotenvx/dotenvx": "^1.59.1",
24
24
  "yargs": "^17.7.2"
25
25
  },
26
26
  "devDependencies": {
package/src/api/auth.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { config } from 'dotenv';
1
+ import { config } from '@dotenvx/dotenvx';
2
+ import { writeFileSync, existsSync, readFileSync } from 'fs';
3
+ import { join } from 'path';
2
4
 
3
5
  config();
4
6
 
@@ -13,9 +15,61 @@ export function getToken(): string {
13
15
  export function requireToken(): string {
14
16
  const token = process.env.SALEOR_CLOUD_TOKEN;
15
17
  if (!token) {
16
- console.error('Error: SALEOR_CLOUD_TOKEN environment variable is required');
17
- console.error('Get your token at: https://cloud.saleor.io/settings/api-tokens');
18
+ console.error('\n🔑 Saleor Cloud Token Required');
19
+ console.error(' Get your token at: https://cloud.saleor.io/settings/api-tokens\n');
20
+ console.error('Or create a .env file with: SALEOR_CLOUD_TOKEN=your-token');
21
+ console.error('\nTo set token: export SALEOR_CLOUD_TOKEN=your-token\n');
18
22
  process.exit(1);
19
23
  }
20
24
  return token;
21
25
  }
26
+
27
+ export async function promptAndSaveToken(): Promise<string> {
28
+ console.log('\n🔑 Saleor Cloud Token Required');
29
+ console.log(' Get your token at: https://cloud.saleor.io/settings/api-tokens\n');
30
+
31
+ const readline = await import('readline');
32
+ const rl = readline.createInterface({
33
+ input: process.stdin,
34
+ output: process.stdout
35
+ });
36
+
37
+ return new Promise((resolve) => {
38
+ rl.question('Enter your SALEOR_CLOUD_TOKEN: ', (answer: string) => {
39
+ rl.close();
40
+ const token = answer.trim();
41
+
42
+ if (!token) {
43
+ console.error('Error: Token cannot be empty');
44
+ process.exit(1);
45
+ }
46
+
47
+ const envPath = join(process.cwd(), '.env');
48
+ const envLine = `SALEOR_CLOUD_TOKEN=${token}\n`;
49
+
50
+ try {
51
+ let existingContent = '';
52
+ if (existsSync(envPath)) {
53
+ existingContent = readFileSync(envPath, 'utf-8');
54
+ if (existingContent.includes('SALEOR_CLOUD_TOKEN=')) {
55
+ existingContent = existingContent.replace(
56
+ /SALEOR_CLOUD_TOKEN=.*\n?/g,
57
+ envLine
58
+ );
59
+ } else {
60
+ existingContent += envLine;
61
+ }
62
+ } else {
63
+ existingContent = envLine;
64
+ }
65
+ writeFileSync(envPath, existingContent);
66
+ console.log('\n✅ Token saved to .env file');
67
+ } catch {
68
+ console.log('\n⚠️ Could not save to .env, token will not persist');
69
+ }
70
+
71
+ process.env.SALEOR_CLOUD_TOKEN = token;
72
+ resolve(token);
73
+ });
74
+ });
75
+ }
@@ -1,9 +1,16 @@
1
1
  import type { CommandModule } from 'yargs';
2
2
  import { createApp } from '../../commands/app.js';
3
+ import { promptAndSaveToken } from '../../api/auth.js';
3
4
 
4
5
  type AppType = 'dashboard-extension' | 'payment' | 'webhook';
5
6
  type PaymentProvider = 'dummy' | 'stripe';
6
7
 
8
+ async function ensureToken() {
9
+ if (!process.env.SALEOR_CLOUD_TOKEN) {
10
+ await promptAndSaveToken();
11
+ }
12
+ }
13
+
7
14
  export const appCommands: CommandModule = {
8
15
  command: 'app <action>',
9
16
  describe: 'Scaffold Saleor apps',
@@ -40,6 +47,9 @@ export const appCommands: CommandModule = {
40
47
  description: 'Environment ID to register app with',
41
48
  }),
42
49
  handler: async (argv) => {
50
+ if (argv.environment) {
51
+ await ensureToken();
52
+ }
43
53
  await createApp(
44
54
  argv.name,
45
55
  argv.type as AppType,
@@ -1,5 +1,12 @@
1
1
  import type { CommandModule } from 'yargs';
2
2
  import { createStore, listStores, createEnvironment } from '../../commands/store.js';
3
+ import { promptAndSaveToken, getToken } from '../../api/auth.js';
4
+
5
+ async function ensureToken() {
6
+ if (!process.env.SALEOR_CLOUD_TOKEN) {
7
+ await promptAndSaveToken();
8
+ }
9
+ }
3
10
 
4
11
  export const storeCommands: CommandModule = {
5
12
  command: 'store <action>',
@@ -24,6 +31,7 @@ export const storeCommands: CommandModule = {
24
31
  default: 'us-east-1',
25
32
  }),
26
33
  handler: async (argv) => {
34
+ await ensureToken();
27
35
  await createStore(argv.name, argv.region);
28
36
  },
29
37
  })
@@ -32,6 +40,7 @@ export const storeCommands: CommandModule = {
32
40
  describe: 'List your Saleor Cloud stores',
33
41
  builder: (yargs) => yargs,
34
42
  handler: async () => {
43
+ await ensureToken();
35
44
  await listStores();
36
45
  },
37
46
  })
@@ -58,6 +67,7 @@ export const storeCommands: CommandModule = {
58
67
  demandOption: true,
59
68
  }),
60
69
  handler: async (argv) => {
70
+ await ensureToken();
61
71
  await createEnvironment(argv.store as string, argv.name as string);
62
72
  },
63
73
  }),
@@ -31,27 +31,27 @@ export async function createApp(
31
31
  environmentId?: string,
32
32
  provider?: PaymentProvider
33
33
  ): Promise<void> {
34
- info(`Creating ${type} app: ${name}`);
34
+ console.log(info(`Creating ${type} app: ${name}`));
35
35
 
36
36
  if (type === 'payment') {
37
37
  const paymentProvider = provider || 'dummy';
38
- info(`Payment provider: ${paymentProvider}`);
39
- info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`);
38
+ console.log(info(`Payment provider: ${paymentProvider}`));
39
+ console.log(info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`));
40
40
 
41
41
  if (environmentId) {
42
42
  await registerHostedApp(environmentId, name, paymentProvider);
43
43
  } else {
44
- success(`\nPayment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`);
45
- info(`\nTo complete setup:`);
46
- info(`1. Go to your dashboard at https://cloud.saleor.io`);
47
- info(`2. Navigate to Apps > Third party apps`);
48
- info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`);
44
+ console.log(success(`\nPayment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`));
45
+ console.log(info(`\nTo complete setup:`));
46
+ console.log(info(`1. Go to your dashboard at https://cloud.saleor.io`));
47
+ console.log(info(`2. Navigate to Apps > Third party apps`));
48
+ console.log(info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`));
49
49
  }
50
50
  return;
51
51
  }
52
52
 
53
53
  const template = APP_TEMPLATES[type];
54
- info(`Cloning template from: ${template.repo}`);
54
+ console.log(info(`Cloning template from: ${template.repo}`));
55
55
 
56
56
  try {
57
57
  const { spawn } = await import('child_process');
@@ -61,23 +61,23 @@ export async function createApp(
61
61
 
62
62
  child.on('close', (code) => {
63
63
  if (code === 0) {
64
- success(`\n${type} app "${name}" created successfully!`);
65
- info(`\nTo get started:`);
66
- info(`cd ${name}`);
67
- info(`npm install`);
68
- info(`npm run dev`);
64
+ console.log(success(`\n${type} app "${name}" created successfully!`));
65
+ console.log(info(`\nTo get started:`));
66
+ console.log(info(`cd ${name}`));
67
+ console.log(info(`npm install`));
68
+ console.log(info(`npm run dev`));
69
69
 
70
70
  if (environmentId) {
71
- info(`\nRegistering app with environment ${environmentId}...`);
71
+ console.log(info(`\nRegistering app with environment ${environmentId}...`));
72
72
  registerLocalApp(environmentId, name, type);
73
73
  }
74
74
  } else {
75
- error(`Failed to clone template (exit code: ${code})`);
75
+ console.log(error(`Failed to clone template (exit code: ${code})`));
76
76
  process.exit(1);
77
77
  }
78
78
  });
79
79
  } catch (err) {
80
- error(`Failed to create app: ${err}`);
80
+ console.log(error(`Failed to create app: ${err}`));
81
81
  process.exit(1);
82
82
  }
83
83
  }
@@ -90,15 +90,15 @@ async function registerHostedApp(
90
90
  const token = requireToken();
91
91
  const client = new SaleorCloudClient(token);
92
92
 
93
- info(`Registering hosted ${provider} payment app with environment...`);
93
+ console.log(info(`Registering hosted ${provider} payment app with environment...`));
94
94
 
95
95
  try {
96
96
  const result = await client.registerApp(environmentId, 'payment', name);
97
- success(`Payment app registered successfully!`);
98
- info(`App ID: ${result.app.id}`);
99
- info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`);
97
+ console.log(success(`Payment app registered successfully!`));
98
+ console.log(info(`App ID: ${result.app.id}`));
99
+ console.log(info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`));
100
100
  } catch (err) {
101
- error(`Failed to register app: ${err}`);
101
+ console.log(error(`Failed to register app: ${err}`));
102
102
  process.exit(1);
103
103
  }
104
104
  }
@@ -113,11 +113,11 @@ async function registerLocalApp(
113
113
 
114
114
  try {
115
115
  const result = await client.registerApp(environmentId, type, name);
116
- success(`App registered with environment!`);
117
- info(`App ID: ${result.app.id}`);
116
+ console.log(success(`App registered with environment!`));
117
+ console.log(info(`App ID: ${result.app.id}`));
118
118
  } catch (err) {
119
- warning(`Could not register app automatically: ${err}`);
120
- info(`You can register manually in the dashboard.`);
119
+ console.log(warning(`Could not register app automatically: ${err}`));
120
+ console.log(info(`You can register manually in the dashboard.`));
121
121
  }
122
122
  }
123
123
 
@@ -1,20 +1,20 @@
1
1
  import { SaleorCloudClient } from '../api/client.js';
2
2
  import { requireToken } from '../api/auth.js';
3
- import { spinner, success, error, info } from '../tui/components.js';
3
+ import { success, error, info } from '../tui/components.js';
4
4
 
5
5
  export async function createStore(name: string, region: string): Promise<void> {
6
6
  const token = requireToken();
7
7
  const client = new SaleorCloudClient(token);
8
8
 
9
- info(`Creating store: ${name} in ${region}...`);
9
+ console.log(info(`Creating store: ${name} in ${region}...`));
10
10
 
11
11
  try {
12
12
  const result = await client.createStore(name, region);
13
- success(`Store created successfully!`);
14
- info(`Store ID: ${result.store.id}`);
15
- info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`);
13
+ console.log(success(`Store created successfully!`));
14
+ console.log(info(`Store ID: ${result.store.id}`));
15
+ console.log(info(`Dashboard: https://cloud.saleor.io/stores/${result.store.id}`));
16
16
  } catch (err) {
17
- error(`Failed to create store: ${err}`);
17
+ console.log(error(`Failed to create store: ${err}`));
18
18
  process.exit(1);
19
19
  }
20
20
  }
@@ -23,17 +23,17 @@ export async function listStores(): Promise<void> {
23
23
  const token = requireToken();
24
24
  const client = new SaleorCloudClient(token);
25
25
 
26
- info('Fetching stores...');
26
+ console.log(info('Fetching stores...'));
27
27
 
28
28
  try {
29
29
  const result = await client.getStores();
30
30
 
31
31
  if (result.stores.length === 0) {
32
- info('No stores found. Create one with: jolly store create --name <name>');
32
+ console.log(info('No stores found. Create one with: jolly store create --name <name>'));
33
33
  return;
34
34
  }
35
35
 
36
- success(`Found ${result.stores.length} store(s):\n`);
36
+ console.log(success(`Found ${result.stores.length} store(s):\n`));
37
37
  for (const store of result.stores) {
38
38
  console.log(` ${store.name} (${store.id})`);
39
39
  console.log(` Region: ${store.region}`);
@@ -41,7 +41,7 @@ export async function listStores(): Promise<void> {
41
41
  console.log();
42
42
  }
43
43
  } catch (err) {
44
- error(`Failed to list stores: ${err}`);
44
+ console.log(error(`Failed to list stores: ${err}`));
45
45
  process.exit(1);
46
46
  }
47
47
  }
@@ -50,15 +50,15 @@ export async function createEnvironment(storeId: string, name: string): Promise<
50
50
  const token = requireToken();
51
51
  const client = new SaleorCloudClient(token);
52
52
 
53
- info(`Creating environment: ${name} for store ${storeId}...`);
53
+ console.log(info(`Creating environment: ${name} for store ${storeId}...`));
54
54
 
55
55
  try {
56
56
  const result = await client.createEnvironment(storeId, name);
57
- success(`Environment created successfully!`);
58
- info(`Environment ID: ${result.environment.id}`);
59
- info(`API URL will be available at: https://${result.environment.id}.saleor.cloud`);
57
+ console.log(success(`Environment created successfully!`));
58
+ console.log(info(`Environment ID: ${result.environment.id}`));
59
+ console.log(info(`API URL will be available at: https://${result.environment.id}.saleor.cloud`));
60
60
  } catch (err) {
61
- error(`Failed to create environment: ${err}`);
61
+ console.log(error(`Failed to create environment: ${err}`));
62
62
  process.exit(1);
63
63
  }
64
64
  }