@bigcommerce/create-catalyst 0.18.0 → 0.19.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 +683 -589
- 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.19.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";
|
|
@@ -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,155 @@ 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
|
-
|
|
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;
|
|
448
|
+
}
|
|
449
|
+
if ("auth" in obj) {
|
|
450
|
+
if (!isRecord(obj.auth)) {
|
|
451
|
+
return false;
|
|
404
452
|
}
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
headers: __spreadProps(__spreadValues({}, headers), {
|
|
408
|
-
Accept: "application/json",
|
|
409
|
-
"X-Auth-Token": this.accessToken,
|
|
410
|
-
"User-Agent": this.userAgent
|
|
411
|
-
})
|
|
412
|
-
}, rest);
|
|
413
|
-
return fetch(`${this.bigCommerceApiUrl}/stores/${this.storeHash}${path}`, options);
|
|
453
|
+
const { storeHash, accessToken } = obj.auth;
|
|
454
|
+
return (storeHash === void 0 || typeof storeHash === "string") && (accessToken === void 0 || typeof accessToken === "string");
|
|
414
455
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
`));
|
|
422
|
-
process.exit(1);
|
|
423
|
-
}
|
|
424
|
-
return parse(yield res.json(), BigCommerceStoreInfo);
|
|
425
|
-
});
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
var Config = class {
|
|
459
|
+
constructor(projectDir) {
|
|
460
|
+
this.configPath = join(projectDir, ".catalyst");
|
|
461
|
+
this.config = this.read();
|
|
426
462
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (!res.ok) {
|
|
431
|
-
console.error(chalk.red(`
|
|
432
|
-
GET /v3/channels failed: ${res.status} ${res.statusText}
|
|
433
|
-
`));
|
|
434
|
-
process.exit(1);
|
|
435
|
-
}
|
|
436
|
-
return parse(yield res.json(), BigCommerceChannelsV3ResponseSchema);
|
|
437
|
-
});
|
|
463
|
+
getAuth() {
|
|
464
|
+
var _a;
|
|
465
|
+
return (_a = this.config.auth) != null ? _a : {};
|
|
438
466
|
}
|
|
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
|
-
});
|
|
467
|
+
setAuth(storeHash, accessToken) {
|
|
468
|
+
this.config.auth = { storeHash, accessToken };
|
|
469
|
+
this.save();
|
|
464
470
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
});
|
|
487
|
-
}
|
|
488
|
-
sampleDataApi(path, opts = {}) {
|
|
489
|
-
if (!this.sampleDataApiUrl || !this.storeHash || !this.accessToken) {
|
|
490
|
-
throw new Error(
|
|
491
|
-
"sampleDataApiUrl, storeHash, and accessToken are required to make API requests"
|
|
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] !== 27;
|
|
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.cyan("\nPlease visit the following URL to authenticate with your BigCommerce store:")
|
|
559
|
+
);
|
|
560
|
+
console.log(chalk2.yellow(`
|
|
561
|
+
${deviceCode.verification_uri}
|
|
562
|
+
`));
|
|
563
|
+
console.log(chalk2.cyan(`Enter code: `) + chalk2.yellow(`${deviceCode.user_code}
|
|
564
|
+
`));
|
|
565
|
+
const shouldOpenUrl = yield waitForKeyPress(
|
|
566
|
+
"Press any key to open the URL in your browser (or ESC to skip)..."
|
|
567
|
+
);
|
|
568
|
+
if (shouldOpenUrl) {
|
|
569
|
+
yield open(deviceCode.verification_uri);
|
|
570
|
+
}
|
|
571
|
+
const credentials = yield spinner(
|
|
572
|
+
() => waitForCredentials(auth, deviceCode.device_code, deviceCode.interval),
|
|
573
|
+
{ text: "Waiting for authentication...", successText: "Authentication successful!" }
|
|
574
|
+
);
|
|
575
|
+
return {
|
|
576
|
+
storeHash: credentials.store_hash,
|
|
577
|
+
accessToken: credentials.access_token
|
|
578
|
+
};
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
function storeCredentials(projectDir, credentials) {
|
|
582
|
+
const config = new Config(projectDir);
|
|
583
|
+
config.setAuth(credentials.storeHash, credentials.accessToken);
|
|
584
|
+
}
|
|
636
585
|
|
|
637
586
|
// src/utils/telemetry/telemetry.ts
|
|
638
587
|
import { Analytics } from "@segment/analytics-node";
|
|
@@ -720,28 +669,13 @@ var Telemetry = class {
|
|
|
720
669
|
};
|
|
721
670
|
|
|
722
671
|
// src/utils/write-env.ts
|
|
723
|
-
import { randomBytes as randomBytes2 } from "crypto";
|
|
724
672
|
import { outputFileSync } from "fs-extra/esm";
|
|
725
|
-
import { join } from "path";
|
|
726
|
-
var writeEnv = (projectDir, {
|
|
727
|
-
channelId,
|
|
728
|
-
storeHash,
|
|
729
|
-
storefrontToken,
|
|
730
|
-
arbitraryEnv
|
|
731
|
-
}) => {
|
|
673
|
+
import { join as join2 } from "path";
|
|
674
|
+
var writeEnv = (projectDir, envVars) => {
|
|
732
675
|
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")
|
|
676
|
+
join2(projectDir, ".env.local"),
|
|
677
|
+
`${Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n")}
|
|
678
|
+
`
|
|
745
679
|
);
|
|
746
680
|
};
|
|
747
681
|
|
|
@@ -751,285 +685,445 @@ function getPlatformCheckCommand(command) {
|
|
|
751
685
|
return isWindows2 ? `where.exe ${command}` : `which ${command}`;
|
|
752
686
|
}
|
|
753
687
|
var telemetry = new Telemetry();
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
)
|
|
759
|
-
|
|
688
|
+
function handleChannelCreation(cliApi) {
|
|
689
|
+
return __async(this, null, function* () {
|
|
690
|
+
const newChannelName = yield input({
|
|
691
|
+
message: "What would you like to name your new channel?"
|
|
692
|
+
});
|
|
693
|
+
const shouldInstallSampleData = yield select({
|
|
694
|
+
message: "Would you like to install sample data?",
|
|
695
|
+
choices: [
|
|
696
|
+
{ name: "Yes", value: true },
|
|
697
|
+
{ name: "No", value: false }
|
|
698
|
+
]
|
|
699
|
+
});
|
|
700
|
+
const response = yield cliApi.createChannel(newChannelName, shouldInstallSampleData);
|
|
701
|
+
if (!response.ok) {
|
|
702
|
+
console.error(
|
|
703
|
+
chalk3.red(`
|
|
704
|
+
POST /channels/catalyst failed: ${response.status} ${response.statusText}
|
|
705
|
+
`)
|
|
706
|
+
);
|
|
707
|
+
process.exit(1);
|
|
708
|
+
}
|
|
709
|
+
const channelData = yield response.json();
|
|
710
|
+
if (!isCreateChannelResponse(channelData)) {
|
|
711
|
+
console.error(chalk3.red("\nUnexpected response format from create channel endpoint\n"));
|
|
712
|
+
process.exit(1);
|
|
713
|
+
}
|
|
714
|
+
return {
|
|
715
|
+
channelId: channelData.data.id,
|
|
716
|
+
storefrontToken: channelData.data.storefront_api_token,
|
|
717
|
+
envVars: channelData.data.envVars
|
|
718
|
+
};
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
function handleChannelSelection(bc) {
|
|
722
|
+
return __async(this, null, function* () {
|
|
723
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
724
|
+
const channelsResponse = yield bc.fetch("/v3/channels?available=true&type=storefront");
|
|
725
|
+
if (!channelsResponse.ok) {
|
|
726
|
+
console.error(
|
|
727
|
+
chalk3.red(
|
|
728
|
+
`
|
|
729
|
+
GET /v3/channels failed: ${channelsResponse.status} ${channelsResponse.statusText}
|
|
730
|
+
`
|
|
731
|
+
)
|
|
732
|
+
);
|
|
733
|
+
process.exit(1);
|
|
734
|
+
}
|
|
735
|
+
const availableChannels = yield channelsResponse.json();
|
|
736
|
+
if (!isChannelsResponse(availableChannels)) {
|
|
737
|
+
console.error(chalk3.red("\nUnexpected response format from channels endpoint\n"));
|
|
738
|
+
process.exit(1);
|
|
739
|
+
}
|
|
740
|
+
const existingChannel = yield select({
|
|
741
|
+
message: "Which channel would you like to use?",
|
|
742
|
+
choices: availableChannels.data.sort((a, b) => {
|
|
743
|
+
const aIndex = channelSortOrder.indexOf(a.platform);
|
|
744
|
+
const bIndex = channelSortOrder.indexOf(b.platform);
|
|
745
|
+
if (aIndex === -1 && bIndex === -1) {
|
|
746
|
+
return 0;
|
|
747
|
+
}
|
|
748
|
+
if (aIndex === -1) return 1;
|
|
749
|
+
if (bIndex === -1) return -1;
|
|
750
|
+
return aIndex - bIndex;
|
|
751
|
+
}).map((ch) => ({
|
|
752
|
+
name: ch.name,
|
|
753
|
+
value: ch,
|
|
754
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
755
|
+
}))
|
|
756
|
+
});
|
|
757
|
+
return existingChannel.id;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
function getChannelInit(cliApi, channelId) {
|
|
761
|
+
return __async(this, null, function* () {
|
|
762
|
+
const initResponse = yield cliApi.getChannelInit(channelId);
|
|
763
|
+
if (!initResponse.ok) {
|
|
764
|
+
console.error(
|
|
765
|
+
chalk3.red(
|
|
766
|
+
`
|
|
767
|
+
GET /channels/${channelId}/init failed: ${initResponse.status} ${initResponse.statusText}
|
|
768
|
+
`
|
|
769
|
+
)
|
|
770
|
+
);
|
|
771
|
+
process.exit(1);
|
|
772
|
+
}
|
|
773
|
+
const initData = yield initResponse.json();
|
|
774
|
+
if (!isInitResponse(initData)) {
|
|
775
|
+
console.error(chalk3.red("\nUnexpected response format from init endpoint\n"));
|
|
776
|
+
process.exit(1);
|
|
777
|
+
}
|
|
778
|
+
return {
|
|
779
|
+
storefrontToken: initData.data.storefront_api_token,
|
|
780
|
+
envVars: initData.data.envVars
|
|
781
|
+
};
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
function setupProject(options) {
|
|
785
|
+
return __async(this, null, function* () {
|
|
786
|
+
let { projectName, projectDir } = options;
|
|
787
|
+
if (!pathExistsSync(projectDir)) {
|
|
788
|
+
console.error(chalk3.red(`Error: --projectDir ${projectDir} is not a valid path
|
|
789
|
+
`));
|
|
790
|
+
process.exit(1);
|
|
791
|
+
}
|
|
792
|
+
if (projectName) {
|
|
793
|
+
projectName = kebabCase(projectName);
|
|
794
|
+
projectDir = join3(options.projectDir, projectName);
|
|
795
|
+
if (pathExistsSync(projectDir)) {
|
|
796
|
+
console.error(chalk3.red(`Error: ${projectDir} already exists
|
|
797
|
+
`));
|
|
798
|
+
process.exit(1);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
if (!projectName) {
|
|
802
|
+
const validateProjectName = (i) => {
|
|
803
|
+
const formatted = kebabCase(i);
|
|
804
|
+
if (!formatted) return "Project name is required";
|
|
805
|
+
const targetDir = join3(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
|
+
return { projectName, projectDir };
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
function checkRequiredTools() {
|
|
760
823
|
try {
|
|
761
824
|
execSync5(getPlatformCheckCommand("git"), { stdio: "ignore" });
|
|
762
825
|
} catch (e) {
|
|
763
|
-
console.error(
|
|
826
|
+
console.error(chalk3.red("Error: git is required to create a Catalyst project\n"));
|
|
764
827
|
process.exit(1);
|
|
765
828
|
}
|
|
766
829
|
try {
|
|
767
830
|
execSync5(getPlatformCheckCommand("pnpm"), { stdio: "ignore" });
|
|
768
831
|
} catch (e) {
|
|
769
|
-
console.error(
|
|
770
|
-
console.error(
|
|
832
|
+
console.error(chalk3.red("Error: pnpm is required to create a Catalyst project\n"));
|
|
833
|
+
console.error(chalk3.yellow("Tip: Enable it by running `corepack enable pnpm`\n"));
|
|
771
834
|
process.exit(1);
|
|
772
835
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
836
|
+
}
|
|
837
|
+
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("--gh-ref <ref>", "Clone a specific ref from the source repository").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(
|
|
838
|
+
new Option("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
839
|
+
).addOption(
|
|
840
|
+
new Option("--cli-api-origin <origin>", "Catalyst CLI API origin").default("https://cxm-prd.bigcommerceapp.com").hideHelp()
|
|
841
|
+
).action((options) => __async(void 0, null, function* () {
|
|
842
|
+
const { ghRef, repository } = options;
|
|
843
|
+
checkRequiredTools();
|
|
844
|
+
const { projectName, projectDir } = yield setupProject({
|
|
845
|
+
projectName: options.projectName,
|
|
846
|
+
projectDir: options.projectDir
|
|
847
|
+
});
|
|
780
848
|
let storeHash = options.storeHash;
|
|
781
849
|
let accessToken = options.accessToken;
|
|
782
850
|
let channelId;
|
|
783
851
|
let storefrontToken = options.storefrontToken;
|
|
852
|
+
let credentials;
|
|
784
853
|
if (options.channelId) {
|
|
785
854
|
channelId = parseInt(options.channelId, 10);
|
|
786
855
|
}
|
|
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);
|
|
856
|
+
let envVars = {};
|
|
857
|
+
if ((!storeHash || !accessToken) && (!channelId || !storefrontToken)) {
|
|
858
|
+
credentials = yield login(`https://login.${options.bigcommerceHostname}`);
|
|
844
859
|
storeHash = credentials.storeHash;
|
|
845
860
|
accessToken = credentials.accessToken;
|
|
846
861
|
}
|
|
847
|
-
if (
|
|
848
|
-
|
|
862
|
+
if (storeHash && channelId && storefrontToken) {
|
|
863
|
+
envVars.BIGCOMMERCE_STORE_HASH = storeHash;
|
|
864
|
+
envVars.BIGCOMMERCE_CHANNEL_ID = channelId.toString();
|
|
865
|
+
envVars.BIGCOMMERCE_STOREFRONT_API_TOKEN = storefrontToken;
|
|
866
|
+
} else {
|
|
867
|
+
if (!storeHash || !accessToken) {
|
|
868
|
+
console.log(`
|
|
849
869
|
Creating '${projectName}' at '${projectDir}'
|
|
850
870
|
`);
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
871
|
+
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain: options.resetMain });
|
|
872
|
+
yield installDependencies(projectDir);
|
|
873
|
+
if (options.env) {
|
|
874
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
875
|
+
const [key, value] = env.split("=");
|
|
876
|
+
if (key && value) {
|
|
877
|
+
acc[key] = value;
|
|
878
|
+
}
|
|
879
|
+
return acc;
|
|
880
|
+
}, {});
|
|
881
|
+
Object.assign(envVars, cliEnvVars);
|
|
882
|
+
}
|
|
883
|
+
writeEnv(projectDir, envVars);
|
|
884
|
+
console.log(
|
|
885
|
+
[
|
|
886
|
+
`
|
|
887
|
+
${chalk3.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
857
888
|
`,
|
|
858
|
-
|
|
859
|
-
|
|
889
|
+
`Next steps:`,
|
|
890
|
+
Object.keys(envVars).length > 0 ? chalk3.yellow(`
|
|
891
|
+
- cd ${projectName} && pnpm run dev
|
|
892
|
+
`) : [
|
|
893
|
+
chalk3.yellow(`
|
|
860
894
|
- cd ${projectName} && cp .env.example .env.local`),
|
|
861
|
-
|
|
895
|
+
chalk3.yellow(`
|
|
862
896
|
- Populate .env.local with your BigCommerce API credentials
|
|
863
897
|
`)
|
|
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));
|
|
898
|
+
].join("")
|
|
899
|
+
].join("\n")
|
|
900
|
+
);
|
|
901
|
+
process.exit(0);
|
|
879
902
|
}
|
|
880
|
-
|
|
881
|
-
if (
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
{ name: "Yes", value: true },
|
|
886
|
-
{ name: "No", value: false }
|
|
887
|
-
]
|
|
903
|
+
yield telemetry.identify(storeHash);
|
|
904
|
+
if (!channelId || !storefrontToken) {
|
|
905
|
+
const bc = new Https({
|
|
906
|
+
baseUrl: `https://api.${options.bigcommerceHostname}/stores/${storeHash}`,
|
|
907
|
+
accessToken
|
|
888
908
|
});
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
909
|
+
const cliApi = new CliApi({
|
|
910
|
+
origin: options.cliApiOrigin,
|
|
911
|
+
storeHash,
|
|
912
|
+
accessToken
|
|
893
913
|
});
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
channelId
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
914
|
+
if (channelId && !storefrontToken) {
|
|
915
|
+
const initData = yield getChannelInit(cliApi, channelId);
|
|
916
|
+
envVars = __spreadValues({}, initData.envVars);
|
|
917
|
+
storefrontToken = initData.storefrontToken;
|
|
918
|
+
} else if (!channelId) {
|
|
919
|
+
const eligibilityResponse = yield cliApi.checkEligibility();
|
|
920
|
+
if (!eligibilityResponse.ok) {
|
|
921
|
+
console.error(
|
|
922
|
+
chalk3.red(
|
|
923
|
+
`
|
|
924
|
+
GET /channels/catalyst/eligibility failed: ${eligibilityResponse.status} ${eligibilityResponse.statusText}
|
|
925
|
+
`
|
|
926
|
+
)
|
|
927
|
+
);
|
|
928
|
+
process.exit(1);
|
|
929
|
+
}
|
|
930
|
+
const eligibilityData = yield eligibilityResponse.json();
|
|
931
|
+
if (!isEligibilityResponse(eligibilityData)) {
|
|
932
|
+
console.error(chalk3.red("\nUnexpected response format from eligibility endpoint\n"));
|
|
933
|
+
process.exit(1);
|
|
934
|
+
}
|
|
935
|
+
if (!eligibilityData.data.eligible) {
|
|
936
|
+
console.warn(chalk3.yellow(eligibilityData.data.message));
|
|
937
|
+
}
|
|
938
|
+
let shouldCreateChannel;
|
|
939
|
+
if (eligibilityData.data.eligible) {
|
|
940
|
+
shouldCreateChannel = yield select({
|
|
941
|
+
message: "Would you like to create a new channel?",
|
|
942
|
+
choices: [
|
|
943
|
+
{ name: "Yes", value: true },
|
|
944
|
+
{ name: "No", value: false }
|
|
945
|
+
]
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
if (shouldCreateChannel) {
|
|
949
|
+
const channelData = yield handleChannelCreation(cliApi);
|
|
950
|
+
channelId = channelData.channelId;
|
|
951
|
+
storefrontToken = channelData.storefrontToken;
|
|
952
|
+
envVars = __spreadValues({}, channelData.envVars);
|
|
953
|
+
console.log(chalk3.green(`Channel created successfully`));
|
|
954
|
+
}
|
|
955
|
+
if (!shouldCreateChannel) {
|
|
956
|
+
channelId = yield handleChannelSelection(bc);
|
|
957
|
+
const initData = yield getChannelInit(cliApi, channelId);
|
|
958
|
+
envVars = __spreadValues({}, initData.envVars);
|
|
959
|
+
storefrontToken = initData.storefrontToken;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
919
962
|
}
|
|
920
963
|
}
|
|
964
|
+
if (options.env) {
|
|
965
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
966
|
+
const [key, value] = env.split("=");
|
|
967
|
+
if (key && value) {
|
|
968
|
+
acc[key] = value;
|
|
969
|
+
}
|
|
970
|
+
return acc;
|
|
971
|
+
}, {});
|
|
972
|
+
Object.assign(envVars, cliEnvVars);
|
|
973
|
+
}
|
|
974
|
+
if (options.storeHash) {
|
|
975
|
+
envVars.BIGCOMMERCE_STORE_HASH = options.storeHash;
|
|
976
|
+
}
|
|
977
|
+
if (options.channelId) {
|
|
978
|
+
envVars.BIGCOMMERCE_CHANNEL_ID = options.channelId;
|
|
979
|
+
}
|
|
980
|
+
if (options.storefrontToken) {
|
|
981
|
+
envVars.BIGCOMMERCE_STOREFRONT_TOKEN = options.storefrontToken;
|
|
982
|
+
}
|
|
921
983
|
if (!channelId) throw new Error("Something went wrong, channelId is not defined");
|
|
922
984
|
if (!storefrontToken) throw new Error("Something went wrong, storefrontToken is not defined");
|
|
923
985
|
console.log(`
|
|
924
986
|
Creating '${projectName}' at '${projectDir}'
|
|
925
987
|
`);
|
|
926
|
-
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain });
|
|
927
|
-
writeEnv(projectDir, {
|
|
928
|
-
channelId: channelId.toString(),
|
|
929
|
-
storeHash,
|
|
930
|
-
storefrontToken,
|
|
931
|
-
arbitraryEnv: options.env
|
|
932
|
-
});
|
|
988
|
+
cloneCatalyst({ repository, projectName, projectDir, ghRef, resetMain: options.resetMain });
|
|
933
989
|
yield installDependencies(projectDir);
|
|
990
|
+
writeEnv(projectDir, envVars);
|
|
991
|
+
if (credentials) {
|
|
992
|
+
storeCredentials(projectDir, credentials);
|
|
993
|
+
}
|
|
934
994
|
console.log(
|
|
935
995
|
`
|
|
936
|
-
${
|
|
996
|
+
${chalk3.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
937
997
|
`,
|
|
938
998
|
"\nNext steps:\n",
|
|
939
|
-
|
|
999
|
+
chalk3.yellow(`
|
|
940
1000
|
cd ${projectName} && pnpm run dev
|
|
941
1001
|
`)
|
|
942
1002
|
);
|
|
943
1003
|
}));
|
|
1004
|
+
function isInitResponse(response) {
|
|
1005
|
+
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;
|
|
1006
|
+
}
|
|
1007
|
+
function isEligibilityResponse(response) {
|
|
1008
|
+
return typeof response === "object" && response !== null && "data" in response && typeof response.data === "object" && response.data !== null && "eligible" in response.data && "message" in response.data;
|
|
1009
|
+
}
|
|
1010
|
+
function isCreateChannelResponse(response) {
|
|
1011
|
+
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;
|
|
1012
|
+
}
|
|
1013
|
+
function isChannelsResponse(response) {
|
|
1014
|
+
return typeof response === "object" && response !== null && "data" in response && Array.isArray(response.data) && response.data.every(
|
|
1015
|
+
(item) => typeof item === "object" && item !== null && "id" in item && "name" in item && "platform" in item
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
944
1018
|
|
|
945
1019
|
// src/commands/init.ts
|
|
946
1020
|
import { Command as Command2, Option as Option2 } from "@commander-js/extra-typings";
|
|
947
|
-
import {
|
|
948
|
-
import
|
|
949
|
-
|
|
1021
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
1022
|
+
import chalk4 from "chalk";
|
|
1023
|
+
function isChannelsResponse2(response) {
|
|
1024
|
+
return typeof response === "object" && response !== null && "data" in response && Array.isArray(response.data) && response.data.every(
|
|
1025
|
+
(item) => typeof item === "object" && item !== null && "id" in item && "name" in item && "platform" in item
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
1028
|
+
function isInitResponse2(response) {
|
|
1029
|
+
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;
|
|
1030
|
+
}
|
|
950
1031
|
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(
|
|
1032
|
+
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
1033
|
new Option2("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
953
1034
|
).addOption(
|
|
954
|
-
new Option2("--
|
|
1035
|
+
new Option2("--cli-api-origin <origin>", "Catalyst CLI API origin").default("https://cxm-prd.bigcommerceapp.com").hideHelp()
|
|
955
1036
|
).action((options) => __async(void 0, null, function* () {
|
|
956
1037
|
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
1038
|
let storeHash = options.storeHash;
|
|
962
1039
|
let accessToken = options.accessToken;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
accessToken = credentials.accessToken;
|
|
1040
|
+
if (!storeHash || !accessToken) {
|
|
1041
|
+
const config = new Config(projectDir);
|
|
1042
|
+
const storedAuth = config.getAuth();
|
|
1043
|
+
storeHash = storeHash != null ? storeHash : storedAuth.storeHash;
|
|
1044
|
+
accessToken = accessToken != null ? accessToken : storedAuth.accessToken;
|
|
969
1045
|
}
|
|
970
1046
|
if (!storeHash || !accessToken) {
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1047
|
+
const credentials = yield login(`https://login.${options.bigcommerceHostname}`);
|
|
1048
|
+
storeHash = credentials.storeHash;
|
|
1049
|
+
accessToken = credentials.accessToken;
|
|
1050
|
+
storeCredentials(projectDir, credentials);
|
|
975
1051
|
}
|
|
976
1052
|
yield telemetry2.identify(storeHash);
|
|
977
|
-
const bc = new Https({
|
|
978
|
-
|
|
979
|
-
|
|
1053
|
+
const bc = new Https({
|
|
1054
|
+
baseUrl: `https://api.${options.bigcommerceHostname}/stores/${storeHash}`,
|
|
1055
|
+
accessToken
|
|
1056
|
+
});
|
|
1057
|
+
const cliApi = new CliApi({
|
|
1058
|
+
origin: options.cliApiOrigin,
|
|
980
1059
|
storeHash,
|
|
981
1060
|
accessToken
|
|
982
1061
|
});
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
|
|
1062
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
1063
|
+
const channelsResponse = yield bc.fetch("/v3/channels?available=true&type=storefront");
|
|
1064
|
+
if (!channelsResponse.ok) {
|
|
1065
|
+
console.error(
|
|
1066
|
+
chalk4.red(
|
|
1067
|
+
`
|
|
1068
|
+
GET /v3/channels failed: ${channelsResponse.status} ${channelsResponse.statusText}
|
|
1069
|
+
`
|
|
1070
|
+
)
|
|
1071
|
+
);
|
|
1072
|
+
process.exit(1);
|
|
986
1073
|
}
|
|
987
|
-
|
|
988
|
-
if (
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
choices: [
|
|
992
|
-
{ name: "Yes", value: true },
|
|
993
|
-
{ name: "No", value: false }
|
|
994
|
-
]
|
|
995
|
-
});
|
|
1074
|
+
const availableChannels = yield channelsResponse.json();
|
|
1075
|
+
if (!isChannelsResponse2(availableChannels)) {
|
|
1076
|
+
console.error(chalk4.red("\nUnexpected response format from channels endpoint\n"));
|
|
1077
|
+
process.exit(1);
|
|
996
1078
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1079
|
+
const existingChannel = yield select2({
|
|
1080
|
+
message: "Which channel would you like to use?",
|
|
1081
|
+
choices: availableChannels.data.sort(
|
|
1082
|
+
(a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)
|
|
1083
|
+
).map((ch) => ({
|
|
1084
|
+
name: ch.name,
|
|
1085
|
+
value: ch,
|
|
1086
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
1087
|
+
}))
|
|
1088
|
+
});
|
|
1089
|
+
const channelId = existingChannel.id;
|
|
1090
|
+
const initResponse = yield cliApi.getChannelInit(channelId);
|
|
1091
|
+
if (!initResponse.ok) {
|
|
1092
|
+
console.error(
|
|
1093
|
+
chalk4.red(
|
|
1094
|
+
`
|
|
1095
|
+
GET /channels/${channelId}/init failed: ${initResponse.status} ${initResponse.statusText}
|
|
1096
|
+
`
|
|
1097
|
+
)
|
|
1098
|
+
);
|
|
1099
|
+
process.exit(1);
|
|
1006
1100
|
}
|
|
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;
|
|
1101
|
+
const initData = yield initResponse.json();
|
|
1102
|
+
if (!isInitResponse2(initData)) {
|
|
1103
|
+
console.error(chalk4.red("\nUnexpected response format from init endpoint\n"));
|
|
1104
|
+
process.exit(1);
|
|
1025
1105
|
}
|
|
1026
|
-
|
|
1027
|
-
if (
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1106
|
+
const envVars = __spreadValues({}, initData.data.envVars);
|
|
1107
|
+
if (options.env) {
|
|
1108
|
+
const cliEnvVars = options.env.reduce((acc, env) => {
|
|
1109
|
+
const [key, value] = env.split("=");
|
|
1110
|
+
if (key && value) {
|
|
1111
|
+
acc[key] = value;
|
|
1112
|
+
}
|
|
1113
|
+
return acc;
|
|
1114
|
+
}, {});
|
|
1115
|
+
Object.assign(envVars, cliEnvVars);
|
|
1116
|
+
}
|
|
1117
|
+
writeEnv(projectDir, envVars);
|
|
1118
|
+
console.log(chalk4.green(`
|
|
1119
|
+
.env.local file created for channel ${existingChannel.name}!
|
|
1120
|
+
`));
|
|
1121
|
+
console.log(chalk4.green(`
|
|
1122
|
+
Next steps:
|
|
1123
|
+
`));
|
|
1124
|
+
console.log(chalk4.yellow(`
|
|
1125
|
+
pnpm run dev
|
|
1126
|
+
`));
|
|
1033
1127
|
}));
|
|
1034
1128
|
|
|
1035
1129
|
// src/commands/integration.ts
|
|
@@ -1040,16 +1134,16 @@ import { outputFileSync as outputFileSync2, writeJsonSync } from "fs-extra/esm";
|
|
|
1040
1134
|
import kebabCase2 from "lodash.kebabcase";
|
|
1041
1135
|
import { coerce, compare } from "semver";
|
|
1042
1136
|
import { promisify } from "util";
|
|
1043
|
-
import { z as
|
|
1137
|
+
import { z as z3 } from "zod";
|
|
1044
1138
|
var exec = promisify(execCb);
|
|
1045
|
-
var ManifestSchema =
|
|
1046
|
-
name:
|
|
1047
|
-
dependencies:
|
|
1048
|
-
devDependencies:
|
|
1049
|
-
environmentVariables:
|
|
1139
|
+
var ManifestSchema = z3.object({
|
|
1140
|
+
name: z3.string(),
|
|
1141
|
+
dependencies: z3.object({ add: z3.array(z3.string()) }),
|
|
1142
|
+
devDependencies: z3.object({ add: z3.array(z3.string()) }),
|
|
1143
|
+
environmentVariables: z3.array(z3.string())
|
|
1050
1144
|
});
|
|
1051
1145
|
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 =
|
|
1146
|
+
const integrationName = z3.string().transform(kebabCase2).parse(integrationNameRaw);
|
|
1053
1147
|
const manifest = {
|
|
1054
1148
|
name: integrationName,
|
|
1055
1149
|
dependencies: { add: [] },
|
|
@@ -1071,9 +1165,9 @@ var integration = new Command3("integration").argument("<integration-name>", "Fo
|
|
|
1071
1165
|
}
|
|
1072
1166
|
return 0;
|
|
1073
1167
|
}).reverse();
|
|
1074
|
-
const PackageDependenciesSchema =
|
|
1075
|
-
dependencies:
|
|
1076
|
-
devDependencies:
|
|
1168
|
+
const PackageDependenciesSchema = z3.object({
|
|
1169
|
+
dependencies: z3.object({}).passthrough(),
|
|
1170
|
+
devDependencies: z3.object({}).passthrough()
|
|
1077
1171
|
});
|
|
1078
1172
|
const getPackageDeps = (ref) => __async(void 0, null, function* () {
|
|
1079
1173
|
const { stdout } = yield exec(`git show ${ref}:core/package.json`);
|
|
@@ -1109,7 +1203,7 @@ var integration = new Command3("integration").argument("<integration-name>", "Fo
|
|
|
1109
1203
|
import { Argument, Command as Command4, Option as Option3 } from "@commander-js/extra-typings";
|
|
1110
1204
|
|
|
1111
1205
|
// src/utils/telemetry/index.ts
|
|
1112
|
-
import
|
|
1206
|
+
import chalk5 from "chalk";
|
|
1113
1207
|
var telemetry3 = new Telemetry();
|
|
1114
1208
|
var isEnabled = telemetry3.isEnabled();
|
|
1115
1209
|
var catalystTelemetry = (options, arg) => {
|
|
@@ -1130,7 +1224,7 @@ var catalystTelemetry = (options, arg) => {
|
|
|
1130
1224
|
}
|
|
1131
1225
|
console.log(
|
|
1132
1226
|
`
|
|
1133
|
-
Status: ${
|
|
1227
|
+
Status: ${chalk5.bold(isEnabled ? chalk5.green("Enabled") : chalk5.red("Disabled"))}`
|
|
1134
1228
|
);
|
|
1135
1229
|
if (!isEnabled) {
|
|
1136
1230
|
console.log(
|
|
@@ -1183,7 +1277,7 @@ var telemetryPostHook = () => __async(void 0, null, function* () {
|
|
|
1183
1277
|
});
|
|
1184
1278
|
|
|
1185
1279
|
// src/index.ts
|
|
1186
|
-
console.log(
|
|
1280
|
+
console.log(chalk6.cyanBright(`
|
|
1187
1281
|
\u25E2 ${package_default.name} v${package_default.version}
|
|
1188
1282
|
`));
|
|
1189
1283
|
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);
|