@dk/jolly 0.1.5 → 0.1.7
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 +42 -19
- package/dist/index.js +91 -68
- package/package.json +6 -6
- package/src/api/auth.ts +1 -1
- package/src/api/client.ts +93 -20
- package/src/commands/app.ts +26 -26
- package/src/commands/store.ts +23 -23
- package/src/test/command-handlers.test.ts +34 -29
- package/src/test/e2e-flows.test.ts +50 -31
- package/src/test/entry-points.test.ts +4 -1
- package/src/test/error-handling.test.ts +8 -8
- package/src/test/mocks.ts +55 -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
|
@@ -11,47 +11,70 @@ class SaleorCloudClient {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
async request(endpoint, options) {
|
|
14
|
-
const
|
|
14
|
+
const mergedOptions = {
|
|
15
|
+
method: options?.method || "GET",
|
|
15
16
|
...options,
|
|
16
17
|
headers: {
|
|
17
|
-
Authorization: `
|
|
18
|
+
Authorization: `Token ${this.token}`,
|
|
18
19
|
"Content-Type": "application/json",
|
|
19
20
|
...options?.headers
|
|
20
21
|
}
|
|
21
|
-
}
|
|
22
|
+
};
|
|
23
|
+
const response = await fetch(`${this.baseUrl}${endpoint}`, mergedOptions);
|
|
22
24
|
if (!response.ok) {
|
|
23
|
-
|
|
25
|
+
const body = await response.text();
|
|
26
|
+
throw new Error(`API error: ${response.status} ${response.statusText} - ${body}`);
|
|
24
27
|
}
|
|
25
28
|
return response.json();
|
|
26
29
|
}
|
|
27
|
-
async
|
|
28
|
-
return this.request("/
|
|
30
|
+
async getOrganizations() {
|
|
31
|
+
return this.request("/organizations");
|
|
29
32
|
}
|
|
30
|
-
async
|
|
31
|
-
return this.request(
|
|
33
|
+
async getProjects(organizationSlug) {
|
|
34
|
+
return this.request(`/organizations/${organizationSlug}/projects`);
|
|
35
|
+
}
|
|
36
|
+
async createProject(organizationSlug, name, region) {
|
|
37
|
+
return this.request(`/organizations/${organizationSlug}/projects`, {
|
|
32
38
|
method: "POST",
|
|
33
39
|
body: JSON.stringify({ name, region })
|
|
34
40
|
});
|
|
35
41
|
}
|
|
36
|
-
async getEnvironments(
|
|
37
|
-
return this.request(`/
|
|
42
|
+
async getEnvironments(organizationSlug, projectSlug) {
|
|
43
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`);
|
|
38
44
|
}
|
|
39
|
-
async createEnvironment(
|
|
40
|
-
return this.request(`/
|
|
45
|
+
async createEnvironment(organizationSlug, projectSlug, name, region) {
|
|
46
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`, {
|
|
41
47
|
method: "POST",
|
|
42
|
-
body: JSON.stringify({ name })
|
|
48
|
+
body: JSON.stringify({ name, region })
|
|
43
49
|
});
|
|
44
50
|
}
|
|
51
|
+
async getEnvironment(organizationSlug, projectSlug, environmentSlug) {
|
|
52
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments/${environmentSlug}`);
|
|
53
|
+
}
|
|
45
54
|
async registerApp(environmentId, appType, name) {
|
|
46
55
|
return this.request(`/environments/${environmentId}/apps`, {
|
|
47
56
|
method: "POST",
|
|
48
57
|
body: JSON.stringify({ type: appType, name })
|
|
49
58
|
});
|
|
50
59
|
}
|
|
60
|
+
async getStores() {
|
|
61
|
+
return this.getOrganizations();
|
|
62
|
+
}
|
|
63
|
+
async createStore(name, region = "us-east-1") {
|
|
64
|
+
const { organizations } = await this.getOrganizations();
|
|
65
|
+
if (organizations.length === 0) {
|
|
66
|
+
throw new Error("No organizations found. Create one at https://cloud.saleor.io");
|
|
67
|
+
}
|
|
68
|
+
return this.createProject(organizations[0].slug, name, region);
|
|
69
|
+
}
|
|
70
|
+
async createEnvironmentFromStore(storeId, name) {
|
|
71
|
+
const { environments } = await this.getEnvironments(storeId, "default");
|
|
72
|
+
return this.createEnvironment(storeId, environments.length > 0 ? environments[0].project?.slug || "default" : "default", name, "default");
|
|
73
|
+
}
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
// src/api/auth.ts
|
|
54
|
-
import { config } from "
|
|
77
|
+
import { config } from "@dotenvx/dotenvx";
|
|
55
78
|
config();
|
|
56
79
|
function requireToken() {
|
|
57
80
|
const token = process.env.SALEOR_CLOUD_TOKEN;
|
|
@@ -125,14 +148,14 @@ function info(msg) {
|
|
|
125
148
|
async function createStore(name, region) {
|
|
126
149
|
const token = requireToken();
|
|
127
150
|
const client = new SaleorCloudClient(token);
|
|
128
|
-
info(`Creating store: ${name} in ${region}...`);
|
|
151
|
+
console.log(info(`Creating store: ${name} in ${region}...`));
|
|
129
152
|
try {
|
|
130
153
|
const result = await client.createStore(name, region);
|
|
131
|
-
success(`Store created successfully!`);
|
|
132
|
-
info(`
|
|
133
|
-
info(`Dashboard: https://cloud.saleor.io/
|
|
154
|
+
console.log(success(`Store created successfully!`));
|
|
155
|
+
console.log(info(`Project slug: ${result.project.slug}`));
|
|
156
|
+
console.log(info(`Dashboard: https://cloud.saleor.io/organizations/default/projects/${result.project.slug}`));
|
|
134
157
|
} catch (err) {
|
|
135
|
-
error(`Failed to create store: ${err}`);
|
|
158
|
+
console.log(error(`Failed to create store: ${err}`));
|
|
136
159
|
process.exit(1);
|
|
137
160
|
}
|
|
138
161
|
}
|
package/dist/index.js
CHANGED
|
@@ -33,47 +33,70 @@ class SaleorCloudClient {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
async request(endpoint, options) {
|
|
36
|
-
const
|
|
36
|
+
const mergedOptions = {
|
|
37
|
+
method: options?.method || "GET",
|
|
37
38
|
...options,
|
|
38
39
|
headers: {
|
|
39
|
-
Authorization: `
|
|
40
|
+
Authorization: `Token ${this.token}`,
|
|
40
41
|
"Content-Type": "application/json",
|
|
41
42
|
...options?.headers
|
|
42
43
|
}
|
|
43
|
-
}
|
|
44
|
+
};
|
|
45
|
+
const response = await fetch(`${this.baseUrl}${endpoint}`, mergedOptions);
|
|
44
46
|
if (!response.ok) {
|
|
45
|
-
|
|
47
|
+
const body = await response.text();
|
|
48
|
+
throw new Error(`API error: ${response.status} ${response.statusText} - ${body}`);
|
|
46
49
|
}
|
|
47
50
|
return response.json();
|
|
48
51
|
}
|
|
49
|
-
async
|
|
50
|
-
return this.request("/
|
|
52
|
+
async getOrganizations() {
|
|
53
|
+
return this.request("/organizations");
|
|
51
54
|
}
|
|
52
|
-
async
|
|
53
|
-
return this.request(
|
|
55
|
+
async getProjects(organizationSlug) {
|
|
56
|
+
return this.request(`/organizations/${organizationSlug}/projects`);
|
|
57
|
+
}
|
|
58
|
+
async createProject(organizationSlug, name, region) {
|
|
59
|
+
return this.request(`/organizations/${organizationSlug}/projects`, {
|
|
54
60
|
method: "POST",
|
|
55
61
|
body: JSON.stringify({ name, region })
|
|
56
62
|
});
|
|
57
63
|
}
|
|
58
|
-
async getEnvironments(
|
|
59
|
-
return this.request(`/
|
|
64
|
+
async getEnvironments(organizationSlug, projectSlug) {
|
|
65
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`);
|
|
60
66
|
}
|
|
61
|
-
async createEnvironment(
|
|
62
|
-
return this.request(`/
|
|
67
|
+
async createEnvironment(organizationSlug, projectSlug, name, region) {
|
|
68
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`, {
|
|
63
69
|
method: "POST",
|
|
64
|
-
body: JSON.stringify({ name })
|
|
70
|
+
body: JSON.stringify({ name, region })
|
|
65
71
|
});
|
|
66
72
|
}
|
|
73
|
+
async getEnvironment(organizationSlug, projectSlug, environmentSlug) {
|
|
74
|
+
return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments/${environmentSlug}`);
|
|
75
|
+
}
|
|
67
76
|
async registerApp(environmentId, appType, name) {
|
|
68
77
|
return this.request(`/environments/${environmentId}/apps`, {
|
|
69
78
|
method: "POST",
|
|
70
79
|
body: JSON.stringify({ type: appType, name })
|
|
71
80
|
});
|
|
72
81
|
}
|
|
82
|
+
async getStores() {
|
|
83
|
+
return this.getOrganizations();
|
|
84
|
+
}
|
|
85
|
+
async createStore(name, region = "us-east-1") {
|
|
86
|
+
const { organizations } = await this.getOrganizations();
|
|
87
|
+
if (organizations.length === 0) {
|
|
88
|
+
throw new Error("No organizations found. Create one at https://cloud.saleor.io");
|
|
89
|
+
}
|
|
90
|
+
return this.createProject(organizations[0].slug, name, region);
|
|
91
|
+
}
|
|
92
|
+
async createEnvironmentFromStore(storeId, name) {
|
|
93
|
+
const { environments } = await this.getEnvironments(storeId, "default");
|
|
94
|
+
return this.createEnvironment(storeId, environments.length > 0 ? environments[0].project?.slug || "default" : "default", name, "default");
|
|
95
|
+
}
|
|
73
96
|
}
|
|
74
97
|
|
|
75
98
|
// src/api/auth.ts
|
|
76
|
-
import { config } from "
|
|
99
|
+
import { config } from "@dotenvx/dotenvx";
|
|
77
100
|
import { writeFileSync, existsSync, readFileSync } from "fs";
|
|
78
101
|
import { join } from "path";
|
|
79
102
|
config();
|
|
@@ -194,51 +217,51 @@ function info(msg) {
|
|
|
194
217
|
async function createStore(name, region) {
|
|
195
218
|
const token = requireToken();
|
|
196
219
|
const client = new SaleorCloudClient(token);
|
|
197
|
-
info(`Creating store: ${name} in ${region}...`);
|
|
220
|
+
console.log(info(`Creating store: ${name} in ${region}...`));
|
|
198
221
|
try {
|
|
199
222
|
const result = await client.createStore(name, region);
|
|
200
|
-
success(`Store created successfully!`);
|
|
201
|
-
info(`
|
|
202
|
-
info(`Dashboard: https://cloud.saleor.io/
|
|
223
|
+
console.log(success(`Store created successfully!`));
|
|
224
|
+
console.log(info(`Project slug: ${result.project.slug}`));
|
|
225
|
+
console.log(info(`Dashboard: https://cloud.saleor.io/organizations/default/projects/${result.project.slug}`));
|
|
203
226
|
} catch (err) {
|
|
204
|
-
error(`Failed to create store: ${err}`);
|
|
227
|
+
console.log(error(`Failed to create store: ${err}`));
|
|
205
228
|
process.exit(1);
|
|
206
229
|
}
|
|
207
230
|
}
|
|
208
231
|
async function listStores() {
|
|
209
232
|
const token = requireToken();
|
|
210
233
|
const client = new SaleorCloudClient(token);
|
|
211
|
-
info("Fetching
|
|
234
|
+
console.log(info("Fetching organizations..."));
|
|
212
235
|
try {
|
|
213
|
-
const
|
|
214
|
-
if (
|
|
215
|
-
info("No
|
|
236
|
+
const { organizations } = await client.getOrganizations();
|
|
237
|
+
if (organizations.length === 0) {
|
|
238
|
+
console.log(info("No organizations found. Create one at https://cloud.saleor.io"));
|
|
216
239
|
return;
|
|
217
240
|
}
|
|
218
|
-
success(`Found ${
|
|
219
|
-
`);
|
|
220
|
-
for (const
|
|
221
|
-
console.log(` ${
|
|
222
|
-
console.log(`
|
|
223
|
-
console.log(` Created: ${new Date(
|
|
241
|
+
console.log(success(`Found ${organizations.length} organization(s):
|
|
242
|
+
`));
|
|
243
|
+
for (const org of organizations) {
|
|
244
|
+
console.log(` ${org.name} (${org.slug})`);
|
|
245
|
+
console.log(` Email: ${org.owner_email}`);
|
|
246
|
+
console.log(` Created: ${new Date(org.created).toLocaleDateString()}`);
|
|
224
247
|
console.log();
|
|
225
248
|
}
|
|
226
249
|
} catch (err) {
|
|
227
|
-
error(`Failed to list stores: ${err}`);
|
|
250
|
+
console.log(error(`Failed to list stores: ${err}`));
|
|
228
251
|
process.exit(1);
|
|
229
252
|
}
|
|
230
253
|
}
|
|
231
|
-
async function createEnvironment(
|
|
254
|
+
async function createEnvironment(organizationSlug, name) {
|
|
232
255
|
const token = requireToken();
|
|
233
256
|
const client = new SaleorCloudClient(token);
|
|
234
|
-
info(`Creating environment: ${name} for
|
|
257
|
+
console.log(info(`Creating environment: ${name} for organization ${organizationSlug}...`));
|
|
235
258
|
try {
|
|
236
|
-
const
|
|
237
|
-
success(`Environment created successfully!`);
|
|
238
|
-
info(`Environment
|
|
239
|
-
info(`
|
|
259
|
+
const { environment } = await client.createEnvironment(organizationSlug, "default", name, "us-east-1");
|
|
260
|
+
console.log(success(`Environment created successfully!`));
|
|
261
|
+
console.log(info(`Environment key: ${environment.key}`));
|
|
262
|
+
console.log(info(`Domain: ${environment.domain}`));
|
|
240
263
|
} catch (err) {
|
|
241
|
-
error(`Failed to create environment: ${err}`);
|
|
264
|
+
console.log(error(`Failed to create environment: ${err}`));
|
|
242
265
|
process.exit(1);
|
|
243
266
|
}
|
|
244
267
|
}
|
|
@@ -323,26 +346,26 @@ var PAYMENT_APP_URLS = {
|
|
|
323
346
|
stripe: "https://stripe-payment.saleor.io"
|
|
324
347
|
};
|
|
325
348
|
async function createApp(name, type, environmentId, provider) {
|
|
326
|
-
info(`Creating ${type} app: ${name}`);
|
|
349
|
+
console.log(info(`Creating ${type} app: ${name}`));
|
|
327
350
|
if (type === "payment") {
|
|
328
351
|
const paymentProvider = provider || "dummy";
|
|
329
|
-
info(`Payment provider: ${paymentProvider}`);
|
|
330
|
-
info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`);
|
|
352
|
+
console.log(info(`Payment provider: ${paymentProvider}`));
|
|
353
|
+
console.log(info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`));
|
|
331
354
|
if (environmentId) {
|
|
332
355
|
await registerHostedApp(environmentId, name, paymentProvider);
|
|
333
356
|
} else {
|
|
334
|
-
success(`
|
|
335
|
-
Payment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`);
|
|
336
|
-
info(`
|
|
337
|
-
To complete setup:`);
|
|
338
|
-
info(`1. Go to your dashboard at https://cloud.saleor.io`);
|
|
339
|
-
info(`2. Navigate to Apps > Third party apps`);
|
|
340
|
-
info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`);
|
|
357
|
+
console.log(success(`
|
|
358
|
+
Payment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`));
|
|
359
|
+
console.log(info(`
|
|
360
|
+
To complete setup:`));
|
|
361
|
+
console.log(info(`1. Go to your dashboard at https://cloud.saleor.io`));
|
|
362
|
+
console.log(info(`2. Navigate to Apps > Third party apps`));
|
|
363
|
+
console.log(info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`));
|
|
341
364
|
}
|
|
342
365
|
return;
|
|
343
366
|
}
|
|
344
367
|
const template = APP_TEMPLATES[type];
|
|
345
|
-
info(`Cloning template from: ${template.repo}`);
|
|
368
|
+
console.log(info(`Cloning template from: ${template.repo}`));
|
|
346
369
|
try {
|
|
347
370
|
const { spawn } = await import("child_process");
|
|
348
371
|
const child = spawn("git", ["clone", template.repo, name], {
|
|
@@ -350,39 +373,39 @@ To complete setup:`);
|
|
|
350
373
|
});
|
|
351
374
|
child.on("close", (code) => {
|
|
352
375
|
if (code === 0) {
|
|
353
|
-
success(`
|
|
354
|
-
${type} app "${name}" created successfully!`);
|
|
355
|
-
info(`
|
|
356
|
-
To get started:`);
|
|
357
|
-
info(`cd ${name}`);
|
|
358
|
-
info(`npm install`);
|
|
359
|
-
info(`npm run dev`);
|
|
376
|
+
console.log(success(`
|
|
377
|
+
${type} app "${name}" created successfully!`));
|
|
378
|
+
console.log(info(`
|
|
379
|
+
To get started:`));
|
|
380
|
+
console.log(info(`cd ${name}`));
|
|
381
|
+
console.log(info(`npm install`));
|
|
382
|
+
console.log(info(`npm run dev`));
|
|
360
383
|
if (environmentId) {
|
|
361
|
-
info(`
|
|
362
|
-
Registering app with environment ${environmentId}...`);
|
|
384
|
+
console.log(info(`
|
|
385
|
+
Registering app with environment ${environmentId}...`));
|
|
363
386
|
registerLocalApp(environmentId, name, type);
|
|
364
387
|
}
|
|
365
388
|
} else {
|
|
366
|
-
error(`Failed to clone template (exit code: ${code})`);
|
|
389
|
+
console.log(error(`Failed to clone template (exit code: ${code})`));
|
|
367
390
|
process.exit(1);
|
|
368
391
|
}
|
|
369
392
|
});
|
|
370
393
|
} catch (err) {
|
|
371
|
-
error(`Failed to create app: ${err}`);
|
|
394
|
+
console.log(error(`Failed to create app: ${err}`));
|
|
372
395
|
process.exit(1);
|
|
373
396
|
}
|
|
374
397
|
}
|
|
375
398
|
async function registerHostedApp(environmentId, name, provider) {
|
|
376
399
|
const token = requireToken();
|
|
377
400
|
const client = new SaleorCloudClient(token);
|
|
378
|
-
info(`Registering hosted ${provider} payment app with environment...`);
|
|
401
|
+
console.log(info(`Registering hosted ${provider} payment app with environment...`));
|
|
379
402
|
try {
|
|
380
403
|
const result = await client.registerApp(environmentId, "payment", name);
|
|
381
|
-
success(`Payment app registered successfully!`);
|
|
382
|
-
info(`App ID: ${result.app.id}`);
|
|
383
|
-
info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`);
|
|
404
|
+
console.log(success(`Payment app registered successfully!`));
|
|
405
|
+
console.log(info(`App ID: ${result.app.id}`));
|
|
406
|
+
console.log(info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`));
|
|
384
407
|
} catch (err) {
|
|
385
|
-
error(`Failed to register app: ${err}`);
|
|
408
|
+
console.log(error(`Failed to register app: ${err}`));
|
|
386
409
|
process.exit(1);
|
|
387
410
|
}
|
|
388
411
|
}
|
|
@@ -391,11 +414,11 @@ async function registerLocalApp(environmentId, name, type) {
|
|
|
391
414
|
const client = new SaleorCloudClient(token);
|
|
392
415
|
try {
|
|
393
416
|
const result = await client.registerApp(environmentId, type, name);
|
|
394
|
-
success(`App registered with environment!`);
|
|
395
|
-
info(`App ID: ${result.app.id}`);
|
|
417
|
+
console.log(success(`App registered with environment!`));
|
|
418
|
+
console.log(info(`App ID: ${result.app.id}`));
|
|
396
419
|
} catch (err) {
|
|
397
|
-
warning(`Could not register app automatically: ${err}`);
|
|
398
|
-
info(`You can register manually in the dashboard.`);
|
|
420
|
+
console.log(warning(`Could not register app automatically: ${err}`));
|
|
421
|
+
console.log(info(`You can register manually in the dashboard.`));
|
|
399
422
|
}
|
|
400
423
|
}
|
|
401
424
|
function warning(msg) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dk/jolly",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
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