@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 +59 -1
- package/dist/bootstrap.js +14 -8
- package/dist/index.js +129 -60
- package/package.json +6 -6
- package/src/api/auth.ts +57 -3
- package/src/cli/commands/app.ts +10 -0
- package/src/cli/commands/store.ts +10 -0
- package/src/commands/app.ts +26 -26
- package/src/commands/store.ts +15 -15
package/bun.lock
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "@saleor/jolly",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"
|
|
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 "
|
|
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(
|
|
60
|
-
|
|
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 "
|
|
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(
|
|
82
|
-
|
|
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 =
|
|
461
|
-
if (
|
|
529
|
+
const fullPath = join2(projectPath, file);
|
|
530
|
+
if (existsSync2(fullPath)) {
|
|
462
531
|
detected.push({
|
|
463
532
|
name,
|
|
464
533
|
path: fullPath,
|
|
465
|
-
skillsPath:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
544
|
-
|
|
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 =
|
|
556
|
-
|
|
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.
|
|
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
|
|
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
|
-
"
|
|
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 '
|
|
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('
|
|
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
|
+
}
|
package/src/cli/commands/app.ts
CHANGED
|
@@ -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
|
}),
|
package/src/commands/app.ts
CHANGED
|
@@ -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
|
|
package/src/commands/store.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { SaleorCloudClient } from '../api/client.js';
|
|
2
2
|
import { requireToken } from '../api/auth.js';
|
|
3
|
-
import {
|
|
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
|
}
|