@bigcommerce/create-catalyst 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +687 -590
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -53,12 +53,12 @@ var __async = (__this, __arguments, generator) => {
|
|
|
53
53
|
|
|
54
54
|
// src/index.ts
|
|
55
55
|
import { program } from "@commander-js/extra-typings";
|
|
56
|
-
import
|
|
56
|
+
import chalk6 from "chalk";
|
|
57
57
|
|
|
58
58
|
// package.json
|
|
59
59
|
var package_default = {
|
|
60
60
|
name: "@bigcommerce/create-catalyst",
|
|
61
|
-
version: "0.
|
|
61
|
+
version: "0.20.0",
|
|
62
62
|
type: "module",
|
|
63
63
|
bin: "bin/index.cjs",
|
|
64
64
|
files: [
|
|
@@ -77,6 +77,7 @@ var package_default = {
|
|
|
77
77
|
},
|
|
78
78
|
dependencies: {
|
|
79
79
|
"@commander-js/extra-typings": "^12.1.0",
|
|
80
|
+
"@iarna/toml": "^2.2.5",
|
|
80
81
|
"@inquirer/prompts": "^7.2.0",
|
|
81
82
|
"@segment/analytics-node": "^2.2.0",
|
|
82
83
|
chalk: "^5.3.0",
|
|
@@ -87,10 +88,11 @@ var package_default = {
|
|
|
87
88
|
giget: "^1.2.3",
|
|
88
89
|
"lodash.kebabcase": "^4.1.1",
|
|
89
90
|
nypm: "^0.4.1",
|
|
91
|
+
open: "^10.1.0",
|
|
90
92
|
ora: "^8.1.1",
|
|
91
93
|
semver: "^7.6.3",
|
|
92
94
|
"std-env": "^3.8.0",
|
|
93
|
-
zod: "^3.
|
|
95
|
+
zod: "^3.24.1",
|
|
94
96
|
"zod-validation-error": "^3.4.0"
|
|
95
97
|
},
|
|
96
98
|
devDependencies: {
|
|
@@ -101,12 +103,12 @@ var package_default = {
|
|
|
101
103
|
"@types/fs-extra": "^11.0.4",
|
|
102
104
|
"@types/jest": "^29.5.14",
|
|
103
105
|
"@types/lodash.kebabcase": "^4.1.9",
|
|
104
|
-
"@types/node": "^20.17.
|
|
106
|
+
"@types/node": "^20.17.10",
|
|
105
107
|
"@types/prompts": "^2.4.9",
|
|
106
108
|
"@types/semver": "^7.5.8",
|
|
107
109
|
eslint: "^8.57.1",
|
|
108
110
|
jest: "^29.7.0",
|
|
109
|
-
msw: "^2.6.
|
|
111
|
+
msw: "^2.6.9",
|
|
110
112
|
prettier: "^3.4.2",
|
|
111
113
|
tsup: "^8.3.5",
|
|
112
114
|
typescript: "^5.7.2"
|
|
@@ -115,13 +117,122 @@ var package_default = {
|
|
|
115
117
|
|
|
116
118
|
// src/commands/create.ts
|
|
117
119
|
import { Command, Option } from "@commander-js/extra-typings";
|
|
118
|
-
import { input, select
|
|
119
|
-
import
|
|
120
|
+
import { input, select } from "@inquirer/prompts";
|
|
121
|
+
import chalk3 from "chalk";
|
|
120
122
|
import { execSync as execSync5 } from "child_process";
|
|
121
123
|
import { pathExistsSync } from "fs-extra/esm";
|
|
122
124
|
import kebabCase from "lodash.kebabcase";
|
|
123
|
-
import { join as
|
|
124
|
-
|
|
125
|
+
import { join as join3 } from "path";
|
|
126
|
+
|
|
127
|
+
// src/utils/user-agent.ts
|
|
128
|
+
import {
|
|
129
|
+
isDevelopment,
|
|
130
|
+
isLinux,
|
|
131
|
+
isMacOS,
|
|
132
|
+
isProduction,
|
|
133
|
+
isTest,
|
|
134
|
+
isWindows,
|
|
135
|
+
nodeVersion,
|
|
136
|
+
process as process2,
|
|
137
|
+
provider,
|
|
138
|
+
runtime
|
|
139
|
+
} from "std-env";
|
|
140
|
+
var { name, version } = package_default;
|
|
141
|
+
var getOS = () => {
|
|
142
|
+
if (isWindows) return "Windows";
|
|
143
|
+
if (isMacOS) return "macOS";
|
|
144
|
+
if (isLinux) return "Linux";
|
|
145
|
+
return "Unknown OS";
|
|
146
|
+
};
|
|
147
|
+
var getEnv = () => {
|
|
148
|
+
if (isDevelopment) return "Development";
|
|
149
|
+
if (isTest) return "Test";
|
|
150
|
+
if (isProduction) return "Production";
|
|
151
|
+
};
|
|
152
|
+
var getPlatform = () => {
|
|
153
|
+
const os = getOS();
|
|
154
|
+
const env = getEnv();
|
|
155
|
+
const keysOfInterest = [
|
|
156
|
+
os,
|
|
157
|
+
env,
|
|
158
|
+
runtime,
|
|
159
|
+
provider,
|
|
160
|
+
`Node ${nodeVersion}`,
|
|
161
|
+
process2.env.NODE_ENV
|
|
162
|
+
].filter(Boolean);
|
|
163
|
+
return keysOfInterest.join("; ");
|
|
164
|
+
};
|
|
165
|
+
var detectedPlatform = getPlatform();
|
|
166
|
+
var getCLIUserAgent = (platform, extensions) => {
|
|
167
|
+
const userAgentParts = [`${name}/${version}`];
|
|
168
|
+
const platformValue = platform != null ? platform : detectedPlatform;
|
|
169
|
+
userAgentParts.push(`(${platformValue})`);
|
|
170
|
+
if (extensions) {
|
|
171
|
+
userAgentParts.push(extensions);
|
|
172
|
+
}
|
|
173
|
+
return userAgentParts.join(" ");
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// src/utils/https.ts
|
|
177
|
+
var Https = class {
|
|
178
|
+
constructor({ baseUrl, accessToken }) {
|
|
179
|
+
this.baseUrl = baseUrl;
|
|
180
|
+
this.accessToken = accessToken;
|
|
181
|
+
this.userAgent = getCLIUserAgent();
|
|
182
|
+
}
|
|
183
|
+
fetch(_0) {
|
|
184
|
+
return __async(this, arguments, function* (path, opts = {}) {
|
|
185
|
+
const _a = opts, { headers = {} } = _a, rest = __objRest(_a, ["headers"]);
|
|
186
|
+
const options = __spreadValues({
|
|
187
|
+
headers: __spreadValues(__spreadProps(__spreadValues({}, headers), {
|
|
188
|
+
Accept: "application/json",
|
|
189
|
+
"User-Agent": this.userAgent
|
|
190
|
+
}), this.accessToken && { "X-Auth-Token": this.accessToken })
|
|
191
|
+
}, rest);
|
|
192
|
+
return fetch(`${this.baseUrl}${path}`, options);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// src/utils/cli-api.ts
|
|
198
|
+
var CliApi = class {
|
|
199
|
+
constructor({ origin, storeHash, accessToken }) {
|
|
200
|
+
this.client = new Https({
|
|
201
|
+
baseUrl: `${origin}/stores/${storeHash}/cli-api/v3`,
|
|
202
|
+
accessToken
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
getChannelInit(channelId) {
|
|
206
|
+
return __async(this, null, function* () {
|
|
207
|
+
return this.client.fetch(`/channels/${channelId}/init`, {
|
|
208
|
+
method: "GET"
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
checkEligibility() {
|
|
213
|
+
return __async(this, null, function* () {
|
|
214
|
+
return this.client.fetch("/channels/catalyst/eligibility", {
|
|
215
|
+
method: "GET"
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
createChannel(name2, installSampleData = false) {
|
|
220
|
+
return __async(this, null, function* () {
|
|
221
|
+
return this.client.fetch("/channels/catalyst", {
|
|
222
|
+
method: "POST",
|
|
223
|
+
headers: { "Content-Type": "application/json" },
|
|
224
|
+
body: JSON.stringify({
|
|
225
|
+
name: name2,
|
|
226
|
+
initialData: {
|
|
227
|
+
type: installSampleData ? "sample" : "none"
|
|
228
|
+
},
|
|
229
|
+
deployStorefront: true,
|
|
230
|
+
devOrigin: "http://localhost:3000"
|
|
231
|
+
})
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
};
|
|
125
236
|
|
|
126
237
|
// src/utils/clone-catalyst.ts
|
|
127
238
|
import { execSync as execSync4 } from "child_process";
|
|
@@ -209,7 +320,7 @@ var cloneCatalyst = ({
|
|
|
209
320
|
console.log();
|
|
210
321
|
if (ghRef) {
|
|
211
322
|
if (resetMain) {
|
|
212
|
-
|
|
323
|
+
execSync4("git checkout -b main", { cwd: projectDir, stdio: "inherit" });
|
|
213
324
|
resetBranchToRef(projectDir, ghRef);
|
|
214
325
|
console.log(`Reset main to ${ghRef} successfully.`);
|
|
215
326
|
console.log();
|
|
@@ -220,8 +331,36 @@ var cloneCatalyst = ({
|
|
|
220
331
|
}
|
|
221
332
|
};
|
|
222
333
|
|
|
223
|
-
// src/utils/
|
|
334
|
+
// src/utils/install-dependencies.ts
|
|
224
335
|
import chalk from "chalk";
|
|
336
|
+
import { installDependencies as installDeps } from "nypm";
|
|
337
|
+
|
|
338
|
+
// src/utils/spinner.ts
|
|
339
|
+
import { oraPromise } from "ora";
|
|
340
|
+
var spinner = (action, oraOpts) => __async(void 0, null, function* () {
|
|
341
|
+
return oraPromise(action, __spreadValues({
|
|
342
|
+
spinner: "triangle"
|
|
343
|
+
}, oraOpts)).catch(() => process.exit(1));
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// src/utils/install-dependencies.ts
|
|
347
|
+
var installAllDeps = (projectDir) => __async(void 0, null, function* () {
|
|
348
|
+
yield installDeps({ cwd: projectDir, silent: true, packageManager: "pnpm" });
|
|
349
|
+
});
|
|
350
|
+
var installDependencies = (projectDir) => __async(void 0, null, function* () {
|
|
351
|
+
return spinner(installAllDeps(projectDir), {
|
|
352
|
+
text: `Installing dependencies. This could take a minute...`,
|
|
353
|
+
successText: `Dependencies installed successfully`,
|
|
354
|
+
failText: (err) => chalk.red(`Failed to install dependencies: ${err.message}`)
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// src/utils/login.ts
|
|
359
|
+
import chalk2 from "chalk";
|
|
360
|
+
import open from "open";
|
|
361
|
+
import { createInterface } from "readline";
|
|
362
|
+
|
|
363
|
+
// src/utils/auth.ts
|
|
225
364
|
import { z as z2 } from "zod";
|
|
226
365
|
|
|
227
366
|
// src/utils/parse.ts
|
|
@@ -238,113 +377,17 @@ var parse = (data, schema) => {
|
|
|
238
377
|
}
|
|
239
378
|
};
|
|
240
379
|
|
|
241
|
-
// src/utils/
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
isProduction,
|
|
247
|
-
isTest,
|
|
248
|
-
isWindows,
|
|
249
|
-
nodeVersion,
|
|
250
|
-
process as process2,
|
|
251
|
-
provider,
|
|
252
|
-
runtime
|
|
253
|
-
} from "std-env";
|
|
254
|
-
var { name, version } = package_default;
|
|
255
|
-
var getOS = () => {
|
|
256
|
-
if (isWindows) return "Windows";
|
|
257
|
-
if (isMacOS) return "macOS";
|
|
258
|
-
if (isLinux) return "Linux";
|
|
259
|
-
return "Unknown OS";
|
|
260
|
-
};
|
|
261
|
-
var getEnv = () => {
|
|
262
|
-
if (isDevelopment) return "Development";
|
|
263
|
-
if (isTest) return "Test";
|
|
264
|
-
if (isProduction) return "Production";
|
|
265
|
-
};
|
|
266
|
-
var getPlatform = () => {
|
|
267
|
-
const os = getOS();
|
|
268
|
-
const env = getEnv();
|
|
269
|
-
const keysOfInterest = [
|
|
270
|
-
os,
|
|
271
|
-
env,
|
|
272
|
-
runtime,
|
|
273
|
-
provider,
|
|
274
|
-
`Node ${nodeVersion}`,
|
|
275
|
-
process2.env.NODE_ENV
|
|
276
|
-
].filter(Boolean);
|
|
277
|
-
return keysOfInterest.join("; ");
|
|
278
|
-
};
|
|
279
|
-
var detectedPlatform = getPlatform();
|
|
280
|
-
var getCLIUserAgent = (platform, extensions) => {
|
|
281
|
-
const userAgentParts = [`${name}/${version}`];
|
|
282
|
-
const platformValue = platform != null ? platform : detectedPlatform;
|
|
283
|
-
userAgentParts.push(`(${platformValue})`);
|
|
284
|
-
if (extensions) {
|
|
285
|
-
userAgentParts.push(extensions);
|
|
286
|
-
}
|
|
287
|
-
return userAgentParts.join(" ");
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// src/utils/https.ts
|
|
291
|
-
var BigCommerceStoreInfo = z2.object({
|
|
292
|
-
features: z2.object({
|
|
293
|
-
storefront_limits: z2.object({
|
|
294
|
-
active: z2.number(),
|
|
295
|
-
total_including_inactive: z2.number()
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
});
|
|
299
|
-
var BigCommerceV3ApiResponseSchema = (schema) => z2.object({
|
|
300
|
-
data: schema,
|
|
301
|
-
meta: z2.object({})
|
|
302
|
-
});
|
|
303
|
-
var BigCommerceChannelsV3ResponseSchema = BigCommerceV3ApiResponseSchema(
|
|
304
|
-
z2.array(
|
|
305
|
-
z2.object({
|
|
306
|
-
id: z2.number(),
|
|
307
|
-
name: z2.string(),
|
|
308
|
-
status: z2.string(),
|
|
309
|
-
platform: z2.string()
|
|
310
|
-
})
|
|
311
|
-
)
|
|
312
|
-
);
|
|
313
|
-
var Https = class {
|
|
314
|
-
constructor({
|
|
315
|
-
bigCommerceApiUrl,
|
|
316
|
-
bigCommerceAuthUrl,
|
|
317
|
-
sampleDataApiUrl,
|
|
318
|
-
storeHash,
|
|
319
|
-
accessToken
|
|
320
|
-
}) {
|
|
321
|
-
this.DEVICE_OAUTH_CLIENT_ID = "acse0vvawm9r1n0evag4b8e1ea1fo90";
|
|
322
|
-
this.MAX_EPOC_EXPIRES_AT = 2147483647;
|
|
323
|
-
this.bigCommerceApiUrl = bigCommerceApiUrl != null ? bigCommerceApiUrl : "";
|
|
324
|
-
this.bigCommerceAuthUrl = bigCommerceAuthUrl != null ? bigCommerceAuthUrl : "";
|
|
325
|
-
this.sampleDataApiUrl = sampleDataApiUrl != null ? sampleDataApiUrl : "";
|
|
326
|
-
this.storeHash = storeHash != null ? storeHash : "";
|
|
327
|
-
this.accessToken = accessToken != null ? accessToken : "";
|
|
328
|
-
this.userAgent = getCLIUserAgent();
|
|
329
|
-
}
|
|
330
|
-
auth(path, opts = {}) {
|
|
331
|
-
if (!this.bigCommerceAuthUrl) {
|
|
332
|
-
throw new Error("bigCommerceAuthUrl is required to make API requests");
|
|
333
|
-
}
|
|
334
|
-
const _a = opts, { headers = {} } = _a, rest = __objRest(_a, ["headers"]);
|
|
335
|
-
const options = __spreadValues({
|
|
336
|
-
method: "POST",
|
|
337
|
-
headers: __spreadProps(__spreadValues({}, headers), {
|
|
338
|
-
Accept: "application/json",
|
|
339
|
-
"Content-Type": "application/json",
|
|
340
|
-
"User-Agent": this.userAgent
|
|
341
|
-
})
|
|
342
|
-
}, rest);
|
|
343
|
-
return fetch(`${this.bigCommerceAuthUrl}${path}`, options);
|
|
380
|
+
// src/utils/auth.ts
|
|
381
|
+
var Auth = class {
|
|
382
|
+
constructor({ baseUrl }) {
|
|
383
|
+
this.DEVICE_OAUTH_CLIENT_ID = "s1q4io7mah2lm1i6uwp9yl1eit80n3b";
|
|
384
|
+
this.client = new Https({ baseUrl });
|
|
344
385
|
}
|
|
345
386
|
getDeviceCode() {
|
|
346
387
|
return __async(this, null, function* () {
|
|
347
|
-
const response = yield this.
|
|
388
|
+
const response = yield this.client.fetch("/device/token", {
|
|
389
|
+
method: "POST",
|
|
390
|
+
headers: { "Content-Type": "application/json" },
|
|
348
391
|
body: JSON.stringify({
|
|
349
392
|
scopes: [
|
|
350
393
|
"store_channel_settings",
|
|
@@ -358,14 +401,6 @@ var Https = class {
|
|
|
358
401
|
client_id: this.DEVICE_OAUTH_CLIENT_ID
|
|
359
402
|
})
|
|
360
403
|
});
|
|
361
|
-
if (!response.ok) {
|
|
362
|
-
console.error(
|
|
363
|
-
chalk.red(`
|
|
364
|
-
POST /device/token failed: ${response.status} ${response.statusText}
|
|
365
|
-
`)
|
|
366
|
-
);
|
|
367
|
-
process.exit(1);
|
|
368
|
-
}
|
|
369
404
|
const DeviceCodeSchema = z2.object({
|
|
370
405
|
device_code: z2.string(),
|
|
371
406
|
user_code: z2.string(),
|
|
@@ -378,7 +413,9 @@ POST /device/token failed: ${response.status} ${response.statusText}
|
|
|
378
413
|
}
|
|
379
414
|
checkDeviceCode(deviceCode) {
|
|
380
415
|
return __async(this, null, function* () {
|
|
381
|
-
const response = yield this.
|
|
416
|
+
const response = yield this.client.fetch("/device/token", {
|
|
417
|
+
method: "POST",
|
|
418
|
+
headers: { "Content-Type": "application/json" },
|
|
382
419
|
body: JSON.stringify({
|
|
383
420
|
device_code: deviceCode,
|
|
384
421
|
client_id: this.DEVICE_OAUTH_CLIENT_ID
|
|
@@ -396,243 +433,149 @@ POST /device/token failed: ${response.status} ${response.statusText}
|
|
|
396
433
|
return parse(yield response.json(), DeviceCodeSuccessSchema);
|
|
397
434
|
});
|
|
398
435
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
})
|
|
412
|
-
}, rest);
|
|
413
|
-
return fetch(`${this.bigCommerceApiUrl}/stores/${this.storeHash}${path}`, options);
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// src/utils/config.ts
|
|
439
|
+
import { parse as parseTOML, stringify as stringifyTOML } from "@iarna/toml";
|
|
440
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
441
|
+
import { dirname, join } from "path";
|
|
442
|
+
function isRecord(value) {
|
|
443
|
+
return typeof value === "object" && value !== null;
|
|
444
|
+
}
|
|
445
|
+
function isCatalystConfig(obj) {
|
|
446
|
+
if (!isRecord(obj)) {
|
|
447
|
+
return false;
|
|
414
448
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
`));
|
|
422
|
-
process.exit(1);
|
|
423
|
-
}
|
|
424
|
-
return parse(yield res.json(), BigCommerceStoreInfo);
|
|
425
|
-
});
|
|
449
|
+
if ("auth" in obj) {
|
|
450
|
+
if (!isRecord(obj.auth)) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
const { storeHash, accessToken } = obj.auth;
|
|
454
|
+
return (storeHash === void 0 || typeof storeHash === "string") && (accessToken === void 0 || typeof accessToken === "string");
|
|
426
455
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
`));
|
|
434
|
-
process.exit(1);
|
|
435
|
-
}
|
|
436
|
-
return parse(yield res.json(), BigCommerceChannelsV3ResponseSchema);
|
|
437
|
-
});
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
var Config = class {
|
|
459
|
+
constructor(projectDir) {
|
|
460
|
+
this.configPath = join(projectDir, ".catalyst");
|
|
461
|
+
this.config = this.read();
|
|
438
462
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
method: "POST",
|
|
443
|
-
headers: { "Content-Type": "application/json" },
|
|
444
|
-
body: JSON.stringify({
|
|
445
|
-
bigcommerce_protected_app_sections: [
|
|
446
|
-
"storefront_settings",
|
|
447
|
-
"currencies",
|
|
448
|
-
"domains",
|
|
449
|
-
"notifications",
|
|
450
|
-
"social"
|
|
451
|
-
]
|
|
452
|
-
})
|
|
453
|
-
});
|
|
454
|
-
if (!res.ok) {
|
|
455
|
-
console.warn(
|
|
456
|
-
chalk.yellow(
|
|
457
|
-
`
|
|
458
|
-
Failed to create channel menus: ${res.status} ${res.statusText}. You may want to create these later: https://developer.bigcommerce.com/docs/rest-management/channels/menus#create-channel-menus
|
|
459
|
-
`
|
|
460
|
-
)
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
});
|
|
463
|
+
getAuth() {
|
|
464
|
+
var _a;
|
|
465
|
+
return (_a = this.config.auth) != null ? _a : {};
|
|
464
466
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
method: "POST",
|
|
469
|
-
headers: { "Content-Type": "application/json" },
|
|
470
|
-
body: JSON.stringify({ expires_at: this.MAX_EPOC_EXPIRES_AT, channel_ids: [] })
|
|
471
|
-
});
|
|
472
|
-
if (!res.ok) {
|
|
473
|
-
console.error(
|
|
474
|
-
chalk.red(`
|
|
475
|
-
POST /v3/storefront/api-token failed: ${res.status} ${res.statusText}
|
|
476
|
-
`)
|
|
477
|
-
);
|
|
478
|
-
process.exit(1);
|
|
479
|
-
}
|
|
480
|
-
const BigCommerceStorefrontTokenSchema = z2.object({
|
|
481
|
-
data: z2.object({
|
|
482
|
-
token: z2.string()
|
|
483
|
-
})
|
|
484
|
-
});
|
|
485
|
-
return parse(yield res.json(), BigCommerceStorefrontTokenSchema);
|
|
486
|
-
});
|
|
467
|
+
setAuth(storeHash, accessToken) {
|
|
468
|
+
this.config.auth = { storeHash, accessToken };
|
|
469
|
+
this.save();
|
|
487
470
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
471
|
+
save() {
|
|
472
|
+
var _a;
|
|
473
|
+
const configObj = {};
|
|
474
|
+
if (((_a = this.config.auth) == null ? void 0 : _a.storeHash) && this.config.auth.accessToken) {
|
|
475
|
+
configObj.auth = {
|
|
476
|
+
storeHash: this.config.auth.storeHash,
|
|
477
|
+
accessToken: this.config.auth.accessToken
|
|
478
|
+
};
|
|
493
479
|
}
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
checkEligibility() {
|
|
507
|
-
return __async(this, null, function* () {
|
|
508
|
-
const res = yield this.sampleDataApi("/v3/channels/catalyst/eligibility", {
|
|
509
|
-
method: "GET"
|
|
510
|
-
});
|
|
511
|
-
if (!res.ok) {
|
|
512
|
-
console.error(
|
|
513
|
-
chalk.red(
|
|
514
|
-
`
|
|
515
|
-
GET /v3/channels/catalyst/eligibility failed: ${res.status} ${res.statusText}
|
|
516
|
-
`
|
|
517
|
-
)
|
|
518
|
-
);
|
|
519
|
-
process.exit(1);
|
|
520
|
-
}
|
|
521
|
-
const CheckEligibilitySchema = z2.object({
|
|
522
|
-
data: z2.object({
|
|
523
|
-
eligible: z2.boolean(),
|
|
524
|
-
message: z2.string()
|
|
525
|
-
})
|
|
526
|
-
});
|
|
527
|
-
return parse(yield res.json(), CheckEligibilitySchema);
|
|
528
|
-
});
|
|
480
|
+
const dir = dirname(this.configPath);
|
|
481
|
+
if (!existsSync(dir)) {
|
|
482
|
+
mkdirSync(dir, { recursive: true });
|
|
483
|
+
}
|
|
484
|
+
const preamble = `# DO NOT commit this file to your repository!
|
|
485
|
+
# This file contains sensitive configuration specific to your local CLI setup.
|
|
486
|
+
# It includes authentication tokens and store-specific information.
|
|
487
|
+
# If using version control, make sure to add .catalyst to your .gitignore file.
|
|
488
|
+
|
|
489
|
+
`;
|
|
490
|
+
writeFileSync(this.configPath, preamble + stringifyTOML(configObj));
|
|
529
491
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
`)
|
|
540
|
-
);
|
|
541
|
-
process.exit(1);
|
|
492
|
+
read() {
|
|
493
|
+
if (!existsSync(this.configPath)) {
|
|
494
|
+
return {};
|
|
495
|
+
}
|
|
496
|
+
try {
|
|
497
|
+
const contents = readFileSync(this.configPath, "utf-8");
|
|
498
|
+
const parsed = parseTOML(contents);
|
|
499
|
+
if (isCatalystConfig(parsed)) {
|
|
500
|
+
return parsed;
|
|
542
501
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
});
|
|
550
|
-
return parse(yield res.json(), SampleDataChannelCreateSchema);
|
|
551
|
-
});
|
|
502
|
+
console.warn("Invalid config format in .catalyst file, using defaults");
|
|
503
|
+
return {};
|
|
504
|
+
} catch (e) {
|
|
505
|
+
console.warn("Failed to parse .catalyst config file, using defaults");
|
|
506
|
+
return {};
|
|
507
|
+
}
|
|
552
508
|
}
|
|
553
509
|
};
|
|
554
510
|
|
|
555
|
-
// src/utils/install-dependencies.ts
|
|
556
|
-
import chalk2 from "chalk";
|
|
557
|
-
import { installDependencies as installDeps } from "nypm";
|
|
558
|
-
|
|
559
|
-
// src/utils/spinner.ts
|
|
560
|
-
import { oraPromise } from "ora";
|
|
561
|
-
var spinner = (action, oraOpts) => __async(void 0, null, function* () {
|
|
562
|
-
return oraPromise(action, __spreadValues({
|
|
563
|
-
spinner: "triangle"
|
|
564
|
-
}, oraOpts)).catch(() => process.exit(1));
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
// src/utils/install-dependencies.ts
|
|
568
|
-
var installAllDeps = (projectDir) => __async(void 0, null, function* () {
|
|
569
|
-
yield installDeps({ cwd: projectDir, silent: true, packageManager: "pnpm" });
|
|
570
|
-
});
|
|
571
|
-
var installDependencies = (projectDir) => __async(void 0, null, function* () {
|
|
572
|
-
return spinner(installAllDeps(projectDir), {
|
|
573
|
-
text: `Installing dependencies. This could take a minute...`,
|
|
574
|
-
successText: `Dependencies installed successfully`,
|
|
575
|
-
failText: (err) => chalk2.red(`Failed to install dependencies: ${err.message}`)
|
|
576
|
-
});
|
|
577
|
-
});
|
|
578
|
-
|
|
579
511
|
// src/utils/login.ts
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
var poll = (auth, deviceCode, interval, expiresIn) => __async(void 0, null, function* () {
|
|
583
|
-
const intervalMs = interval * 1e3;
|
|
584
|
-
const expiresAtMs = expiresIn * 1e3;
|
|
585
|
-
const retries = expiresAtMs / intervalMs;
|
|
586
|
-
for (let i = 0; i < retries; i += 1) {
|
|
512
|
+
function pollDeviceCode(auth, deviceCode, interval) {
|
|
513
|
+
return __async(this, null, function* () {
|
|
587
514
|
try {
|
|
588
|
-
|
|
515
|
+
const credentials = yield auth.checkDeviceCode(deviceCode);
|
|
516
|
+
return credentials;
|
|
589
517
|
} catch (e) {
|
|
518
|
+
yield new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
519
|
+
return null;
|
|
590
520
|
}
|
|
591
|
-
yield new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
592
|
-
}
|
|
593
|
-
console.error(chalk3.red("\nDevice code expired. Please try again.\n"));
|
|
594
|
-
process.exit(1);
|
|
595
|
-
});
|
|
596
|
-
var login = (bigCommerceAuthUrl, storeHash, accessToken) => __async(void 0, null, function* () {
|
|
597
|
-
if (storeHash && accessToken) {
|
|
598
|
-
return { storeHash, accessToken };
|
|
599
|
-
}
|
|
600
|
-
const shouldLogin = yield select({
|
|
601
|
-
message: "Would you like to connect to a BigCommerce store?",
|
|
602
|
-
choices: [
|
|
603
|
-
{ name: "Yes", value: true },
|
|
604
|
-
{ name: "No", value: false }
|
|
605
|
-
]
|
|
606
521
|
});
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
[
|
|
614
|
-
`
|
|
615
|
-
Please visit ${chalk3.cyan(deviceCode.verification_uri)} and enter the code: ${chalk3.yellow(
|
|
616
|
-
deviceCode.user_code
|
|
617
|
-
)}
|
|
618
|
-
`,
|
|
619
|
-
`The code will expire in ${chalk3.yellow(`${deviceCode.expires_in / 60} minutes`)}
|
|
620
|
-
`
|
|
621
|
-
].join("\n")
|
|
622
|
-
);
|
|
623
|
-
const { store_hash, access_token } = yield spinner(
|
|
624
|
-
poll(auth, deviceCode.device_code, deviceCode.interval, deviceCode.expires_in),
|
|
625
|
-
{
|
|
626
|
-
text: "Waiting for device code to be authorized",
|
|
627
|
-
successText: "Device code authorized\n",
|
|
628
|
-
failText: "Device code expired\n"
|
|
522
|
+
}
|
|
523
|
+
function waitForCredentials(auth, deviceCode, interval) {
|
|
524
|
+
return __async(this, null, function* () {
|
|
525
|
+
const credentials = yield pollDeviceCode(auth, deviceCode, interval);
|
|
526
|
+
if (credentials) {
|
|
527
|
+
return credentials;
|
|
629
528
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
529
|
+
return waitForCredentials(auth, deviceCode, interval);
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
function waitForKeyPress(prompt) {
|
|
533
|
+
return __async(this, null, function* () {
|
|
534
|
+
const rl = createInterface({
|
|
535
|
+
input: process.stdin,
|
|
536
|
+
output: process.stdout
|
|
537
|
+
});
|
|
538
|
+
process.stdin.setRawMode(true);
|
|
539
|
+
process.stdin.resume();
|
|
540
|
+
return new Promise((resolve) => {
|
|
541
|
+
process.stdin.once("data", (data) => {
|
|
542
|
+
process.stdin.setRawMode(false);
|
|
543
|
+
process.stdin.pause();
|
|
544
|
+
rl.close();
|
|
545
|
+
const shouldProceed = data[0] === 13 || data[0] === 10;
|
|
546
|
+
process.stdout.write("\n");
|
|
547
|
+
resolve(shouldProceed);
|
|
548
|
+
});
|
|
549
|
+
rl.write(prompt);
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
function login(baseUrl) {
|
|
554
|
+
return __async(this, null, function* () {
|
|
555
|
+
const auth = new Auth({ baseUrl });
|
|
556
|
+
const deviceCode = yield auth.getDeviceCode();
|
|
557
|
+
console.log(
|
|
558
|
+
chalk2.yellow("\n! First copy your one-time code: ") + chalk2.bold(deviceCode.user_code)
|
|
559
|
+
);
|
|
560
|
+
console.log(`Press Enter to open ${deviceCode.verification_uri} in your browser...`);
|
|
561
|
+
const shouldOpenUrl = yield waitForKeyPress("");
|
|
562
|
+
if (shouldOpenUrl) {
|
|
563
|
+
yield open(deviceCode.verification_uri);
|
|
564
|
+
}
|
|
565
|
+
const credentials = yield spinner(
|
|
566
|
+
() => waitForCredentials(auth, deviceCode.device_code, deviceCode.interval),
|
|
567
|
+
{ text: "Waiting for authentication...", successText: "Authentication complete" }
|
|
568
|
+
);
|
|
569
|
+
return {
|
|
570
|
+
storeHash: credentials.store_hash,
|
|
571
|
+
accessToken: credentials.access_token
|
|
572
|
+
};
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
function storeCredentials(projectDir, credentials) {
|
|
576
|
+
const config = new Config(projectDir);
|
|
577
|
+
config.setAuth(credentials.storeHash, credentials.accessToken);
|
|
578
|
+
}
|
|
636
579
|
|
|
637
580
|
// src/utils/telemetry/telemetry.ts
|
|
638
581
|
import { Analytics } from "@segment/analytics-node";
|
|
@@ -720,28 +663,13 @@ var Telemetry = class {
|
|
|
720
663
|
};
|
|
721
664
|
|
|
722
665
|
// src/utils/write-env.ts
|
|
723
|
-
import { randomBytes as randomBytes2 } from "crypto";
|
|
724
666
|
import { outputFileSync } from "fs-extra/esm";
|
|
725
|
-
import { join } from "path";
|
|
726
|
-
var writeEnv = (projectDir, {
|
|
727
|
-
channelId,
|
|
728
|
-
storeHash,
|
|
729
|
-
storefrontToken,
|
|
730
|
-
arbitraryEnv
|
|
731
|
-
}) => {
|
|
667
|
+
import { join as join2 } from "path";
|
|
668
|
+
var writeEnv = (projectDir, envVars) => {
|
|
732
669
|
outputFileSync(
|
|
733
|
-
|
|
734
|
-
[
|
|
735
|
-
|
|
736
|
-
`BIGCOMMERCE_CHANNEL_ID=${channelId}`,
|
|
737
|
-
`BIGCOMMERCE_STOREFRONT_TOKEN=${storefrontToken}`,
|
|
738
|
-
"",
|
|
739
|
-
`AUTH_SECRET=${randomBytes2(32).toString("hex")}`,
|
|
740
|
-
`CLIENT_LOGGER=false`,
|
|
741
|
-
`ENABLE_ADMIN_ROUTE=true`,
|
|
742
|
-
`DEFAULT_REVALIDATE_TARGET=3600`,
|
|
743
|
-
arbitraryEnv == null ? void 0 : arbitraryEnv.map((env) => env).join("\n")
|
|
744
|
-
].join("\n")
|
|
670
|
+
join2(projectDir, ".env.local"),
|
|
671
|
+
`${Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n")}
|
|
672
|
+
`
|
|
745
673
|
);
|
|
746
674
|
};
|
|
747
675
|
|
|
@@ -751,285 +679,454 @@ function getPlatformCheckCommand(command) {
|
|
|
751
679
|
return isWindows2 ? `where.exe ${command}` : `which ${command}`;
|
|
752
680
|
}
|
|
753
681
|
var telemetry = new Telemetry();
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
)
|
|
759
|
-
|
|
682
|
+
function handleChannelCreation(cliApi) {
|
|
683
|
+
return __async(this, null, function* () {
|
|
684
|
+
const newChannelName = yield input({
|
|
685
|
+
message: "What would you like to name your new channel?"
|
|
686
|
+
});
|
|
687
|
+
const shouldInstallSampleData = yield select({
|
|
688
|
+
message: "Would you like to install sample data?",
|
|
689
|
+
choices: [
|
|
690
|
+
{ name: "Yes", value: true },
|
|
691
|
+
{ name: "No", value: false }
|
|
692
|
+
]
|
|
693
|
+
});
|
|
694
|
+
const response = yield cliApi.createChannel(newChannelName, shouldInstallSampleData);
|
|
695
|
+
if (!response.ok) {
|
|
696
|
+
console.error(
|
|
697
|
+
chalk3.red(`
|
|
698
|
+
POST /channels/catalyst failed: ${response.status} ${response.statusText}
|
|
699
|
+
`)
|
|
700
|
+
);
|
|
701
|
+
process.exit(1);
|
|
702
|
+
}
|
|
703
|
+
const channelData = yield response.json();
|
|
704
|
+
if (!isCreateChannelResponse(channelData)) {
|
|
705
|
+
console.error(chalk3.red("\nUnexpected response format from create channel endpoint\n"));
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
return {
|
|
709
|
+
channelId: channelData.data.id,
|
|
710
|
+
storefrontToken: channelData.data.storefront_api_token,
|
|
711
|
+
envVars: channelData.data.envVars
|
|
712
|
+
};
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
function handleChannelSelection(bc) {
|
|
716
|
+
return __async(this, null, function* () {
|
|
717
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
718
|
+
const channelsResponse = yield bc.fetch("/v3/channels?available=true&type=storefront");
|
|
719
|
+
if (!channelsResponse.ok) {
|
|
720
|
+
console.error(
|
|
721
|
+
chalk3.red(
|
|
722
|
+
`
|
|
723
|
+
GET /v3/channels failed: ${channelsResponse.status} ${channelsResponse.statusText}
|
|
724
|
+
`
|
|
725
|
+
)
|
|
726
|
+
);
|
|
727
|
+
process.exit(1);
|
|
728
|
+
}
|
|
729
|
+
const availableChannels = yield channelsResponse.json();
|
|
730
|
+
if (!isChannelsResponse(availableChannels)) {
|
|
731
|
+
console.error(chalk3.red("\nUnexpected response format from channels endpoint\n"));
|
|
732
|
+
process.exit(1);
|
|
733
|
+
}
|
|
734
|
+
const existingChannel = yield select({
|
|
735
|
+
message: "Which channel would you like to use?",
|
|
736
|
+
choices: availableChannels.data.sort((a, b) => {
|
|
737
|
+
const aIndex = channelSortOrder.indexOf(a.platform);
|
|
738
|
+
const bIndex = channelSortOrder.indexOf(b.platform);
|
|
739
|
+
if (aIndex === -1 && bIndex === -1) {
|
|
740
|
+
return 0;
|
|
741
|
+
}
|
|
742
|
+
if (aIndex === -1) return 1;
|
|
743
|
+
if (bIndex === -1) return -1;
|
|
744
|
+
return aIndex - bIndex;
|
|
745
|
+
}).map((ch) => ({
|
|
746
|
+
name: ch.name,
|
|
747
|
+
value: ch,
|
|
748
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
749
|
+
}))
|
|
750
|
+
});
|
|
751
|
+
return existingChannel.id;
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
function getChannelInit(cliApi, channelId) {
|
|
755
|
+
return __async(this, null, function* () {
|
|
756
|
+
const initResponse = yield cliApi.getChannelInit(channelId);
|
|
757
|
+
if (!initResponse.ok) {
|
|
758
|
+
console.error(
|
|
759
|
+
chalk3.red(
|
|
760
|
+
`
|
|
761
|
+
GET /channels/${channelId}/init failed: ${initResponse.status} ${initResponse.statusText}
|
|
762
|
+
`
|
|
763
|
+
)
|
|
764
|
+
);
|
|
765
|
+
process.exit(1);
|
|
766
|
+
}
|
|
767
|
+
const initData = yield initResponse.json();
|
|
768
|
+
if (!isInitResponse(initData)) {
|
|
769
|
+
console.error(chalk3.red("\nUnexpected response format from init endpoint\n"));
|
|
770
|
+
process.exit(1);
|
|
771
|
+
}
|
|
772
|
+
return {
|
|
773
|
+
storefrontToken: initData.data.storefront_api_token,
|
|
774
|
+
envVars: initData.data.envVars
|
|
775
|
+
};
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
function setupProject(options) {
|
|
779
|
+
return __async(this, null, function* () {
|
|
780
|
+
let { projectName, projectDir } = options;
|
|
781
|
+
if (!pathExistsSync(projectDir)) {
|
|
782
|
+
console.error(chalk3.red(`Error: --projectDir ${projectDir} is not a valid path
|
|
783
|
+
`));
|
|
784
|
+
process.exit(1);
|
|
785
|
+
}
|
|
786
|
+
if (projectName) {
|
|
787
|
+
projectName = kebabCase(projectName);
|
|
788
|
+
projectDir = join3(options.projectDir, projectName);
|
|
789
|
+
if (pathExistsSync(projectDir)) {
|
|
790
|
+
console.error(chalk3.red(`Error: ${projectDir} already exists
|
|
791
|
+
`));
|
|
792
|
+
process.exit(1);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (!projectName) {
|
|
796
|
+
const validateProjectName = (i) => {
|
|
797
|
+
const formatted = kebabCase(i);
|
|
798
|
+
if (!formatted) return "Project name is required";
|
|
799
|
+
const targetDir = join3(options.projectDir, formatted);
|
|
800
|
+
if (pathExistsSync(targetDir)) return `Destination '${targetDir}' already exists`;
|
|
801
|
+
projectName = formatted;
|
|
802
|
+
projectDir = targetDir;
|
|
803
|
+
return true;
|
|
804
|
+
};
|
|
805
|
+
yield input({
|
|
806
|
+
message: "What is the name of your project?",
|
|
807
|
+
default: "my-catalyst-app",
|
|
808
|
+
validate: validateProjectName
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
if (!projectName) throw new Error("Something went wrong, projectName is not defined");
|
|
812
|
+
if (!projectDir) throw new Error("Something went wrong, projectDir is not defined");
|
|
813
|
+
return { projectName, projectDir };
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
function checkRequiredTools() {
|
|
760
817
|
try {
|
|
761
818
|
execSync5(getPlatformCheckCommand("git"), { stdio: "ignore" });
|
|
762
819
|
} catch (e) {
|
|
763
|
-
console.error(
|
|
820
|
+
console.error(chalk3.red("Error: git is required to create a Catalyst project\n"));
|
|
764
821
|
process.exit(1);
|
|
765
822
|
}
|
|
766
823
|
try {
|
|
767
824
|
execSync5(getPlatformCheckCommand("pnpm"), { stdio: "ignore" });
|
|
768
825
|
} catch (e) {
|
|
769
|
-
console.error(
|
|
770
|
-
console.error(
|
|
826
|
+
console.error(chalk3.red("Error: pnpm is required to create a Catalyst project\n"));
|
|
827
|
+
console.error(chalk3.yellow("Tip: Enable it by running `corepack enable pnpm`\n"));
|
|
771
828
|
process.exit(1);
|
|
772
829
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
830
|
+
}
|
|
831
|
+
var create = new Command("create").description("Command to scaffold and connect a Catalyst storefront to your BigCommerce store").option("--project-name <name>", "Name of your Catalyst project").option("--project-dir <dir>", "Directory in which to create your project", process.cwd()).option("--store-hash <hash>", "BigCommerce store hash").option("--access-token <token>", "BigCommerce access token").option("--channel-id <id>", "BigCommerce channel ID").option("--storefront-token <token>", "BigCommerce storefront token").option(
|
|
832
|
+
"--gh-ref <ref>",
|
|
833
|
+
"Clone a specific ref from the source repository",
|
|
834
|
+
"@bigcommerce/catalyst-core@latest"
|
|
835
|
+
).option("--reset-main", "Reset the main branch to the gh-ref").option("--repository <repository>", "GitHub repository to clone from", "bigcommerce/catalyst").option("--env <vars...>", "Arbitrary environment variables to set in .env.local").addOption(
|
|
836
|
+
new Option("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
837
|
+
).addOption(
|
|
838
|
+
new Option("--cli-api-origin <origin>", "Catalyst CLI API origin").default("https://cxm-prd.bigcommerceapp.com").hideHelp()
|
|
839
|
+
).action((options) => __async(void 0, null, function* () {
|
|
840
|
+
const { ghRef, repository } = options;
|
|
841
|
+
checkRequiredTools();
|
|
842
|
+
const { projectName, projectDir } = yield setupProject({
|
|
843
|
+
projectName: options.projectName,
|
|
844
|
+
projectDir: options.projectDir
|
|
845
|
+
});
|
|
780
846
|
let storeHash = options.storeHash;
|
|
781
847
|
let accessToken = options.accessToken;
|
|
782
848
|
let channelId;
|
|
783
849
|
let storefrontToken = options.storefrontToken;
|
|
850
|
+
let credentials;
|
|
784
851
|
if (options.channelId) {
|
|
785
852
|
channelId = parseInt(options.channelId, 10);
|
|
786
853
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
`)
|
|
790
|
-
process.exit(1);
|
|
791
|
-
}
|
|
792
|
-
if (options.projectName) {
|
|
793
|
-
projectName = kebabCase(options.projectName);
|
|
794
|
-
projectDir = join2(options.projectDir, projectName);
|
|
795
|
-
if (pathExistsSync(projectDir)) {
|
|
796
|
-
console.error(chalk4.red(`Error: ${projectDir} already exists
|
|
797
|
-
`));
|
|
798
|
-
process.exit(1);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
if (!options.projectName) {
|
|
802
|
-
const validateProjectName = (i) => {
|
|
803
|
-
const formatted = kebabCase(i);
|
|
804
|
-
if (!formatted) return "Project name is required";
|
|
805
|
-
const targetDir = join2(options.projectDir, formatted);
|
|
806
|
-
if (pathExistsSync(targetDir)) return `Destination '${targetDir}' already exists`;
|
|
807
|
-
projectName = formatted;
|
|
808
|
-
projectDir = targetDir;
|
|
809
|
-
return true;
|
|
810
|
-
};
|
|
811
|
-
yield input({
|
|
812
|
-
message: "What is the name of your project?",
|
|
813
|
-
default: "my-catalyst-app",
|
|
814
|
-
validate: validateProjectName
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
if (!projectName) throw new Error("Something went wrong, projectName is not defined");
|
|
818
|
-
if (!projectDir) throw new Error("Something went wrong, projectDir is not defined");
|
|
819
|
-
if (storeHash && channelId && storefrontToken) {
|
|
820
|
-
console.log(`
|
|
821
|
-
Creating '${projectName}' at '${projectDir}'
|
|
822
|
-
`);
|
|
823
|
-
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain });
|
|
824
|
-
writeEnv(projectDir, {
|
|
825
|
-
channelId: channelId.toString(),
|
|
826
|
-
storeHash,
|
|
827
|
-
storefrontToken,
|
|
828
|
-
arbitraryEnv: options.env
|
|
829
|
-
});
|
|
830
|
-
yield installDependencies(projectDir);
|
|
831
|
-
console.log(
|
|
832
|
-
`
|
|
833
|
-
${chalk4.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
834
|
-
`,
|
|
835
|
-
"\nNext steps:\n",
|
|
836
|
-
chalk4.yellow(`
|
|
837
|
-
cd ${projectName} && pnpm run dev
|
|
838
|
-
`)
|
|
839
|
-
);
|
|
840
|
-
process.exit(0);
|
|
841
|
-
}
|
|
842
|
-
if (!options.storeHash || !options.accessToken) {
|
|
843
|
-
const credentials = yield login(bigcommerceAuthUrl);
|
|
854
|
+
let envVars = {};
|
|
855
|
+
if ((!storeHash || !accessToken) && (!channelId || !storefrontToken)) {
|
|
856
|
+
credentials = yield login(`https://login.${options.bigcommerceHostname}`);
|
|
844
857
|
storeHash = credentials.storeHash;
|
|
845
858
|
accessToken = credentials.accessToken;
|
|
846
859
|
}
|
|
847
|
-
if (
|
|
848
|
-
|
|
860
|
+
if (storeHash && channelId && storefrontToken) {
|
|
861
|
+
envVars.BIGCOMMERCE_STORE_HASH = storeHash;
|
|
862
|
+
envVars.BIGCOMMERCE_CHANNEL_ID = channelId.toString();
|
|
863
|
+
envVars.BIGCOMMERCE_STOREFRONT_API_TOKEN = storefrontToken;
|
|
864
|
+
} else {
|
|
865
|
+
if (!storeHash || !accessToken) {
|
|
866
|
+
console.log(`
|
|
849
867
|
Creating '${projectName}' at '${projectDir}'
|
|
850
868
|
`);
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
869
|
+
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain: options.resetMain });
|
|
870
|
+
yield installDependencies(projectDir);
|
|
871
|
+
if (options.env) {
|
|
872
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
873
|
+
const [key, value] = env.split("=");
|
|
874
|
+
if (key && value) {
|
|
875
|
+
acc[key] = value;
|
|
876
|
+
}
|
|
877
|
+
return acc;
|
|
878
|
+
}, {});
|
|
879
|
+
Object.assign(envVars, cliEnvVars);
|
|
880
|
+
}
|
|
881
|
+
writeEnv(projectDir, envVars);
|
|
882
|
+
console.log(
|
|
883
|
+
[
|
|
884
|
+
`
|
|
885
|
+
${chalk3.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
857
886
|
`,
|
|
858
|
-
|
|
859
|
-
|
|
887
|
+
`Next steps:`,
|
|
888
|
+
Object.keys(envVars).length > 0 ? chalk3.yellow(`
|
|
889
|
+
- cd ${projectName} && pnpm run dev
|
|
890
|
+
`) : [
|
|
891
|
+
chalk3.yellow(`
|
|
860
892
|
- cd ${projectName} && cp .env.example .env.local`),
|
|
861
|
-
|
|
893
|
+
chalk3.yellow(`
|
|
862
894
|
- Populate .env.local with your BigCommerce API credentials
|
|
863
895
|
`)
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
yield telemetry.identify(storeHash);
|
|
869
|
-
if (!channelId || !storefrontToken) {
|
|
870
|
-
const bc = new Https({ bigCommerceApiUrl: bigcommerceApiUrl, storeHash, accessToken });
|
|
871
|
-
const sampleDataApi = new Https({
|
|
872
|
-
sampleDataApiUrl,
|
|
873
|
-
storeHash,
|
|
874
|
-
accessToken
|
|
875
|
-
});
|
|
876
|
-
const eligibilityResponse = yield sampleDataApi.checkEligibility();
|
|
877
|
-
if (!eligibilityResponse.data.eligible) {
|
|
878
|
-
console.warn(chalk4.yellow(eligibilityResponse.data.message));
|
|
879
|
-
}
|
|
880
|
-
let shouldCreateChannel;
|
|
881
|
-
if (eligibilityResponse.data.eligible) {
|
|
882
|
-
shouldCreateChannel = yield select2({
|
|
883
|
-
message: "Would you like to create a new channel?",
|
|
884
|
-
choices: [
|
|
885
|
-
{ name: "Yes", value: true },
|
|
886
|
-
{ name: "No", value: false }
|
|
887
|
-
]
|
|
888
|
-
});
|
|
896
|
+
].join("")
|
|
897
|
+
].join("\n")
|
|
898
|
+
);
|
|
899
|
+
process.exit(0);
|
|
889
900
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
901
|
+
yield telemetry.identify(storeHash);
|
|
902
|
+
if (!channelId || !storefrontToken) {
|
|
903
|
+
const bc = new Https({
|
|
904
|
+
baseUrl: `https://api.${options.bigcommerceHostname}/stores/${storeHash}`,
|
|
905
|
+
accessToken
|
|
893
906
|
});
|
|
894
|
-
const {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
channelId = createdChannelId;
|
|
899
|
-
storefrontToken = storefrontApiToken;
|
|
900
|
-
}
|
|
901
|
-
if (!shouldCreateChannel) {
|
|
902
|
-
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
903
|
-
const availableChannels = yield bc.channels("?available=true&type=storefront");
|
|
904
|
-
const existingChannel = yield select2({
|
|
905
|
-
message: "Which channel would you like to use?",
|
|
906
|
-
choices: availableChannels.data.sort(
|
|
907
|
-
(a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)
|
|
908
|
-
).map((ch) => ({
|
|
909
|
-
name: ch.name,
|
|
910
|
-
value: ch,
|
|
911
|
-
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
912
|
-
}))
|
|
907
|
+
const cliApi = new CliApi({
|
|
908
|
+
origin: options.cliApiOrigin,
|
|
909
|
+
storeHash,
|
|
910
|
+
accessToken
|
|
913
911
|
});
|
|
914
|
-
channelId
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
912
|
+
if (channelId && !storefrontToken) {
|
|
913
|
+
const initData = yield getChannelInit(cliApi, channelId);
|
|
914
|
+
envVars = __spreadValues({}, initData.envVars);
|
|
915
|
+
storefrontToken = initData.storefrontToken;
|
|
916
|
+
} else if (!channelId) {
|
|
917
|
+
const eligibilityResponse = yield cliApi.checkEligibility();
|
|
918
|
+
if (!eligibilityResponse.ok) {
|
|
919
|
+
console.error(
|
|
920
|
+
chalk3.red(
|
|
921
|
+
`
|
|
922
|
+
GET /channels/catalyst/eligibility failed: ${eligibilityResponse.status} ${eligibilityResponse.statusText}
|
|
923
|
+
`
|
|
924
|
+
)
|
|
925
|
+
);
|
|
926
|
+
process.exit(1);
|
|
927
|
+
}
|
|
928
|
+
const eligibilityData = yield eligibilityResponse.json();
|
|
929
|
+
if (!isEligibilityResponse(eligibilityData)) {
|
|
930
|
+
console.error(chalk3.red("\nUnexpected response format from eligibility endpoint\n"));
|
|
931
|
+
process.exit(1);
|
|
932
|
+
}
|
|
933
|
+
if (!eligibilityData.data.eligible) {
|
|
934
|
+
console.warn(chalk3.yellow(eligibilityData.data.message));
|
|
935
|
+
}
|
|
936
|
+
let shouldCreateChannel;
|
|
937
|
+
if (eligibilityData.data.eligible) {
|
|
938
|
+
shouldCreateChannel = yield select({
|
|
939
|
+
message: "Would you like to create a new channel?",
|
|
940
|
+
choices: [
|
|
941
|
+
{ name: "Yes", value: true },
|
|
942
|
+
{ name: "No", value: false }
|
|
943
|
+
]
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
if (shouldCreateChannel) {
|
|
947
|
+
const channelData = yield handleChannelCreation(cliApi);
|
|
948
|
+
channelId = channelData.channelId;
|
|
949
|
+
storefrontToken = channelData.storefrontToken;
|
|
950
|
+
envVars = __spreadValues({}, channelData.envVars);
|
|
951
|
+
console.log(chalk3.green(`Channel created successfully`));
|
|
952
|
+
console.warn(
|
|
953
|
+
chalk3.yellow(
|
|
954
|
+
"\nNote: A preview storefront has been deployed in your BigCommerce control panel. This preview may look different from your local environment as it may be running different code."
|
|
955
|
+
)
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
if (!shouldCreateChannel) {
|
|
959
|
+
channelId = yield handleChannelSelection(bc);
|
|
960
|
+
const initData = yield getChannelInit(cliApi, channelId);
|
|
961
|
+
envVars = __spreadValues({}, initData.envVars);
|
|
962
|
+
storefrontToken = initData.storefrontToken;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
919
965
|
}
|
|
920
966
|
}
|
|
967
|
+
if (options.env) {
|
|
968
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
969
|
+
const [key, value] = env.split("=");
|
|
970
|
+
if (key && value) {
|
|
971
|
+
acc[key] = value;
|
|
972
|
+
}
|
|
973
|
+
return acc;
|
|
974
|
+
}, {});
|
|
975
|
+
Object.assign(envVars, cliEnvVars);
|
|
976
|
+
}
|
|
977
|
+
if (options.storeHash) {
|
|
978
|
+
envVars.BIGCOMMERCE_STORE_HASH = options.storeHash;
|
|
979
|
+
}
|
|
980
|
+
if (options.channelId) {
|
|
981
|
+
envVars.BIGCOMMERCE_CHANNEL_ID = options.channelId;
|
|
982
|
+
}
|
|
983
|
+
if (options.storefrontToken) {
|
|
984
|
+
envVars.BIGCOMMERCE_STOREFRONT_TOKEN = options.storefrontToken;
|
|
985
|
+
}
|
|
921
986
|
if (!channelId) throw new Error("Something went wrong, channelId is not defined");
|
|
922
987
|
if (!storefrontToken) throw new Error("Something went wrong, storefrontToken is not defined");
|
|
923
988
|
console.log(`
|
|
924
989
|
Creating '${projectName}' at '${projectDir}'
|
|
925
990
|
`);
|
|
926
|
-
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain });
|
|
927
|
-
writeEnv(projectDir, {
|
|
928
|
-
channelId: channelId.toString(),
|
|
929
|
-
storeHash,
|
|
930
|
-
storefrontToken,
|
|
931
|
-
arbitraryEnv: options.env
|
|
932
|
-
});
|
|
991
|
+
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain: options.resetMain });
|
|
933
992
|
yield installDependencies(projectDir);
|
|
993
|
+
writeEnv(projectDir, envVars);
|
|
994
|
+
if (credentials) {
|
|
995
|
+
storeCredentials(projectDir, credentials);
|
|
996
|
+
}
|
|
934
997
|
console.log(
|
|
935
998
|
`
|
|
936
|
-
${
|
|
999
|
+
${chalk3.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
937
1000
|
`,
|
|
938
1001
|
"\nNext steps:\n",
|
|
939
|
-
|
|
1002
|
+
chalk3.yellow(`
|
|
940
1003
|
cd ${projectName} && pnpm run dev
|
|
941
1004
|
`)
|
|
942
1005
|
);
|
|
943
1006
|
}));
|
|
1007
|
+
function isInitResponse(response) {
|
|
1008
|
+
return typeof response === "object" && response !== null && "data" in response && typeof response.data === "object" && response.data !== null && "storefront_api_token" in response.data && "envVars" in response.data;
|
|
1009
|
+
}
|
|
1010
|
+
function isEligibilityResponse(response) {
|
|
1011
|
+
return typeof response === "object" && response !== null && "data" in response && typeof response.data === "object" && response.data !== null && "eligible" in response.data && "message" in response.data;
|
|
1012
|
+
}
|
|
1013
|
+
function isCreateChannelResponse(response) {
|
|
1014
|
+
return typeof response === "object" && response !== null && "data" in response && typeof response.data === "object" && response.data !== null && "id" in response.data && "storefront_api_token" in response.data && "envVars" in response.data;
|
|
1015
|
+
}
|
|
1016
|
+
function isChannelsResponse(response) {
|
|
1017
|
+
return typeof response === "object" && response !== null && "data" in response && Array.isArray(response.data) && response.data.every(
|
|
1018
|
+
(item) => typeof item === "object" && item !== null && "id" in item && "name" in item && "platform" in item
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
944
1021
|
|
|
945
1022
|
// src/commands/init.ts
|
|
946
1023
|
import { Command as Command2, Option as Option2 } from "@commander-js/extra-typings";
|
|
947
|
-
import {
|
|
948
|
-
import
|
|
949
|
-
|
|
1024
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
1025
|
+
import chalk4 from "chalk";
|
|
1026
|
+
function isChannelsResponse2(response) {
|
|
1027
|
+
return typeof response === "object" && response !== null && "data" in response && Array.isArray(response.data) && response.data.every(
|
|
1028
|
+
(item) => typeof item === "object" && item !== null && "id" in item && "name" in item && "platform" in item
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
function isInitResponse2(response) {
|
|
1032
|
+
return typeof response === "object" && response !== null && "data" in response && typeof response.data === "object" && response.data !== null && "storefront_api_token" in response.data && "envVars" in response.data;
|
|
1033
|
+
}
|
|
950
1034
|
var telemetry2 = new Telemetry();
|
|
951
|
-
var init = new Command2("init").description("Connect a BigCommerce store with an existing Catalyst project").option("--store-hash <hash>", "BigCommerce store hash").option("--access-token <token>", "BigCommerce access token").addOption(
|
|
1035
|
+
var init = new Command2("init").description("Connect a BigCommerce store with an existing Catalyst project").option("--store-hash <hash>", "BigCommerce store hash").option("--access-token <token>", "BigCommerce access token").option("--env <vars...>", "Arbitrary environment variables to set in .env.local").addOption(
|
|
952
1036
|
new Option2("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
953
1037
|
).addOption(
|
|
954
|
-
new Option2("--
|
|
1038
|
+
new Option2("--cli-api-origin <origin>", "Catalyst CLI API origin").default("https://cxm-prd.bigcommerceapp.com").hideHelp()
|
|
955
1039
|
).action((options) => __async(void 0, null, function* () {
|
|
956
1040
|
const projectDir = process.cwd();
|
|
957
|
-
const URLSchema = z4.string().url();
|
|
958
|
-
const sampleDataApiUrl = parse(options.sampleDataApiUrl, URLSchema);
|
|
959
|
-
const bigCommerceApiUrl = `https://api.${options.bigcommerceHostname}`;
|
|
960
|
-
const bigCommerceAuthUrl = `https://login.${options.bigcommerceHostname}`;
|
|
961
1041
|
let storeHash = options.storeHash;
|
|
962
1042
|
let accessToken = options.accessToken;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
accessToken = credentials.accessToken;
|
|
1043
|
+
if (!storeHash || !accessToken) {
|
|
1044
|
+
const config = new Config(projectDir);
|
|
1045
|
+
const storedAuth = config.getAuth();
|
|
1046
|
+
storeHash = storeHash != null ? storeHash : storedAuth.storeHash;
|
|
1047
|
+
accessToken = accessToken != null ? accessToken : storedAuth.accessToken;
|
|
969
1048
|
}
|
|
970
1049
|
if (!storeHash || !accessToken) {
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1050
|
+
const credentials = yield login(`https://login.${options.bigcommerceHostname}`);
|
|
1051
|
+
storeHash = credentials.storeHash;
|
|
1052
|
+
accessToken = credentials.accessToken;
|
|
1053
|
+
storeCredentials(projectDir, credentials);
|
|
975
1054
|
}
|
|
976
1055
|
yield telemetry2.identify(storeHash);
|
|
977
|
-
const bc = new Https({
|
|
978
|
-
|
|
979
|
-
|
|
1056
|
+
const bc = new Https({
|
|
1057
|
+
baseUrl: `https://api.${options.bigcommerceHostname}/stores/${storeHash}`,
|
|
1058
|
+
accessToken
|
|
1059
|
+
});
|
|
1060
|
+
const cliApi = new CliApi({
|
|
1061
|
+
origin: options.cliApiOrigin,
|
|
980
1062
|
storeHash,
|
|
981
1063
|
accessToken
|
|
982
1064
|
});
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
|
|
1065
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
1066
|
+
const channelsResponse = yield bc.fetch("/v3/channels?available=true&type=storefront");
|
|
1067
|
+
if (!channelsResponse.ok) {
|
|
1068
|
+
console.error(
|
|
1069
|
+
chalk4.red(
|
|
1070
|
+
`
|
|
1071
|
+
GET /v3/channels failed: ${channelsResponse.status} ${channelsResponse.statusText}
|
|
1072
|
+
`
|
|
1073
|
+
)
|
|
1074
|
+
);
|
|
1075
|
+
process.exit(1);
|
|
986
1076
|
}
|
|
987
|
-
|
|
988
|
-
if (
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
choices: [
|
|
992
|
-
{ name: "Yes", value: true },
|
|
993
|
-
{ name: "No", value: false }
|
|
994
|
-
]
|
|
995
|
-
});
|
|
1077
|
+
const availableChannels = yield channelsResponse.json();
|
|
1078
|
+
if (!isChannelsResponse2(availableChannels)) {
|
|
1079
|
+
console.error(chalk4.red("\nUnexpected response format from channels endpoint\n"));
|
|
1080
|
+
process.exit(1);
|
|
996
1081
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1082
|
+
const existingChannel = yield select2({
|
|
1083
|
+
message: "Which channel would you like to use?",
|
|
1084
|
+
choices: availableChannels.data.sort(
|
|
1085
|
+
(a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)
|
|
1086
|
+
).map((ch) => ({
|
|
1087
|
+
name: ch.name,
|
|
1088
|
+
value: ch,
|
|
1089
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
1090
|
+
}))
|
|
1091
|
+
});
|
|
1092
|
+
const channelId = existingChannel.id;
|
|
1093
|
+
const initResponse = yield cliApi.getChannelInit(channelId);
|
|
1094
|
+
if (!initResponse.ok) {
|
|
1095
|
+
console.error(
|
|
1096
|
+
chalk4.red(
|
|
1097
|
+
`
|
|
1098
|
+
GET /channels/${channelId}/init failed: ${initResponse.status} ${initResponse.statusText}
|
|
1099
|
+
`
|
|
1100
|
+
)
|
|
1101
|
+
);
|
|
1102
|
+
process.exit(1);
|
|
1006
1103
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
message: "Which channel would you like to use?",
|
|
1012
|
-
choices: availableChannels.data.sort(
|
|
1013
|
-
(a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)
|
|
1014
|
-
).map((ch) => ({
|
|
1015
|
-
name: ch.name,
|
|
1016
|
-
value: ch,
|
|
1017
|
-
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
1018
|
-
}))
|
|
1019
|
-
});
|
|
1020
|
-
channelId = existingChannel.id;
|
|
1021
|
-
const {
|
|
1022
|
-
data: { token: sfToken }
|
|
1023
|
-
} = yield bc.storefrontToken();
|
|
1024
|
-
storefrontToken = sfToken;
|
|
1104
|
+
const initData = yield initResponse.json();
|
|
1105
|
+
if (!isInitResponse2(initData)) {
|
|
1106
|
+
console.error(chalk4.red("\nUnexpected response format from init endpoint\n"));
|
|
1107
|
+
process.exit(1);
|
|
1025
1108
|
}
|
|
1026
|
-
|
|
1027
|
-
if (
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1109
|
+
const envVars = __spreadValues({}, initData.data.envVars);
|
|
1110
|
+
if (options.env) {
|
|
1111
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
1112
|
+
const [key, value] = env.split("=");
|
|
1113
|
+
if (key && value) {
|
|
1114
|
+
acc[key] = value;
|
|
1115
|
+
}
|
|
1116
|
+
return acc;
|
|
1117
|
+
}, {});
|
|
1118
|
+
Object.assign(envVars, cliEnvVars);
|
|
1119
|
+
}
|
|
1120
|
+
writeEnv(projectDir, envVars);
|
|
1121
|
+
console.log(chalk4.green(`
|
|
1122
|
+
.env.local file created for channel ${existingChannel.name}!
|
|
1123
|
+
`));
|
|
1124
|
+
console.log(chalk4.green(`
|
|
1125
|
+
Next steps:
|
|
1126
|
+
`));
|
|
1127
|
+
console.log(chalk4.yellow(`
|
|
1128
|
+
pnpm run dev
|
|
1129
|
+
`));
|
|
1033
1130
|
}));
|
|
1034
1131
|
|
|
1035
1132
|
// src/commands/integration.ts
|
|
@@ -1040,16 +1137,16 @@ import { outputFileSync as outputFileSync2, writeJsonSync } from "fs-extra/esm";
|
|
|
1040
1137
|
import kebabCase2 from "lodash.kebabcase";
|
|
1041
1138
|
import { coerce, compare } from "semver";
|
|
1042
1139
|
import { promisify } from "util";
|
|
1043
|
-
import { z as
|
|
1140
|
+
import { z as z3 } from "zod";
|
|
1044
1141
|
var exec = promisify(execCb);
|
|
1045
|
-
var ManifestSchema =
|
|
1046
|
-
name:
|
|
1047
|
-
dependencies:
|
|
1048
|
-
devDependencies:
|
|
1049
|
-
environmentVariables:
|
|
1142
|
+
var ManifestSchema = z3.object({
|
|
1143
|
+
name: z3.string(),
|
|
1144
|
+
dependencies: z3.object({ add: z3.array(z3.string()) }),
|
|
1145
|
+
devDependencies: z3.object({ add: z3.array(z3.string()) }),
|
|
1146
|
+
environmentVariables: z3.array(z3.string())
|
|
1050
1147
|
});
|
|
1051
1148
|
var integration = new Command3("integration").argument("<integration-name>", "Formatted name of the integration").option("--commit-hash <hash>", "Override integration source branch with a specific commit hash").action((integrationNameRaw, options) => __async(void 0, null, function* () {
|
|
1052
|
-
const integrationName =
|
|
1149
|
+
const integrationName = z3.string().transform(kebabCase2).parse(integrationNameRaw);
|
|
1053
1150
|
const manifest = {
|
|
1054
1151
|
name: integrationName,
|
|
1055
1152
|
dependencies: { add: [] },
|
|
@@ -1071,9 +1168,9 @@ var integration = new Command3("integration").argument("<integration-name>", "Fo
|
|
|
1071
1168
|
}
|
|
1072
1169
|
return 0;
|
|
1073
1170
|
}).reverse();
|
|
1074
|
-
const PackageDependenciesSchema =
|
|
1075
|
-
dependencies:
|
|
1076
|
-
devDependencies:
|
|
1171
|
+
const PackageDependenciesSchema = z3.object({
|
|
1172
|
+
dependencies: z3.object({}).passthrough(),
|
|
1173
|
+
devDependencies: z3.object({}).passthrough()
|
|
1077
1174
|
});
|
|
1078
1175
|
const getPackageDeps = (ref) => __async(void 0, null, function* () {
|
|
1079
1176
|
const { stdout } = yield exec(`git show ${ref}:core/package.json`);
|
|
@@ -1109,7 +1206,7 @@ var integration = new Command3("integration").argument("<integration-name>", "Fo
|
|
|
1109
1206
|
import { Argument, Command as Command4, Option as Option3 } from "@commander-js/extra-typings";
|
|
1110
1207
|
|
|
1111
1208
|
// src/utils/telemetry/index.ts
|
|
1112
|
-
import
|
|
1209
|
+
import chalk5 from "chalk";
|
|
1113
1210
|
var telemetry3 = new Telemetry();
|
|
1114
1211
|
var isEnabled = telemetry3.isEnabled();
|
|
1115
1212
|
var catalystTelemetry = (options, arg) => {
|
|
@@ -1130,7 +1227,7 @@ var catalystTelemetry = (options, arg) => {
|
|
|
1130
1227
|
}
|
|
1131
1228
|
console.log(
|
|
1132
1229
|
`
|
|
1133
|
-
Status: ${
|
|
1230
|
+
Status: ${chalk5.bold(isEnabled ? chalk5.green("Enabled") : chalk5.red("Disabled"))}`
|
|
1134
1231
|
);
|
|
1135
1232
|
if (!isEnabled) {
|
|
1136
1233
|
console.log(
|
|
@@ -1183,7 +1280,7 @@ var telemetryPostHook = () => __async(void 0, null, function* () {
|
|
|
1183
1280
|
});
|
|
1184
1281
|
|
|
1185
1282
|
// src/index.ts
|
|
1186
|
-
console.log(
|
|
1283
|
+
console.log(chalk6.cyanBright(`
|
|
1187
1284
|
\u25E2 ${package_default.name} v${package_default.version}
|
|
1188
1285
|
`));
|
|
1189
1286
|
program.name(package_default.name).version(package_default.version).description("A command line tool to create a new Catalyst project.").addCommand(create, { isDefault: true }).addCommand(init).addCommand(integration).addCommand(telemetry4).hook("preAction", telemetryPreHook).hook("postAction", telemetryPostHook);
|