@bigcommerce/create-catalyst 0.1.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/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/index.js +875 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 BigCommerce
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# create-catalyst
|
|
2
|
+
|
|
3
|
+
Create a new Catalyst project, optionally connect the project to a BigCommerce store. Also supports "switching" the store that Catalyst is connected to by running `init`.
|
|
4
|
+
|
|
5
|
+
## NPM
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm create catalyst-storefront@latest
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## PNPM
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm create catalyst-storefront@latest
|
|
15
|
+
```
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
33
|
+
var __async = (__this, __arguments, generator) => {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
var fulfilled = (value) => {
|
|
36
|
+
try {
|
|
37
|
+
step(generator.next(value));
|
|
38
|
+
} catch (e) {
|
|
39
|
+
reject(e);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var rejected = (value) => {
|
|
43
|
+
try {
|
|
44
|
+
step(generator.throw(value));
|
|
45
|
+
} catch (e) {
|
|
46
|
+
reject(e);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
50
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/index.ts
|
|
55
|
+
import { Command, Option } from "@commander-js/extra-typings";
|
|
56
|
+
import chalk8 from "chalk";
|
|
57
|
+
import { satisfies } from "semver";
|
|
58
|
+
|
|
59
|
+
// package.json
|
|
60
|
+
var package_default = {
|
|
61
|
+
name: "@bigcommerce/create-catalyst",
|
|
62
|
+
version: "0.1.0",
|
|
63
|
+
type: "module",
|
|
64
|
+
bin: "dist/index.js",
|
|
65
|
+
files: [
|
|
66
|
+
"dist"
|
|
67
|
+
],
|
|
68
|
+
scripts: {
|
|
69
|
+
dev: "tsup --watch",
|
|
70
|
+
typecheck: "tsc --noEmit",
|
|
71
|
+
lint: "eslint . --max-warnings 0",
|
|
72
|
+
test: "jest",
|
|
73
|
+
build: "tsup"
|
|
74
|
+
},
|
|
75
|
+
engines: {
|
|
76
|
+
node: ">=18.17.0"
|
|
77
|
+
},
|
|
78
|
+
dependencies: {
|
|
79
|
+
"@commander-js/extra-typings": "^12.0.0",
|
|
80
|
+
"@inquirer/prompts": "^3.3.0",
|
|
81
|
+
chalk: "^5.3.0",
|
|
82
|
+
commander: "^12.0.0",
|
|
83
|
+
"fs-extra": "^11.2.0",
|
|
84
|
+
giget: "^1.2.1",
|
|
85
|
+
"lodash.kebabcase": "^4.1.1",
|
|
86
|
+
"lodash.merge": "^4.6.2",
|
|
87
|
+
msw: "^2.1.7",
|
|
88
|
+
nypm: "^0.3.6",
|
|
89
|
+
ora: "^8.0.1",
|
|
90
|
+
semver: "^7.6.0",
|
|
91
|
+
zod: "^3.22.4",
|
|
92
|
+
"zod-validation-error": "^3.0.0"
|
|
93
|
+
},
|
|
94
|
+
devDependencies: {
|
|
95
|
+
"@bigcommerce/eslint-config": "^2.7.0",
|
|
96
|
+
"@bigcommerce/eslint-config-catalyst": "workspace:^",
|
|
97
|
+
"@swc/core": "^1.3.107",
|
|
98
|
+
"@swc/jest": "^0.2.34",
|
|
99
|
+
"@types/fs-extra": "^11.0.4",
|
|
100
|
+
"@types/jest": "^29.5.11",
|
|
101
|
+
"@types/lodash.kebabcase": "^4.1.9",
|
|
102
|
+
"@types/lodash.merge": "^4.6.9",
|
|
103
|
+
"@types/node": "^18.17.12",
|
|
104
|
+
"@types/prompts": "^2.4.9",
|
|
105
|
+
"@types/semver": "^7.5.7",
|
|
106
|
+
eslint: "^8.55.0",
|
|
107
|
+
jest: "^29.7.0",
|
|
108
|
+
prettier: "^3.1.1",
|
|
109
|
+
tsup: "^6.7.0",
|
|
110
|
+
typescript: "^5.3.3"
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/commands/create.ts
|
|
115
|
+
import { input, select as select2 } from "@inquirer/prompts";
|
|
116
|
+
import chalk6 from "chalk";
|
|
117
|
+
import { exec as execCallback } from "child_process";
|
|
118
|
+
import { pathExistsSync } from "fs-extra/esm";
|
|
119
|
+
import kebabCase from "lodash.kebabcase";
|
|
120
|
+
import { join as join3 } from "path";
|
|
121
|
+
import { promisify } from "util";
|
|
122
|
+
import { z as z4 } from "zod";
|
|
123
|
+
|
|
124
|
+
// src/utils/check-storefront-limit.ts
|
|
125
|
+
import chalk from "chalk";
|
|
126
|
+
var checkStorefrontLimit = (channels, storeInfo) => {
|
|
127
|
+
const { data: availableChannels } = channels;
|
|
128
|
+
const { features } = storeInfo;
|
|
129
|
+
if (availableChannels.length >= features.storefront_limits.total_including_inactive) {
|
|
130
|
+
console.error(
|
|
131
|
+
chalk.yellow(
|
|
132
|
+
`You have reached the maximum number of storefronts allowed for your plan. Please select an existing channel below, purchase additional storefront seats in your BigCommerce Control Panel, or contact BigCommerce Support: ${chalk.cyan(
|
|
133
|
+
"https://support.bigcommerce.com"
|
|
134
|
+
)}
|
|
135
|
+
`
|
|
136
|
+
)
|
|
137
|
+
);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const activeChannels = availableChannels.filter((channel) => channel.status === "active");
|
|
141
|
+
if (activeChannels.length >= features.storefront_limits.active) {
|
|
142
|
+
console.error(
|
|
143
|
+
chalk.yellow(
|
|
144
|
+
"You have reached the maximum number of active storefronts allowed for your plan. Please select an existing channel below, de-activate an active channel, or purchase additional storefront seats in your BigCommerce Control Panel.\n"
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// src/utils/clone-catalyst.ts
|
|
153
|
+
import chalk2 from "chalk";
|
|
154
|
+
import { copySync, readJsonSync, removeSync, writeJsonSync } from "fs-extra/esm";
|
|
155
|
+
import { downloadTemplate } from "giget";
|
|
156
|
+
import merge from "lodash.merge";
|
|
157
|
+
import { join } from "path";
|
|
158
|
+
import * as z from "zod";
|
|
159
|
+
|
|
160
|
+
// src/utils/spinner.ts
|
|
161
|
+
import { oraPromise } from "ora";
|
|
162
|
+
var spinnerIcon = "triangle";
|
|
163
|
+
var spinner = (action, oraOpts) => __async(void 0, null, function* () {
|
|
164
|
+
return oraPromise(action, __spreadValues({
|
|
165
|
+
spinner: spinnerIcon
|
|
166
|
+
}, oraOpts)).catch(() => process.exit(1));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// src/utils/clone-catalyst.ts
|
|
170
|
+
var cloneCatalyst = (_0) => __async(void 0, [_0], function* ({
|
|
171
|
+
projectDir,
|
|
172
|
+
projectName,
|
|
173
|
+
ghRef = "main"
|
|
174
|
+
}) {
|
|
175
|
+
yield spinner(
|
|
176
|
+
downloadTemplate(`github:bigcommerce/catalyst/apps/core#${ghRef}`, {
|
|
177
|
+
dir: projectDir,
|
|
178
|
+
offline: false
|
|
179
|
+
}),
|
|
180
|
+
{
|
|
181
|
+
text: "Cloning Catalyst template...",
|
|
182
|
+
successText: "Catalyst template cloned successfully",
|
|
183
|
+
failText: (err) => chalk2.red(`Failed to clone Catalyst template: ${err.message}`)
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
yield spinner(
|
|
187
|
+
downloadTemplate(`github:bigcommerce/catalyst/packages/components#${ghRef}`, {
|
|
188
|
+
dir: join(projectDir, "tmp"),
|
|
189
|
+
offline: false
|
|
190
|
+
}),
|
|
191
|
+
{
|
|
192
|
+
text: "Cloning Catalyst components...",
|
|
193
|
+
successText: "Catalyst components cloned successfully",
|
|
194
|
+
failText: (err) => chalk2.red(`Failed to clone Catalyst components: ${err.message}`)
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
copySync(join(projectDir, "tmp/src/components"), join(projectDir, "components", "ui"));
|
|
198
|
+
copySync(join(projectDir, "tmp/tailwind.config.js"), join(projectDir, "tailwind.config.js"));
|
|
199
|
+
const packageJson = z.object({
|
|
200
|
+
private: z.boolean().optional(),
|
|
201
|
+
exports: z.object({}).passthrough().optional(),
|
|
202
|
+
sideEffects: z.boolean().optional(),
|
|
203
|
+
peerDependencies: z.object({}).passthrough().optional(),
|
|
204
|
+
dependencies: z.object({
|
|
205
|
+
"@bigcommerce/components": z.string().optional(),
|
|
206
|
+
"@bigcommerce/catalyst-client": z.string().optional()
|
|
207
|
+
}).passthrough(),
|
|
208
|
+
devDependencies: z.object({
|
|
209
|
+
react: z.string().optional(),
|
|
210
|
+
"react-dom": z.string().optional(),
|
|
211
|
+
"@bigcommerce/eslint-config-catalyst": z.string().optional()
|
|
212
|
+
}).passthrough()
|
|
213
|
+
}).passthrough().parse(
|
|
214
|
+
merge(
|
|
215
|
+
{},
|
|
216
|
+
readJsonSync(join(projectDir, "tmp/package.json")),
|
|
217
|
+
readJsonSync(join(projectDir, "package.json")),
|
|
218
|
+
{ name: projectName, description: "" }
|
|
219
|
+
)
|
|
220
|
+
);
|
|
221
|
+
delete packageJson.private;
|
|
222
|
+
delete packageJson.exports;
|
|
223
|
+
delete packageJson.sideEffects;
|
|
224
|
+
delete packageJson.peerDependencies;
|
|
225
|
+
delete packageJson.dependencies["@bigcommerce/components"];
|
|
226
|
+
delete packageJson.devDependencies.react;
|
|
227
|
+
delete packageJson.devDependencies["react-dom"];
|
|
228
|
+
packageJson.dependencies["@bigcommerce/catalyst-client"] = `^0.1.1`;
|
|
229
|
+
packageJson.devDependencies["@bigcommerce/eslint-config-catalyst"] = `^0.1.0`;
|
|
230
|
+
writeJsonSync(join(projectDir, "package.json"), packageJson, { spaces: 2 });
|
|
231
|
+
const tsConfigJson = z.object({
|
|
232
|
+
compilerOptions: z.object({
|
|
233
|
+
declaration: z.boolean().optional(),
|
|
234
|
+
declarationMap: z.boolean().optional(),
|
|
235
|
+
paths: z.object({
|
|
236
|
+
"@bigcommerce/components/*": z.string().array().optional()
|
|
237
|
+
}).passthrough()
|
|
238
|
+
}).passthrough()
|
|
239
|
+
}).passthrough().parse(
|
|
240
|
+
merge(
|
|
241
|
+
{},
|
|
242
|
+
readJsonSync(join(projectDir, "tmp/tsconfig.json")),
|
|
243
|
+
readJsonSync(join(projectDir, "tsconfig.json"))
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
|
+
delete tsConfigJson.compilerOptions.declaration;
|
|
247
|
+
delete tsConfigJson.compilerOptions.declarationMap;
|
|
248
|
+
tsConfigJson.compilerOptions.paths["@bigcommerce/components/*"] = ["./components/ui/*"];
|
|
249
|
+
writeJsonSync(join(projectDir, "tsconfig.json"), tsConfigJson, { spaces: 2 });
|
|
250
|
+
removeSync(join(projectDir, "tmp"));
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// src/utils/https.ts
|
|
254
|
+
import chalk3 from "chalk";
|
|
255
|
+
import { z as z3 } from "zod";
|
|
256
|
+
|
|
257
|
+
// src/utils/parse.ts
|
|
258
|
+
import * as z2 from "zod";
|
|
259
|
+
import { fromZodError } from "zod-validation-error";
|
|
260
|
+
var parse = (data, schema) => {
|
|
261
|
+
try {
|
|
262
|
+
return schema.parse(data);
|
|
263
|
+
} catch (error) {
|
|
264
|
+
if (error instanceof z2.ZodError) {
|
|
265
|
+
console.error(fromZodError(error).toString());
|
|
266
|
+
}
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// src/utils/https.ts
|
|
272
|
+
var BigCommerceStoreInfo = z3.object({
|
|
273
|
+
features: z3.object({
|
|
274
|
+
storefront_limits: z3.object({
|
|
275
|
+
active: z3.number(),
|
|
276
|
+
total_including_inactive: z3.number()
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
});
|
|
280
|
+
var BigCommerceV3ApiResponseSchema = (schema) => z3.object({
|
|
281
|
+
data: schema,
|
|
282
|
+
meta: z3.object({})
|
|
283
|
+
});
|
|
284
|
+
var BigCommerceChannelsV3ResponseSchema = BigCommerceV3ApiResponseSchema(
|
|
285
|
+
z3.array(
|
|
286
|
+
z3.object({
|
|
287
|
+
id: z3.number(),
|
|
288
|
+
name: z3.string(),
|
|
289
|
+
status: z3.string(),
|
|
290
|
+
platform: z3.string()
|
|
291
|
+
})
|
|
292
|
+
)
|
|
293
|
+
);
|
|
294
|
+
var Https = class {
|
|
295
|
+
constructor({
|
|
296
|
+
bigCommerceApiUrl,
|
|
297
|
+
bigCommerceAuthUrl,
|
|
298
|
+
sampleDataApiUrl,
|
|
299
|
+
storeHash,
|
|
300
|
+
accessToken
|
|
301
|
+
}) {
|
|
302
|
+
this.DEVICE_OAUTH_CLIENT_ID = "acse0vvawm9r1n0evag4b8e1ea1fo90";
|
|
303
|
+
this.bigCommerceApiUrl = bigCommerceApiUrl || "";
|
|
304
|
+
this.bigCommerceAuthUrl = bigCommerceAuthUrl || "";
|
|
305
|
+
this.sampleDataApiUrl = sampleDataApiUrl || "";
|
|
306
|
+
this.storeHash = storeHash || "";
|
|
307
|
+
this.accessToken = accessToken || "";
|
|
308
|
+
}
|
|
309
|
+
auth(path, opts = {}) {
|
|
310
|
+
if (!this.bigCommerceAuthUrl) {
|
|
311
|
+
throw new Error("bigCommerceAuthUrl is required to make API requests");
|
|
312
|
+
}
|
|
313
|
+
const _a = opts, { headers = {} } = _a, rest = __objRest(_a, ["headers"]);
|
|
314
|
+
const options = __spreadValues({
|
|
315
|
+
method: "POST",
|
|
316
|
+
headers: __spreadProps(__spreadValues({}, headers), {
|
|
317
|
+
Accept: "application/json",
|
|
318
|
+
"Content-Type": "application/json"
|
|
319
|
+
})
|
|
320
|
+
}, rest);
|
|
321
|
+
return fetch(`${this.bigCommerceAuthUrl}${path}`, options);
|
|
322
|
+
}
|
|
323
|
+
getDeviceCode() {
|
|
324
|
+
return __async(this, null, function* () {
|
|
325
|
+
const response = yield this.auth("/device/token", {
|
|
326
|
+
body: JSON.stringify({
|
|
327
|
+
scopes: [
|
|
328
|
+
"store_v2_content",
|
|
329
|
+
"store_v2_information",
|
|
330
|
+
"store_v2_products",
|
|
331
|
+
"store_cart",
|
|
332
|
+
"store_sites",
|
|
333
|
+
"store_channel_settings",
|
|
334
|
+
"store_storefront_api_customer_impersonation"
|
|
335
|
+
].join(" "),
|
|
336
|
+
client_id: this.DEVICE_OAUTH_CLIENT_ID
|
|
337
|
+
})
|
|
338
|
+
});
|
|
339
|
+
if (!response.ok) {
|
|
340
|
+
console.error(
|
|
341
|
+
chalk3.red(`
|
|
342
|
+
POST /device/token failed: ${response.status} ${response.statusText}
|
|
343
|
+
`)
|
|
344
|
+
);
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
const DeviceCodeSchema = z3.object({
|
|
348
|
+
device_code: z3.string(),
|
|
349
|
+
user_code: z3.string(),
|
|
350
|
+
verification_uri: z3.string(),
|
|
351
|
+
expires_in: z3.number(),
|
|
352
|
+
interval: z3.number()
|
|
353
|
+
});
|
|
354
|
+
return parse(yield response.json(), DeviceCodeSchema);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
checkDeviceCode(deviceCode) {
|
|
358
|
+
return __async(this, null, function* () {
|
|
359
|
+
const response = yield this.auth("/device/token", {
|
|
360
|
+
body: JSON.stringify({
|
|
361
|
+
device_code: deviceCode,
|
|
362
|
+
client_id: this.DEVICE_OAUTH_CLIENT_ID
|
|
363
|
+
})
|
|
364
|
+
});
|
|
365
|
+
if (response.status !== 200) {
|
|
366
|
+
throw new Error("Device code not yet verified");
|
|
367
|
+
}
|
|
368
|
+
const DeviceCodeSuccessSchema = z3.object({
|
|
369
|
+
access_token: z3.string(),
|
|
370
|
+
store_hash: z3.string(),
|
|
371
|
+
context: z3.string(),
|
|
372
|
+
api_uri: z3.string().url()
|
|
373
|
+
});
|
|
374
|
+
return parse(yield response.json(), DeviceCodeSuccessSchema);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
api(path, opts = {}) {
|
|
378
|
+
if (!this.bigCommerceApiUrl || !this.storeHash || !this.accessToken) {
|
|
379
|
+
throw new Error(
|
|
380
|
+
"bigCommerceApiUrl, storeHash, and accessToken are required to make API requests"
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
const _a = opts, { headers = {} } = _a, rest = __objRest(_a, ["headers"]);
|
|
384
|
+
const options = __spreadValues({
|
|
385
|
+
headers: __spreadProps(__spreadValues({}, headers), {
|
|
386
|
+
Accept: "application/json",
|
|
387
|
+
"X-Auth-Token": this.accessToken
|
|
388
|
+
})
|
|
389
|
+
}, rest);
|
|
390
|
+
return fetch(`${this.bigCommerceApiUrl}/stores/${this.storeHash}${path}`, options);
|
|
391
|
+
}
|
|
392
|
+
storeInformation() {
|
|
393
|
+
return __async(this, null, function* () {
|
|
394
|
+
const res = yield this.api("/v2/store");
|
|
395
|
+
if (!res.ok) {
|
|
396
|
+
console.error(chalk3.red(`
|
|
397
|
+
GET /v2/store failed: ${res.status} ${res.statusText}
|
|
398
|
+
`));
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
return parse(yield res.json(), BigCommerceStoreInfo);
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
channels(query = "") {
|
|
405
|
+
return __async(this, null, function* () {
|
|
406
|
+
const res = yield this.api(`/v3/channels${query}`);
|
|
407
|
+
if (!res.ok) {
|
|
408
|
+
console.error(chalk3.red(`
|
|
409
|
+
GET /v3/channels failed: ${res.status} ${res.statusText}
|
|
410
|
+
`));
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
return parse(yield res.json(), BigCommerceChannelsV3ResponseSchema);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
customerImpersonationToken(channelId) {
|
|
417
|
+
return __async(this, null, function* () {
|
|
418
|
+
const res = yield this.api("/v3/storefront/api-token-customer-impersonation", {
|
|
419
|
+
method: "POST",
|
|
420
|
+
headers: { "Content-Type": "application/json" },
|
|
421
|
+
body: JSON.stringify({ expires_at: 2147483647, channel_id: channelId })
|
|
422
|
+
});
|
|
423
|
+
if (!res.ok) {
|
|
424
|
+
console.error(
|
|
425
|
+
chalk3.red(
|
|
426
|
+
`
|
|
427
|
+
POST /v3/storefront/api-token-customer-impersonation failed: ${res.status} ${res.statusText}
|
|
428
|
+
`
|
|
429
|
+
)
|
|
430
|
+
);
|
|
431
|
+
process.exit(1);
|
|
432
|
+
}
|
|
433
|
+
const BigCommerceCustomerImpersonationTokenSchema = z3.object({
|
|
434
|
+
data: z3.object({
|
|
435
|
+
token: z3.string()
|
|
436
|
+
})
|
|
437
|
+
});
|
|
438
|
+
return parse(yield res.json(), BigCommerceCustomerImpersonationTokenSchema);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
sampleDataApi(path, opts = {}) {
|
|
442
|
+
if (!this.sampleDataApiUrl || !this.storeHash || !this.accessToken) {
|
|
443
|
+
throw new Error(
|
|
444
|
+
"sampleDataApiUrl, storeHash, and accessToken are required to make API requests"
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
const _a = opts, { headers = {} } = _a, rest = __objRest(_a, ["headers"]);
|
|
448
|
+
const options = __spreadValues({
|
|
449
|
+
method: "POST",
|
|
450
|
+
headers: __spreadProps(__spreadValues({}, headers), {
|
|
451
|
+
Accept: "application/json",
|
|
452
|
+
"Content-Type": "application/json",
|
|
453
|
+
"X-Auth-Token": this.accessToken
|
|
454
|
+
})
|
|
455
|
+
}, rest);
|
|
456
|
+
return fetch(`${this.sampleDataApiUrl}/stores/${this.storeHash}${path}`, options);
|
|
457
|
+
}
|
|
458
|
+
createChannel(channelName) {
|
|
459
|
+
return __async(this, null, function* () {
|
|
460
|
+
const res = yield this.sampleDataApi("/v3/channels/catalyst", {
|
|
461
|
+
body: JSON.stringify({ name: channelName })
|
|
462
|
+
});
|
|
463
|
+
if (!res.ok) {
|
|
464
|
+
console.error(
|
|
465
|
+
chalk3.red(`
|
|
466
|
+
POST /v3/channels/catalyst failed: ${res.status} ${res.statusText}
|
|
467
|
+
`)
|
|
468
|
+
);
|
|
469
|
+
process.exit(1);
|
|
470
|
+
}
|
|
471
|
+
const SampleDataChannelCreateSchema = z3.object({
|
|
472
|
+
data: z3.object({
|
|
473
|
+
id: z3.number(),
|
|
474
|
+
name: z3.string().min(1),
|
|
475
|
+
storefront_api_token: z3.string()
|
|
476
|
+
})
|
|
477
|
+
});
|
|
478
|
+
return parse(yield res.json(), SampleDataChannelCreateSchema);
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/utils/install-dependencies.ts
|
|
484
|
+
import chalk4 from "chalk";
|
|
485
|
+
import { installDependencies as installDeps } from "nypm";
|
|
486
|
+
var installDependencies = (projectDir, packageManager) => __async(void 0, null, function* () {
|
|
487
|
+
return spinner(installDeps({ cwd: projectDir, silent: true, packageManager }), {
|
|
488
|
+
text: `Installing dependencies. This could take a minute...`,
|
|
489
|
+
successText: `Dependencies installed successfully`,
|
|
490
|
+
failText: (err) => chalk4.red(`Failed to install dependencies: ${err.message}`)
|
|
491
|
+
});
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// src/utils/login.ts
|
|
495
|
+
import { select } from "@inquirer/prompts";
|
|
496
|
+
import chalk5 from "chalk";
|
|
497
|
+
var poll = (auth, deviceCode, interval, expiresIn) => __async(void 0, null, function* () {
|
|
498
|
+
const intervalMs = interval * 1e3;
|
|
499
|
+
const expiresAtMs = expiresIn * 1e3;
|
|
500
|
+
const retries = expiresAtMs / intervalMs;
|
|
501
|
+
for (let i = 0; i < retries; i += 1) {
|
|
502
|
+
try {
|
|
503
|
+
return yield auth.checkDeviceCode(deviceCode);
|
|
504
|
+
} catch (err) {
|
|
505
|
+
}
|
|
506
|
+
yield new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
507
|
+
}
|
|
508
|
+
console.error(chalk5.red("\nDevice code expired. Please try again.\n"));
|
|
509
|
+
process.exit(1);
|
|
510
|
+
});
|
|
511
|
+
var login = (bigCommerceAuthUrl, storeHash, accessToken) => __async(void 0, null, function* () {
|
|
512
|
+
if (storeHash && accessToken) {
|
|
513
|
+
return { storeHash, accessToken };
|
|
514
|
+
}
|
|
515
|
+
const shouldLogin = yield select({
|
|
516
|
+
message: "Would you like to connect to a BigCommerce store?",
|
|
517
|
+
choices: [
|
|
518
|
+
{ name: "Yes", value: true },
|
|
519
|
+
{ name: "No", value: false }
|
|
520
|
+
]
|
|
521
|
+
});
|
|
522
|
+
if (!shouldLogin) {
|
|
523
|
+
return { storeHash, accessToken };
|
|
524
|
+
}
|
|
525
|
+
const auth = new Https({ bigCommerceAuthUrl });
|
|
526
|
+
const deviceCode = yield auth.getDeviceCode();
|
|
527
|
+
console.log(
|
|
528
|
+
[
|
|
529
|
+
`
|
|
530
|
+
Please visit ${chalk5.cyan(deviceCode.verification_uri)} and enter the code: ${chalk5.yellow(
|
|
531
|
+
deviceCode.user_code
|
|
532
|
+
)}
|
|
533
|
+
`,
|
|
534
|
+
`The code will expire in ${chalk5.yellow(`${deviceCode.expires_in / 60} minutes`)}
|
|
535
|
+
`
|
|
536
|
+
].join("\n")
|
|
537
|
+
);
|
|
538
|
+
const { store_hash, access_token } = yield spinner(
|
|
539
|
+
poll(auth, deviceCode.device_code, deviceCode.interval, deviceCode.expires_in),
|
|
540
|
+
{
|
|
541
|
+
text: "Waiting for device code to be authorized",
|
|
542
|
+
successText: "Device code authorized\n",
|
|
543
|
+
failText: "Device code expired\n"
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
return {
|
|
547
|
+
storeHash: store_hash,
|
|
548
|
+
accessToken: access_token
|
|
549
|
+
};
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
// src/utils/write-env.ts
|
|
553
|
+
import { randomBytes } from "crypto";
|
|
554
|
+
import { outputFileSync } from "fs-extra/esm";
|
|
555
|
+
import { join as join2 } from "path";
|
|
556
|
+
var writeEnv = (projectDir, {
|
|
557
|
+
channelId,
|
|
558
|
+
storeHash,
|
|
559
|
+
accessToken,
|
|
560
|
+
customerImpersonationToken
|
|
561
|
+
}) => {
|
|
562
|
+
outputFileSync(
|
|
563
|
+
join2(projectDir, ".env.local"),
|
|
564
|
+
[
|
|
565
|
+
`AUTH_SECRET=${randomBytes(32).toString("hex")}`,
|
|
566
|
+
`BIGCOMMERCE_STORE_HASH=${storeHash}`,
|
|
567
|
+
`BIGCOMMERCE_CHANNEL_ID=${channelId}`,
|
|
568
|
+
`BIGCOMMERCE_ACCESS_TOKEN=${accessToken}`,
|
|
569
|
+
`BIGCOMMERCE_CUSTOMER_IMPERSONATION_TOKEN=${customerImpersonationToken}`,
|
|
570
|
+
`CLIENT_LOGGER=false`,
|
|
571
|
+
`ENABLE_ADMIN_ROUTE=true`,
|
|
572
|
+
`NEXT_PUBLIC_DEFAULT_REVALIDATE_TARGET=3600`
|
|
573
|
+
].join("\n")
|
|
574
|
+
);
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
// src/commands/create.ts
|
|
578
|
+
var exec = promisify(execCallback);
|
|
579
|
+
var create = (options) => __async(void 0, null, function* () {
|
|
580
|
+
const { packageManager, ghRef } = options;
|
|
581
|
+
const URLSchema = z4.string().url();
|
|
582
|
+
const sampleDataApiUrl = parse(options.sampleDataApiUrl, URLSchema);
|
|
583
|
+
const bigcommerceApiUrl = parse(`https://api.${options.bigcommerceHostname}`, URLSchema);
|
|
584
|
+
const bigcommerceAuthUrl = parse(`https://login.${options.bigcommerceHostname}`, URLSchema);
|
|
585
|
+
let projectName;
|
|
586
|
+
let projectDir;
|
|
587
|
+
let storeHash = options.storeHash;
|
|
588
|
+
let accessToken = options.accessToken;
|
|
589
|
+
let channelId;
|
|
590
|
+
let customerImpersonationToken = options.customerImpersonationToken;
|
|
591
|
+
if (options.channelId) {
|
|
592
|
+
channelId = parseInt(options.channelId, 10);
|
|
593
|
+
}
|
|
594
|
+
if (!pathExistsSync(options.projectDir)) {
|
|
595
|
+
console.error(chalk6.red(`Error: --projectDir ${options.projectDir} is not a valid path
|
|
596
|
+
`));
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
if (options.projectName) {
|
|
600
|
+
projectName = kebabCase(options.projectName);
|
|
601
|
+
projectDir = join3(options.projectDir, projectName);
|
|
602
|
+
if (pathExistsSync(projectDir)) {
|
|
603
|
+
console.error(chalk6.red(`Error: ${projectDir} already exists
|
|
604
|
+
`));
|
|
605
|
+
process.exit(1);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (!options.projectName) {
|
|
609
|
+
const validateProjectName = (i) => {
|
|
610
|
+
const formatted = kebabCase(i);
|
|
611
|
+
if (!formatted)
|
|
612
|
+
return "Project name is required";
|
|
613
|
+
const targetDir = join3(options.projectDir, formatted);
|
|
614
|
+
if (pathExistsSync(targetDir))
|
|
615
|
+
return `Destination '${targetDir}' already exists`;
|
|
616
|
+
projectName = formatted;
|
|
617
|
+
projectDir = targetDir;
|
|
618
|
+
return true;
|
|
619
|
+
};
|
|
620
|
+
yield input({
|
|
621
|
+
message: "What is the name of your project?",
|
|
622
|
+
default: "my-catalyst-app",
|
|
623
|
+
validate: validateProjectName
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
if (!options.storeHash || !options.accessToken) {
|
|
627
|
+
const credentials = yield login(bigcommerceAuthUrl);
|
|
628
|
+
storeHash = credentials.storeHash;
|
|
629
|
+
accessToken = credentials.accessToken;
|
|
630
|
+
}
|
|
631
|
+
if (!projectName)
|
|
632
|
+
throw new Error("Something went wrong, projectName is not defined");
|
|
633
|
+
if (!projectDir)
|
|
634
|
+
throw new Error("Something went wrong, projectDir is not defined");
|
|
635
|
+
if (!storeHash || !accessToken) {
|
|
636
|
+
console.log(`
|
|
637
|
+
Creating '${projectName}' at '${projectDir}'
|
|
638
|
+
`);
|
|
639
|
+
yield cloneCatalyst({ projectDir, projectName, ghRef });
|
|
640
|
+
console.log(`
|
|
641
|
+
Using ${chalk6.bold(packageManager)}
|
|
642
|
+
`);
|
|
643
|
+
yield installDependencies(projectDir, packageManager);
|
|
644
|
+
console.log(
|
|
645
|
+
[
|
|
646
|
+
`
|
|
647
|
+
${chalk6.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
648
|
+
`,
|
|
649
|
+
`Next steps:`,
|
|
650
|
+
chalk6.yellow(`
|
|
651
|
+
- cd ${projectName} && cp .env.example .env.local`),
|
|
652
|
+
chalk6.yellow(`
|
|
653
|
+
- Populate .env.local with your BigCommerce API credentials
|
|
654
|
+
`)
|
|
655
|
+
].join("\n")
|
|
656
|
+
);
|
|
657
|
+
process.exit(0);
|
|
658
|
+
}
|
|
659
|
+
if (!channelId || !customerImpersonationToken) {
|
|
660
|
+
const bc = new Https({ bigCommerceApiUrl: bigcommerceApiUrl, storeHash, accessToken });
|
|
661
|
+
const availableChannels = yield bc.channels("?available=true&type=storefront");
|
|
662
|
+
const storeInfo = yield bc.storeInformation();
|
|
663
|
+
const canCreateChannel = checkStorefrontLimit(availableChannels, storeInfo);
|
|
664
|
+
let shouldCreateChannel;
|
|
665
|
+
if (canCreateChannel) {
|
|
666
|
+
shouldCreateChannel = yield select2({
|
|
667
|
+
message: "Would you like to create a new channel?",
|
|
668
|
+
choices: [
|
|
669
|
+
{ name: "Yes", value: true },
|
|
670
|
+
{ name: "No", value: false }
|
|
671
|
+
]
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
if (shouldCreateChannel) {
|
|
675
|
+
const newChannelName = yield input({
|
|
676
|
+
message: "What would you like to name your new channel?"
|
|
677
|
+
});
|
|
678
|
+
const sampleDataApi = new Https({
|
|
679
|
+
sampleDataApiUrl,
|
|
680
|
+
storeHash,
|
|
681
|
+
accessToken
|
|
682
|
+
});
|
|
683
|
+
const {
|
|
684
|
+
data: { id: createdChannelId, storefront_api_token: storefrontApiToken }
|
|
685
|
+
} = yield sampleDataApi.createChannel(newChannelName);
|
|
686
|
+
channelId = createdChannelId;
|
|
687
|
+
customerImpersonationToken = storefrontApiToken;
|
|
688
|
+
}
|
|
689
|
+
if (!shouldCreateChannel) {
|
|
690
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
691
|
+
const existingChannel = yield select2({
|
|
692
|
+
message: "Which channel would you like to use?",
|
|
693
|
+
choices: availableChannels.data.sort(
|
|
694
|
+
(a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)
|
|
695
|
+
).map((ch) => ({
|
|
696
|
+
name: ch.name,
|
|
697
|
+
value: ch,
|
|
698
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
699
|
+
}))
|
|
700
|
+
});
|
|
701
|
+
channelId = existingChannel.id;
|
|
702
|
+
const {
|
|
703
|
+
data: { token }
|
|
704
|
+
} = yield bc.customerImpersonationToken(channelId);
|
|
705
|
+
customerImpersonationToken = token;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (!channelId)
|
|
709
|
+
throw new Error("Something went wrong, channelId is not defined");
|
|
710
|
+
if (!customerImpersonationToken)
|
|
711
|
+
throw new Error("Something went wrong, customerImpersonationToken is not defined");
|
|
712
|
+
console.log(`
|
|
713
|
+
Creating '${projectName}' at '${projectDir}'
|
|
714
|
+
`);
|
|
715
|
+
yield cloneCatalyst({ projectDir, projectName, ghRef });
|
|
716
|
+
writeEnv(projectDir, {
|
|
717
|
+
channelId: channelId.toString(),
|
|
718
|
+
storeHash,
|
|
719
|
+
accessToken,
|
|
720
|
+
customerImpersonationToken
|
|
721
|
+
});
|
|
722
|
+
console.log(`
|
|
723
|
+
Using ${chalk6.bold(packageManager)}
|
|
724
|
+
`);
|
|
725
|
+
yield installDependencies(projectDir, packageManager);
|
|
726
|
+
yield spinner(exec(`${packageManager} run codegen`, { cwd: projectDir }), {
|
|
727
|
+
text: "Generating GraphQL types...",
|
|
728
|
+
successText: "GraphQL types generated successfully",
|
|
729
|
+
failText: (err) => chalk6.red(`Failed to generate GraphQL types: ${err.message}`)
|
|
730
|
+
});
|
|
731
|
+
yield spinner(exec(`${packageManager} run lint -- --fix`, { cwd: projectDir }), {
|
|
732
|
+
text: "Linting to validate generated types...",
|
|
733
|
+
successText: "GraphQL types validated successfully",
|
|
734
|
+
failText: (err) => chalk6.red(`Failed to validate GraphQL types: ${err.message}`)
|
|
735
|
+
});
|
|
736
|
+
console.log(
|
|
737
|
+
`
|
|
738
|
+
${chalk6.green("Success!")} Created '${projectName}' at '${projectDir}'
|
|
739
|
+
`,
|
|
740
|
+
"\nNext steps:\n",
|
|
741
|
+
chalk6.yellow(`
|
|
742
|
+
cd ${projectName} && ${packageManager} run dev
|
|
743
|
+
`)
|
|
744
|
+
);
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
// src/commands/init.ts
|
|
748
|
+
import { input as input2, select as select3 } from "@inquirer/prompts";
|
|
749
|
+
import chalk7 from "chalk";
|
|
750
|
+
import * as z5 from "zod";
|
|
751
|
+
var init = (options) => __async(void 0, null, function* () {
|
|
752
|
+
const projectDir = process.cwd();
|
|
753
|
+
const URLSchema = z5.string().url();
|
|
754
|
+
const sampleDataApiUrl = parse(options.sampleDataApiUrl, URLSchema);
|
|
755
|
+
const bigCommerceApiUrl = `https://api.${options.bigcommerceHostname}`;
|
|
756
|
+
const bigCommerceAuthUrl = `https://login.${options.bigcommerceHostname}`;
|
|
757
|
+
let storeHash = options.storeHash;
|
|
758
|
+
let accessToken = options.accessToken;
|
|
759
|
+
let channelId;
|
|
760
|
+
let customerImpersonationToken;
|
|
761
|
+
if (!options.storeHash || !options.accessToken) {
|
|
762
|
+
const credentials = yield login(bigCommerceAuthUrl);
|
|
763
|
+
storeHash = credentials.storeHash;
|
|
764
|
+
accessToken = credentials.accessToken;
|
|
765
|
+
}
|
|
766
|
+
if (!storeHash || !accessToken) {
|
|
767
|
+
console.log(
|
|
768
|
+
chalk7.yellow("\nYou must authenticate with a store to overwrite your local environment.\n")
|
|
769
|
+
);
|
|
770
|
+
process.exit(1);
|
|
771
|
+
}
|
|
772
|
+
const bc = new Https({ bigCommerceApiUrl, storeHash, accessToken });
|
|
773
|
+
const availableChannels = yield bc.channels("?available=true&type=storefront");
|
|
774
|
+
const storeInfo = yield bc.storeInformation();
|
|
775
|
+
const canCreateChannel = checkStorefrontLimit(availableChannels, storeInfo);
|
|
776
|
+
let shouldCreateChannel;
|
|
777
|
+
if (canCreateChannel) {
|
|
778
|
+
shouldCreateChannel = yield select3({
|
|
779
|
+
message: "Would you like to create a new channel?",
|
|
780
|
+
choices: [
|
|
781
|
+
{ name: "Yes", value: true },
|
|
782
|
+
{ name: "No", value: false }
|
|
783
|
+
]
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
if (shouldCreateChannel) {
|
|
787
|
+
const newChannelName = yield input2({
|
|
788
|
+
message: "What would you like to name your new channel?"
|
|
789
|
+
});
|
|
790
|
+
const sampleDataApi = new Https({
|
|
791
|
+
sampleDataApiUrl,
|
|
792
|
+
storeHash,
|
|
793
|
+
accessToken
|
|
794
|
+
});
|
|
795
|
+
const {
|
|
796
|
+
data: { id: createdChannelId, storefront_api_token: storefrontApiToken }
|
|
797
|
+
} = yield sampleDataApi.createChannel(newChannelName);
|
|
798
|
+
channelId = createdChannelId;
|
|
799
|
+
customerImpersonationToken = storefrontApiToken;
|
|
800
|
+
}
|
|
801
|
+
if (!shouldCreateChannel) {
|
|
802
|
+
const channelSortOrder = ["catalyst", "next", "bigcommerce"];
|
|
803
|
+
const existingChannel = yield select3({
|
|
804
|
+
message: "Which channel would you like to use?",
|
|
805
|
+
choices: availableChannels.data.sort((a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)).map((ch) => ({
|
|
806
|
+
name: ch.name,
|
|
807
|
+
value: ch,
|
|
808
|
+
description: `Channel Platform: ${ch.platform === "bigcommerce" ? "Stencil" : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)}`
|
|
809
|
+
}))
|
|
810
|
+
});
|
|
811
|
+
channelId = existingChannel.id;
|
|
812
|
+
const {
|
|
813
|
+
data: { token }
|
|
814
|
+
} = yield bc.customerImpersonationToken(channelId);
|
|
815
|
+
customerImpersonationToken = token;
|
|
816
|
+
}
|
|
817
|
+
if (!channelId)
|
|
818
|
+
throw new Error("Something went wrong, channelId is not defined");
|
|
819
|
+
if (!customerImpersonationToken)
|
|
820
|
+
throw new Error("Something went wrong, customerImpersonationToken is not defined");
|
|
821
|
+
writeEnv(projectDir, {
|
|
822
|
+
channelId: channelId.toString(),
|
|
823
|
+
storeHash,
|
|
824
|
+
accessToken,
|
|
825
|
+
customerImpersonationToken
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// src/utils/pm.ts
|
|
830
|
+
var packageManagerChoices = ["npm", "pnpm", "yarn"];
|
|
831
|
+
function getPackageManager() {
|
|
832
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
833
|
+
if (userAgent.startsWith("yarn")) {
|
|
834
|
+
return "yarn";
|
|
835
|
+
}
|
|
836
|
+
if (userAgent.startsWith("pnpm")) {
|
|
837
|
+
return "pnpm";
|
|
838
|
+
}
|
|
839
|
+
return "npm";
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/index.ts
|
|
843
|
+
if (!satisfies(process.version, package_default.engines.node)) {
|
|
844
|
+
console.error(
|
|
845
|
+
chalk8.red(
|
|
846
|
+
`
|
|
847
|
+
You are using Node.js ${process.version}. Catalyst requires ${package_default.engines.node}. Please upgrade your Node.js version to continue.
|
|
848
|
+
`
|
|
849
|
+
)
|
|
850
|
+
);
|
|
851
|
+
console.log(
|
|
852
|
+
chalk8.yellow(
|
|
853
|
+
"Tip: If you use nvm, you can run `nvm install 18` to install a compatible node version.\n"
|
|
854
|
+
)
|
|
855
|
+
);
|
|
856
|
+
process.exit(1);
|
|
857
|
+
}
|
|
858
|
+
console.log(chalk8.cyanBright(`
|
|
859
|
+
\u25E2 ${package_default.name} v${package_default.version}
|
|
860
|
+
`));
|
|
861
|
+
var program = new Command().name(package_default.name).version(package_default.version).description("A command line tool to create a new Catalyst project.");
|
|
862
|
+
var createCommand = program.command("create", { isDefault: true }).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("--gh-ref <url>", "Clone a specific ref from the bigcommerce/catalyst repository", "main").option("--store-hash <hash>", "BigCommerce store hash").option("--access-token <token>", "BigCommerce access token").option("--channel-id <id>", "BigCommerce channel ID").option("--customer-impersonation-token <token>", "BigCommerce customer impersonation token").addOption(
|
|
863
|
+
new Option("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
864
|
+
).addOption(
|
|
865
|
+
new Option("--sample-data-api-url <url>", "BigCommerce sample data API URL").default("https://api.bc-sample.store").hideHelp()
|
|
866
|
+
).addOption(
|
|
867
|
+
new Option("--package-manager <pm>", "Override detected package manager").choices(packageManagerChoices).default(getPackageManager()).hideHelp()
|
|
868
|
+
).action((opts) => create(opts));
|
|
869
|
+
var initCommand = program.command("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(
|
|
870
|
+
new Option("--bigcommerce-hostname <hostname>", "BigCommerce hostname").default("bigcommerce.com").hideHelp()
|
|
871
|
+
).addOption(
|
|
872
|
+
new Option("--sample-data-api-url <url>", "BigCommerce sample data API URL").default("https://api.bc-sample.store").hideHelp()
|
|
873
|
+
).action((opts) => init(opts));
|
|
874
|
+
program.parse(process.argv);
|
|
875
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../package.json","../src/commands/create.ts","../src/utils/check-storefront-limit.ts","../src/utils/clone-catalyst.ts","../src/utils/spinner.ts","../src/utils/https.ts","../src/utils/parse.ts","../src/utils/install-dependencies.ts","../src/utils/login.ts","../src/utils/write-env.ts","../src/commands/init.ts","../src/utils/pm.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command, Option } from '@commander-js/extra-typings';\nimport chalk from 'chalk';\nimport { satisfies } from 'semver';\n\nimport PACKAGE_INFO from '../package.json';\n\nimport { create } from './commands/create';\nimport { init } from './commands/init';\nimport { getPackageManager, packageManagerChoices } from './utils/pm';\n\nif (!satisfies(process.version, PACKAGE_INFO.engines.node)) {\n console.error(\n chalk.red(\n `\\nYou are using Node.js ${process.version}. Catalyst requires ${PACKAGE_INFO.engines.node}. Please upgrade your Node.js version to continue.\\n`,\n ),\n );\n console.log(\n chalk.yellow(\n 'Tip: If you use nvm, you can run `nvm install 18` to install a compatible node version.\\n',\n ),\n );\n process.exit(1);\n}\n\nconsole.log(chalk.cyanBright(`\\n◢ ${PACKAGE_INFO.name} v${PACKAGE_INFO.version}\\n`));\n\nexport type Options<T> = T extends Command<infer Args, infer Opts> ? [...Args, Opts, T] : never;\n\nconst program = new Command()\n .name(PACKAGE_INFO.name)\n .version(PACKAGE_INFO.version)\n .description('A command line tool to create a new Catalyst project.');\n\nconst createCommand = program\n .command('create', { isDefault: true })\n .description('Command to scaffold and connect a Catalyst storefront to your BigCommerce store')\n .option('--project-name <name>', 'Name of your Catalyst project')\n .option('--project-dir <dir>', 'Directory in which to create your project', process.cwd())\n .option('--gh-ref <url>', 'Clone a specific ref from the bigcommerce/catalyst repository', 'main')\n .option('--store-hash <hash>', 'BigCommerce store hash')\n .option('--access-token <token>', 'BigCommerce access token')\n .option('--channel-id <id>', 'BigCommerce channel ID')\n .option('--customer-impersonation-token <token>', 'BigCommerce customer impersonation token')\n .addOption(\n new Option('--bigcommerce-hostname <hostname>', 'BigCommerce hostname')\n .default('bigcommerce.com')\n .hideHelp(),\n )\n .addOption(\n new Option('--sample-data-api-url <url>', 'BigCommerce sample data API URL')\n .default('https://api.bc-sample.store')\n .hideHelp(),\n )\n .addOption(\n new Option('--package-manager <pm>', 'Override detected package manager')\n .choices(packageManagerChoices)\n .default(getPackageManager())\n .hideHelp(),\n )\n .action((opts) => create(opts));\n\nexport type CreateCommandOptions = Options<typeof createCommand>[0];\n\nconst initCommand = program\n .command('init')\n .description('Connect a BigCommerce store with an existing Catalyst project')\n .option('--store-hash <hash>', 'BigCommerce store hash')\n .option('--access-token <token>', 'BigCommerce access token')\n .addOption(\n new Option('--bigcommerce-hostname <hostname>', 'BigCommerce hostname')\n .default('bigcommerce.com')\n .hideHelp(),\n )\n .addOption(\n new Option('--sample-data-api-url <url>', 'BigCommerce sample data API URL')\n .default('https://api.bc-sample.store')\n .hideHelp(),\n )\n .action((opts) => init(opts));\n\nexport type InitCommandOptions = Options<typeof initCommand>[0];\n\nprogram.parse(process.argv);\n","{\n \"name\": \"@bigcommerce/create-catalyst\",\n \"version\": \"0.1.0\",\n \"type\": \"module\",\n \"bin\": \"dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"eslint . --max-warnings 0\",\n \"test\": \"jest\",\n \"build\": \"tsup\"\n },\n \"engines\": {\n \"node\": \">=18.17.0\"\n },\n \"dependencies\": {\n \"@commander-js/extra-typings\": \"^12.0.0\",\n \"@inquirer/prompts\": \"^3.3.0\",\n \"chalk\": \"^5.3.0\",\n \"commander\": \"^12.0.0\",\n \"fs-extra\": \"^11.2.0\",\n \"giget\": \"^1.2.1\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"lodash.merge\": \"^4.6.2\",\n \"msw\": \"^2.1.7\",\n \"nypm\": \"^0.3.6\",\n \"ora\": \"^8.0.1\",\n \"semver\": \"^7.6.0\",\n \"zod\": \"^3.22.4\",\n \"zod-validation-error\": \"^3.0.0\"\n },\n \"devDependencies\": {\n \"@bigcommerce/eslint-config\": \"^2.7.0\",\n \"@bigcommerce/eslint-config-catalyst\": \"workspace:^\",\n \"@swc/core\": \"^1.3.107\",\n \"@swc/jest\": \"^0.2.34\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/jest\": \"^29.5.11\",\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@types/lodash.merge\": \"^4.6.9\",\n \"@types/node\": \"^18.17.12\",\n \"@types/prompts\": \"^2.4.9\",\n \"@types/semver\": \"^7.5.7\",\n \"eslint\": \"^8.55.0\",\n \"jest\": \"^29.7.0\",\n \"prettier\": \"^3.1.1\",\n \"tsup\": \"^6.7.0\",\n \"typescript\": \"^5.3.3\"\n }\n}\n","import { input, select } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport { exec as execCallback } from 'child_process';\nimport { pathExistsSync } from 'fs-extra/esm';\nimport kebabCase from 'lodash.kebabcase';\nimport { join } from 'path';\nimport { promisify } from 'util';\nimport { z } from 'zod';\n\nimport { type CreateCommandOptions } from '..';\nimport { checkStorefrontLimit } from '../utils/check-storefront-limit';\nimport { cloneCatalyst } from '../utils/clone-catalyst';\nimport { Https } from '../utils/https';\nimport { installDependencies } from '../utils/install-dependencies';\nimport { login } from '../utils/login';\nimport { parse } from '../utils/parse';\nimport { spinner } from '../utils/spinner';\nimport { writeEnv } from '../utils/write-env';\n\nconst exec = promisify(execCallback);\n\nexport const create = async (options: CreateCommandOptions) => {\n const { packageManager, ghRef } = options;\n\n const URLSchema = z.string().url();\n const sampleDataApiUrl = parse(options.sampleDataApiUrl, URLSchema);\n const bigcommerceApiUrl = parse(`https://api.${options.bigcommerceHostname}`, URLSchema);\n const bigcommerceAuthUrl = parse(`https://login.${options.bigcommerceHostname}`, URLSchema);\n\n let projectName;\n let projectDir;\n let storeHash = options.storeHash;\n let accessToken = options.accessToken;\n let channelId;\n let customerImpersonationToken = options.customerImpersonationToken;\n\n if (options.channelId) {\n channelId = parseInt(options.channelId, 10);\n }\n\n if (!pathExistsSync(options.projectDir)) {\n console.error(chalk.red(`Error: --projectDir ${options.projectDir} is not a valid path\\n`));\n process.exit(1);\n }\n\n if (options.projectName) {\n projectName = kebabCase(options.projectName);\n projectDir = join(options.projectDir, projectName);\n\n if (pathExistsSync(projectDir)) {\n console.error(chalk.red(`Error: ${projectDir} already exists\\n`));\n process.exit(1);\n }\n }\n\n if (!options.projectName) {\n const validateProjectName = (i: string) => {\n const formatted = kebabCase(i);\n\n if (!formatted) return 'Project name is required';\n\n const targetDir = join(options.projectDir, formatted);\n\n if (pathExistsSync(targetDir)) return `Destination '${targetDir}' already exists`;\n\n projectName = formatted;\n projectDir = targetDir;\n\n return true;\n };\n\n await input({\n message: 'What is the name of your project?',\n default: 'my-catalyst-app',\n validate: validateProjectName,\n });\n }\n\n if (!options.storeHash || !options.accessToken) {\n const credentials = await login(bigcommerceAuthUrl);\n\n storeHash = credentials.storeHash;\n accessToken = credentials.accessToken;\n }\n\n if (!projectName) throw new Error('Something went wrong, projectName is not defined');\n if (!projectDir) throw new Error('Something went wrong, projectDir is not defined');\n\n if (!storeHash || !accessToken) {\n console.log(`\\nCreating '${projectName}' at '${projectDir}'\\n`);\n\n await cloneCatalyst({ projectDir, projectName, ghRef });\n\n console.log(`\\nUsing ${chalk.bold(packageManager)}\\n`);\n\n await installDependencies(projectDir, packageManager);\n\n console.log(\n [\n `\\n${chalk.green('Success!')} Created '${projectName}' at '${projectDir}'\\n`,\n `Next steps:`,\n chalk.yellow(`\\n- cd ${projectName} && cp .env.example .env.local`),\n chalk.yellow(`\\n- Populate .env.local with your BigCommerce API credentials\\n`),\n ].join('\\n'),\n );\n\n process.exit(0);\n }\n\n if (!channelId || !customerImpersonationToken) {\n const bc = new Https({ bigCommerceApiUrl: bigcommerceApiUrl, storeHash, accessToken });\n const availableChannels = await bc.channels('?available=true&type=storefront');\n const storeInfo = await bc.storeInformation();\n\n const canCreateChannel = checkStorefrontLimit(availableChannels, storeInfo);\n\n let shouldCreateChannel;\n\n if (canCreateChannel) {\n shouldCreateChannel = await select({\n message: 'Would you like to create a new channel?',\n choices: [\n { name: 'Yes', value: true },\n { name: 'No', value: false },\n ],\n });\n }\n\n if (shouldCreateChannel) {\n const newChannelName = await input({\n message: 'What would you like to name your new channel?',\n });\n\n const sampleDataApi = new Https({\n sampleDataApiUrl,\n storeHash,\n accessToken,\n });\n\n const {\n data: { id: createdChannelId, storefront_api_token: storefrontApiToken },\n } = await sampleDataApi.createChannel(newChannelName);\n\n channelId = createdChannelId;\n customerImpersonationToken = storefrontApiToken;\n\n /**\n * @todo prompt sample data API\n */\n }\n\n if (!shouldCreateChannel) {\n const channelSortOrder = ['catalyst', 'next', 'bigcommerce'];\n\n const existingChannel = await select({\n message: 'Which channel would you like to use?',\n choices: availableChannels.data\n .sort(\n (a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform),\n )\n .map((ch) => ({\n name: ch.name,\n value: ch,\n description: `Channel Platform: ${\n ch.platform === 'bigcommerce'\n ? 'Stencil'\n : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)\n }`,\n })),\n });\n\n channelId = existingChannel.id;\n\n const {\n data: { token },\n } = await bc.customerImpersonationToken(channelId);\n\n customerImpersonationToken = token;\n }\n }\n\n if (!channelId) throw new Error('Something went wrong, channelId is not defined');\n if (!customerImpersonationToken)\n throw new Error('Something went wrong, customerImpersonationToken is not defined');\n\n console.log(`\\nCreating '${projectName}' at '${projectDir}'\\n`);\n\n await cloneCatalyst({ projectDir, projectName, ghRef });\n\n writeEnv(projectDir, {\n channelId: channelId.toString(),\n storeHash,\n accessToken,\n customerImpersonationToken,\n });\n\n console.log(`\\nUsing ${chalk.bold(packageManager)}\\n`);\n\n await installDependencies(projectDir, packageManager);\n\n await spinner(exec(`${packageManager} run codegen`, { cwd: projectDir }), {\n text: 'Generating GraphQL types...',\n successText: 'GraphQL types generated successfully',\n failText: (err) => chalk.red(`Failed to generate GraphQL types: ${err.message}`),\n });\n\n await spinner(exec(`${packageManager} run lint -- --fix`, { cwd: projectDir }), {\n text: 'Linting to validate generated types...',\n successText: 'GraphQL types validated successfully',\n failText: (err) => chalk.red(`Failed to validate GraphQL types: ${err.message}`),\n });\n\n console.log(\n `\\n${chalk.green('Success!')} Created '${projectName}' at '${projectDir}'\\n`,\n '\\nNext steps:\\n',\n chalk.yellow(`\\ncd ${projectName} && ${packageManager} run dev\\n`),\n );\n};\n","import chalk from 'chalk';\n\nimport { type BigCommerceChannelsV3Response, type BigCommerceStoreInfo } from './https';\n\nexport const checkStorefrontLimit = (\n channels: BigCommerceChannelsV3Response,\n storeInfo: BigCommerceStoreInfo,\n) => {\n const { data: availableChannels } = channels;\n const { features } = storeInfo;\n\n if (availableChannels.length >= features.storefront_limits.total_including_inactive) {\n console.error(\n chalk.yellow(\n `You have reached the maximum number of storefronts allowed for your plan. Please select an existing channel below, purchase additional storefront seats in your BigCommerce Control Panel, or contact BigCommerce Support: ${chalk.cyan(\n 'https://support.bigcommerce.com',\n )}\\n`,\n ),\n );\n\n return false;\n }\n\n const activeChannels = availableChannels.filter((channel) => channel.status === 'active');\n\n if (activeChannels.length >= features.storefront_limits.active) {\n console.error(\n chalk.yellow(\n 'You have reached the maximum number of active storefronts allowed for your plan. Please select an existing channel below, de-activate an active channel, or purchase additional storefront seats in your BigCommerce Control Panel.\\n',\n ),\n );\n\n return false;\n }\n\n return true;\n};\n","import chalk from 'chalk';\nimport { copySync, readJsonSync, removeSync, writeJsonSync } from 'fs-extra/esm';\nimport { downloadTemplate } from 'giget';\nimport merge from 'lodash.merge';\nimport { join } from 'path';\nimport * as z from 'zod';\n\nimport { spinner } from './spinner';\n\nexport const cloneCatalyst = async ({\n projectDir,\n projectName,\n ghRef = 'main',\n}: {\n projectDir: string;\n projectName: string;\n ghRef?: string;\n}) => {\n await spinner(\n downloadTemplate(`github:bigcommerce/catalyst/apps/core#${ghRef}`, {\n dir: projectDir,\n offline: false,\n }),\n {\n text: 'Cloning Catalyst template...',\n successText: 'Catalyst template cloned successfully',\n failText: (err) => chalk.red(`Failed to clone Catalyst template: ${err.message}`),\n },\n );\n\n await spinner(\n downloadTemplate(`github:bigcommerce/catalyst/packages/components#${ghRef}`, {\n dir: join(projectDir, 'tmp'),\n offline: false,\n }),\n {\n text: 'Cloning Catalyst components...',\n successText: 'Catalyst components cloned successfully',\n failText: (err) => chalk.red(`Failed to clone Catalyst components: ${err.message}`),\n },\n );\n\n copySync(join(projectDir, 'tmp/src/components'), join(projectDir, 'components', 'ui'));\n copySync(join(projectDir, 'tmp/tailwind.config.js'), join(projectDir, 'tailwind.config.js'));\n\n const packageJson = z\n .object({\n private: z.boolean().optional(),\n exports: z.object({}).passthrough().optional(),\n sideEffects: z.boolean().optional(),\n peerDependencies: z.object({}).passthrough().optional(),\n dependencies: z\n .object({\n '@bigcommerce/components': z.string().optional(),\n '@bigcommerce/catalyst-client': z.string().optional(),\n })\n .passthrough(),\n devDependencies: z\n .object({\n react: z.string().optional(),\n 'react-dom': z.string().optional(),\n '@bigcommerce/eslint-config-catalyst': z.string().optional(),\n })\n .passthrough(),\n })\n .passthrough()\n .parse(\n merge(\n {},\n readJsonSync(join(projectDir, 'tmp/package.json')),\n readJsonSync(join(projectDir, 'package.json')),\n { name: projectName, description: '' },\n ),\n );\n\n delete packageJson.private;\n delete packageJson.exports;\n delete packageJson.sideEffects;\n delete packageJson.peerDependencies; // will go away\n delete packageJson.dependencies['@bigcommerce/components']; // will go away\n delete packageJson.devDependencies.react; // will go away\n delete packageJson.devDependencies['react-dom']; // will go away\n\n packageJson.dependencies['@bigcommerce/catalyst-client'] = `^0.1.1`;\n packageJson.devDependencies['@bigcommerce/eslint-config-catalyst'] = `^0.1.0`;\n\n writeJsonSync(join(projectDir, 'package.json'), packageJson, { spaces: 2 });\n\n const tsConfigJson = z\n .object({\n compilerOptions: z\n .object({\n declaration: z.boolean().optional(),\n declarationMap: z.boolean().optional(),\n paths: z\n .object({\n '@bigcommerce/components/*': z.string().array().optional(),\n })\n .passthrough(),\n })\n .passthrough(),\n })\n .passthrough()\n .parse(\n merge(\n {},\n readJsonSync(join(projectDir, 'tmp/tsconfig.json')),\n readJsonSync(join(projectDir, 'tsconfig.json')),\n ),\n );\n\n delete tsConfigJson.compilerOptions.declaration;\n delete tsConfigJson.compilerOptions.declarationMap;\n\n tsConfigJson.compilerOptions.paths['@bigcommerce/components/*'] = ['./components/ui/*'];\n\n writeJsonSync(join(projectDir, 'tsconfig.json'), tsConfigJson, { spaces: 2 });\n\n removeSync(join(projectDir, 'tmp'));\n};\n","import { type Ora, oraPromise, type PromiseOptions } from 'ora';\n\nconst spinnerIcon = 'triangle' as const;\n\nexport const spinner = async <T>(\n action: PromiseLike<T> | ((spinner: Ora) => PromiseLike<T>),\n oraOpts: PromiseOptions<T>,\n) => {\n return oraPromise(action, {\n spinner: spinnerIcon,\n ...oraOpts,\n }).catch(() => process.exit(1));\n};\n","/* eslint-disable @typescript-eslint/unified-signatures */\n\nimport chalk from 'chalk';\nimport { z } from 'zod';\n\nimport { parse } from './parse';\n\ninterface BigCommerceRestApiConfig {\n bigCommerceApiUrl: string;\n storeHash: string;\n accessToken: string;\n}\n\ninterface SampleDataApiConfig {\n sampleDataApiUrl: string;\n storeHash: string;\n accessToken: string;\n}\n\ninterface DeviceOAuthConfig {\n bigCommerceAuthUrl: string;\n}\n\ninterface HttpsConfig {\n bigCommerceApiUrl?: string;\n bigCommerceAuthUrl?: string;\n sampleDataApiUrl?: string;\n storeHash?: string;\n accessToken?: string;\n}\n\nconst BigCommerceStoreInfo = z.object({\n features: z.object({\n storefront_limits: z.object({\n active: z.number(),\n total_including_inactive: z.number(),\n }),\n }),\n});\n\nexport type BigCommerceStoreInfo = z.infer<typeof BigCommerceStoreInfo>;\n\nconst BigCommerceV3ApiResponseSchema = <T>(schema: z.ZodType<T>) =>\n z.object({\n data: schema,\n meta: z.object({}),\n });\n\nconst BigCommerceChannelsV3ResponseSchema = BigCommerceV3ApiResponseSchema(\n z.array(\n z.object({\n id: z.number(),\n name: z.string(),\n status: z.string(),\n platform: z.string(),\n }),\n ),\n);\n\nexport type BigCommerceChannelsV3Response = z.infer<typeof BigCommerceChannelsV3ResponseSchema>;\n\nexport class Https {\n DEVICE_OAUTH_CLIENT_ID = 'acse0vvawm9r1n0evag4b8e1ea1fo90';\n\n bigCommerceApiUrl: string;\n bigCommerceAuthUrl: string;\n sampleDataApiUrl: string;\n storeHash: string;\n accessToken: string;\n\n constructor({ bigCommerceApiUrl, storeHash, accessToken }: BigCommerceRestApiConfig);\n constructor({ sampleDataApiUrl, storeHash, accessToken }: SampleDataApiConfig);\n constructor({ bigCommerceAuthUrl }: DeviceOAuthConfig);\n constructor({\n bigCommerceApiUrl,\n bigCommerceAuthUrl,\n sampleDataApiUrl,\n storeHash,\n accessToken,\n }: HttpsConfig) {\n this.bigCommerceApiUrl = bigCommerceApiUrl || '';\n this.bigCommerceAuthUrl = bigCommerceAuthUrl || '';\n this.sampleDataApiUrl = sampleDataApiUrl || '';\n this.storeHash = storeHash || '';\n this.accessToken = accessToken || '';\n }\n\n auth(path: string, opts: RequestInit = {}) {\n if (!this.bigCommerceAuthUrl) {\n throw new Error('bigCommerceAuthUrl is required to make API requests');\n }\n\n const { headers = {}, ...rest } = opts;\n\n const options = {\n method: 'POST',\n headers: {\n ...headers,\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n ...rest,\n };\n\n return fetch(`${this.bigCommerceAuthUrl}${path}`, options);\n }\n\n async getDeviceCode() {\n const response = await this.auth('/device/token', {\n body: JSON.stringify({\n scopes: [\n 'store_v2_content',\n 'store_v2_information',\n 'store_v2_products',\n 'store_cart',\n 'store_sites',\n 'store_channel_settings',\n 'store_storefront_api_customer_impersonation',\n ].join(' '),\n client_id: this.DEVICE_OAUTH_CLIENT_ID,\n }),\n });\n\n if (!response.ok) {\n console.error(\n chalk.red(`\\nPOST /device/token failed: ${response.status} ${response.statusText}\\n`),\n );\n process.exit(1);\n }\n\n const DeviceCodeSchema = z.object({\n device_code: z.string(),\n user_code: z.string(),\n verification_uri: z.string(),\n expires_in: z.number(),\n interval: z.number(),\n });\n\n return parse(await response.json(), DeviceCodeSchema);\n }\n\n async checkDeviceCode(deviceCode: string) {\n const response = await this.auth('/device/token', {\n body: JSON.stringify({\n device_code: deviceCode,\n client_id: this.DEVICE_OAUTH_CLIENT_ID,\n }),\n });\n\n if (response.status !== 200) {\n throw new Error('Device code not yet verified');\n }\n\n const DeviceCodeSuccessSchema = z.object({\n access_token: z.string(),\n store_hash: z.string(),\n context: z.string(),\n api_uri: z.string().url(),\n });\n\n return parse(await response.json(), DeviceCodeSuccessSchema);\n }\n\n api(path: string, opts: RequestInit = {}) {\n if (!this.bigCommerceApiUrl || !this.storeHash || !this.accessToken) {\n throw new Error(\n 'bigCommerceApiUrl, storeHash, and accessToken are required to make API requests',\n );\n }\n\n const { headers = {}, ...rest } = opts;\n\n const options = {\n headers: {\n ...headers,\n Accept: 'application/json',\n 'X-Auth-Token': this.accessToken,\n },\n ...rest,\n };\n\n return fetch(`${this.bigCommerceApiUrl}/stores/${this.storeHash}${path}`, options);\n }\n\n async storeInformation() {\n const res = await this.api('/v2/store');\n\n if (!res.ok) {\n console.error(chalk.red(`\\nGET /v2/store failed: ${res.status} ${res.statusText}\\n`));\n process.exit(1);\n }\n\n return parse(await res.json(), BigCommerceStoreInfo);\n }\n\n async channels(query = '') {\n const res = await this.api(`/v3/channels${query}`);\n\n if (!res.ok) {\n console.error(chalk.red(`\\nGET /v3/channels failed: ${res.status} ${res.statusText}\\n`));\n process.exit(1);\n }\n\n return parse(await res.json(), BigCommerceChannelsV3ResponseSchema);\n }\n\n async customerImpersonationToken(channelId: number) {\n const res = await this.api('/v3/storefront/api-token-customer-impersonation', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ expires_at: 2147483647, channel_id: channelId }),\n });\n\n if (!res.ok) {\n console.error(\n chalk.red(\n `\\nPOST /v3/storefront/api-token-customer-impersonation failed: ${res.status} ${res.statusText}\\n`,\n ),\n );\n process.exit(1);\n }\n\n const BigCommerceCustomerImpersonationTokenSchema = z.object({\n data: z.object({\n token: z.string(),\n }),\n });\n\n return parse(await res.json(), BigCommerceCustomerImpersonationTokenSchema);\n }\n\n sampleDataApi(path: string, opts: RequestInit = {}) {\n if (!this.sampleDataApiUrl || !this.storeHash || !this.accessToken) {\n throw new Error(\n 'sampleDataApiUrl, storeHash, and accessToken are required to make API requests',\n );\n }\n\n const { headers = {}, ...rest } = opts;\n\n const options = {\n method: 'POST',\n headers: {\n ...headers,\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'X-Auth-Token': this.accessToken,\n },\n ...rest,\n };\n\n return fetch(`${this.sampleDataApiUrl}/stores/${this.storeHash}${path}`, options);\n }\n\n async createChannel(channelName: string) {\n const res = await this.sampleDataApi('/v3/channels/catalyst', {\n body: JSON.stringify({ name: channelName }),\n });\n\n if (!res.ok) {\n console.error(\n chalk.red(`\\nPOST /v3/channels/catalyst failed: ${res.status} ${res.statusText}\\n`),\n );\n process.exit(1);\n }\n\n const SampleDataChannelCreateSchema = z.object({\n data: z.object({\n id: z.number(),\n name: z.string().min(1),\n storefront_api_token: z.string(),\n }),\n });\n\n return parse(await res.json(), SampleDataChannelCreateSchema);\n }\n}\n","import * as z from 'zod';\nimport { fromZodError } from 'zod-validation-error';\n\nexport const parse = <T>(data: unknown, schema: z.Schema<T>): T => {\n try {\n return schema.parse(data);\n } catch (error) {\n if (error instanceof z.ZodError) {\n console.error(fromZodError(error).toString());\n }\n\n process.exit(1);\n }\n};\n","import chalk from 'chalk';\nimport { installDependencies as installDeps } from 'nypm';\n\nimport { type PackageManager } from './pm';\nimport { spinner } from './spinner';\n\nexport const installDependencies = async (projectDir: string, packageManager: PackageManager) =>\n spinner(installDeps({ cwd: projectDir, silent: true, packageManager }), {\n text: `Installing dependencies. This could take a minute...`,\n successText: `Dependencies installed successfully`,\n failText: (err) => chalk.red(`Failed to install dependencies: ${err.message}`),\n });\n","/* eslint-disable no-await-in-loop */\n\nimport { select } from '@inquirer/prompts';\nimport chalk from 'chalk';\n\nimport { Https } from './https';\nimport { spinner } from './spinner';\n\nconst poll = async (auth: Https, deviceCode: string, interval: number, expiresIn: number) => {\n const intervalMs = interval * 1000;\n const expiresAtMs = expiresIn * 1000;\n const retries = expiresAtMs / intervalMs;\n\n for (let i = 0; i < retries; i += 1) {\n try {\n return await auth.checkDeviceCode(deviceCode);\n } catch (err) {\n // noop\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n\n console.error(chalk.red('\\nDevice code expired. Please try again.\\n'));\n process.exit(1);\n};\n\nexport const login = async (\n bigCommerceAuthUrl: string,\n storeHash?: string,\n accessToken?: string,\n) => {\n if (storeHash && accessToken) {\n return { storeHash, accessToken };\n }\n\n const shouldLogin = await select({\n message: 'Would you like to connect to a BigCommerce store?',\n choices: [\n { name: 'Yes', value: true },\n { name: 'No', value: false },\n ],\n });\n\n if (!shouldLogin) {\n return { storeHash, accessToken };\n }\n\n const auth = new Https({ bigCommerceAuthUrl });\n\n const deviceCode = await auth.getDeviceCode();\n\n console.log(\n [\n `\\nPlease visit ${chalk.cyan(deviceCode.verification_uri)} and enter the code: ${chalk.yellow(\n deviceCode.user_code,\n )}\\n`,\n `The code will expire in ${chalk.yellow(`${deviceCode.expires_in / 60} minutes`)}\\n`,\n ].join('\\n'),\n );\n\n const { store_hash, access_token } = await spinner(\n poll(auth, deviceCode.device_code, deviceCode.interval, deviceCode.expires_in),\n {\n text: 'Waiting for device code to be authorized',\n successText: 'Device code authorized\\n',\n failText: 'Device code expired\\n',\n },\n );\n\n return {\n storeHash: store_hash,\n accessToken: access_token,\n };\n};\n","import { randomBytes } from 'crypto';\nimport { outputFileSync } from 'fs-extra/esm';\nimport { join } from 'path';\n\nexport const writeEnv = (\n projectDir: string,\n {\n channelId,\n storeHash,\n accessToken,\n customerImpersonationToken,\n }: {\n channelId: string;\n storeHash: string;\n accessToken: string;\n customerImpersonationToken: string;\n },\n) => {\n /**\n * @todo silence request logs by default\n */\n outputFileSync(\n join(projectDir, '.env.local'),\n [\n `AUTH_SECRET=${randomBytes(32).toString('hex')}`,\n `BIGCOMMERCE_STORE_HASH=${storeHash}`,\n `BIGCOMMERCE_CHANNEL_ID=${channelId}`,\n `BIGCOMMERCE_ACCESS_TOKEN=${accessToken}`,\n `BIGCOMMERCE_CUSTOMER_IMPERSONATION_TOKEN=${customerImpersonationToken}`,\n `CLIENT_LOGGER=false`,\n `ENABLE_ADMIN_ROUTE=true`,\n `NEXT_PUBLIC_DEFAULT_REVALIDATE_TARGET=3600`,\n ].join('\\n'),\n );\n};\n","import { input, select } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport * as z from 'zod';\n\nimport { type InitCommandOptions } from '../index';\nimport { checkStorefrontLimit } from '../utils/check-storefront-limit';\nimport { Https } from '../utils/https';\nimport { login } from '../utils/login';\nimport { parse } from '../utils/parse';\nimport { writeEnv } from '../utils/write-env';\n\nexport const init = async (options: InitCommandOptions) => {\n const projectDir = process.cwd();\n\n const URLSchema = z.string().url();\n const sampleDataApiUrl = parse(options.sampleDataApiUrl, URLSchema);\n const bigCommerceApiUrl = `https://api.${options.bigcommerceHostname}`;\n const bigCommerceAuthUrl = `https://login.${options.bigcommerceHostname}`;\n\n let storeHash = options.storeHash;\n let accessToken = options.accessToken;\n let channelId;\n let customerImpersonationToken;\n\n if (!options.storeHash || !options.accessToken) {\n const credentials = await login(bigCommerceAuthUrl);\n\n storeHash = credentials.storeHash;\n accessToken = credentials.accessToken;\n }\n\n if (!storeHash || !accessToken) {\n console.log(\n chalk.yellow('\\nYou must authenticate with a store to overwrite your local environment.\\n'),\n );\n\n process.exit(1);\n }\n\n const bc = new Https({ bigCommerceApiUrl, storeHash, accessToken });\n\n const availableChannels = await bc.channels('?available=true&type=storefront');\n const storeInfo = await bc.storeInformation();\n\n const canCreateChannel = checkStorefrontLimit(availableChannels, storeInfo);\n\n let shouldCreateChannel;\n\n if (canCreateChannel) {\n shouldCreateChannel = await select({\n message: 'Would you like to create a new channel?',\n choices: [\n { name: 'Yes', value: true },\n { name: 'No', value: false },\n ],\n });\n }\n\n if (shouldCreateChannel) {\n const newChannelName = await input({\n message: 'What would you like to name your new channel?',\n });\n\n const sampleDataApi = new Https({\n sampleDataApiUrl,\n storeHash,\n accessToken,\n });\n\n const {\n data: { id: createdChannelId, storefront_api_token: storefrontApiToken },\n } = await sampleDataApi.createChannel(newChannelName);\n\n channelId = createdChannelId;\n customerImpersonationToken = storefrontApiToken;\n\n /**\n * @todo prompt sample data API\n */\n }\n\n if (!shouldCreateChannel) {\n const channelSortOrder = ['catalyst', 'next', 'bigcommerce'];\n\n const existingChannel = await select({\n message: 'Which channel would you like to use?',\n choices: availableChannels.data\n .sort((a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform))\n .map((ch) => ({\n name: ch.name,\n value: ch,\n description: `Channel Platform: ${\n ch.platform === 'bigcommerce'\n ? 'Stencil'\n : ch.platform.charAt(0).toUpperCase() + ch.platform.slice(1)\n }`,\n })),\n });\n\n channelId = existingChannel.id;\n\n const {\n data: { token },\n } = await bc.customerImpersonationToken(channelId);\n\n customerImpersonationToken = token;\n }\n\n if (!channelId) throw new Error('Something went wrong, channelId is not defined');\n if (!customerImpersonationToken)\n throw new Error('Something went wrong, customerImpersonationToken is not defined');\n\n writeEnv(projectDir, {\n channelId: channelId.toString(),\n storeHash,\n accessToken,\n customerImpersonationToken,\n });\n};\n","/**\n * The MIT License (MIT)\n *\n * Copyright (c) 2024 Vercel, Inc.\n *\n * Sourced and modified from:\n * https://github.com/vercel/next.js/blob/771e29cb719b382e92d89cac11fbfcb818f5f628/packages/create-next-app/helpers/get-pkg-manager.ts\n *\n * License:\n * https://github.com/vercel/next.js/blob/771e29cb719b382e92d89cac11fbfcb818f5f628/license.md\n */\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn';\n\nexport const packageManagerChoices: PackageManager[] = ['npm', 'pnpm', 'yarn'];\n\nexport function getPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent || '';\n\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n }\n\n if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n }\n\n return 'npm';\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,SAAS,cAAc;AAChC,OAAOA,YAAW;AAClB,SAAS,iBAAiB;;;ACJ1B;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,EACP,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,SAAW;AAAA,IACT,KAAO;AAAA,IACP,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,OAAS;AAAA,EACX;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,cAAgB;AAAA,IACd,+BAA+B;AAAA,IAC/B,qBAAqB;AAAA,IACrB,OAAS;AAAA,IACT,WAAa;AAAA,IACb,YAAY;AAAA,IACZ,OAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,KAAO;AAAA,IACP,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,QAAU;AAAA,IACV,KAAO;AAAA,IACP,wBAAwB;AAAA,EAC1B;AAAA,EACA,iBAAmB;AAAA,IACjB,8BAA8B;AAAA,IAC9B,uCAAuC;AAAA,IACvC,aAAa;AAAA,IACb,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,2BAA2B;AAAA,IAC3B,uBAAuB;AAAA,IACvB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,YAAc;AAAA,EAChB;AACF;;;ACpDA,SAAS,OAAO,UAAAC,eAAc;AAC9B,OAAOC,YAAW;AAClB,SAAS,QAAQ,oBAAoB;AACrC,SAAS,sBAAsB;AAC/B,OAAO,eAAe;AACtB,SAAS,QAAAC,aAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,KAAAC,UAAS;;;ACPlB,OAAO,WAAW;AAIX,IAAM,uBAAuB,CAClC,UACA,cACG;AACH,QAAM,EAAE,MAAM,kBAAkB,IAAI;AACpC,QAAM,EAAE,SAAS,IAAI;AAErB,MAAI,kBAAkB,UAAU,SAAS,kBAAkB,0BAA0B;AACnF,YAAQ;AAAA,MACN,MAAM;AAAA,QACJ,8NAA8N,MAAM;AAAA,UAClO;AAAA,QACF;AAAA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,kBAAkB,OAAO,CAAC,YAAY,QAAQ,WAAW,QAAQ;AAExF,MAAI,eAAe,UAAU,SAAS,kBAAkB,QAAQ;AAC9D,YAAQ;AAAA,MACN,MAAM;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ACpCA,OAAOC,YAAW;AAClB,SAAS,UAAU,cAAc,YAAY,qBAAqB;AAClE,SAAS,wBAAwB;AACjC,OAAO,WAAW;AAClB,SAAS,YAAY;AACrB,YAAY,OAAO;;;ACLnB,SAAmB,kBAAuC;AAE1D,IAAM,cAAc;AAEb,IAAM,UAAU,CACrB,QACA,YACG;AACH,SAAO,WAAW,QAAQ;AAAA,IACxB,SAAS;AAAA,KACN,QACJ,EAAE,MAAM,MAAM,QAAQ,KAAK,CAAC,CAAC;AAChC;;;ADHO,IAAM,gBAAgB,CAAO,OAQ9B,iBAR8B,KAQ9B,WAR8B;AAAA,EAClC;AAAA,EACA;AAAA,EACA,QAAQ;AACV,GAIM;AACJ,QAAM;AAAA,IACJ,iBAAiB,yCAAyC,SAAS;AAAA,MACjE,KAAK;AAAA,MACL,SAAS;AAAA,IACX,CAAC;AAAA,IACD;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU,CAAC,QAAQC,OAAM,IAAI,sCAAsC,IAAI,SAAS;AAAA,IAClF;AAAA,EACF;AAEA,QAAM;AAAA,IACJ,iBAAiB,mDAAmD,SAAS;AAAA,MAC3E,KAAK,KAAK,YAAY,KAAK;AAAA,MAC3B,SAAS;AAAA,IACX,CAAC;AAAA,IACD;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU,CAAC,QAAQA,OAAM,IAAI,wCAAwC,IAAI,SAAS;AAAA,IACpF;AAAA,EACF;AAEA,WAAS,KAAK,YAAY,oBAAoB,GAAG,KAAK,YAAY,cAAc,IAAI,CAAC;AACrF,WAAS,KAAK,YAAY,wBAAwB,GAAG,KAAK,YAAY,oBAAoB,CAAC;AAE3F,QAAM,cACH,SAAO;AAAA,IACN,SAAW,UAAQ,EAAE,SAAS;AAAA,IAC9B,SAAW,SAAO,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS;AAAA,IAC7C,aAAe,UAAQ,EAAE,SAAS;AAAA,IAClC,kBAAoB,SAAO,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS;AAAA,IACtD,cACG,SAAO;AAAA,MACN,2BAA6B,SAAO,EAAE,SAAS;AAAA,MAC/C,gCAAkC,SAAO,EAAE,SAAS;AAAA,IACtD,CAAC,EACA,YAAY;AAAA,IACf,iBACG,SAAO;AAAA,MACN,OAAS,SAAO,EAAE,SAAS;AAAA,MAC3B,aAAe,SAAO,EAAE,SAAS;AAAA,MACjC,uCAAyC,SAAO,EAAE,SAAS;AAAA,IAC7D,CAAC,EACA,YAAY;AAAA,EACjB,CAAC,EACA,YAAY,EACZ;AAAA,IACC;AAAA,MACE,CAAC;AAAA,MACD,aAAa,KAAK,YAAY,kBAAkB,CAAC;AAAA,MACjD,aAAa,KAAK,YAAY,cAAc,CAAC;AAAA,MAC7C,EAAE,MAAM,aAAa,aAAa,GAAG;AAAA,IACvC;AAAA,EACF;AAEF,SAAO,YAAY;AACnB,SAAO,YAAY;AACnB,SAAO,YAAY;AACnB,SAAO,YAAY;AACnB,SAAO,YAAY,aAAa,yBAAyB;AACzD,SAAO,YAAY,gBAAgB;AACnC,SAAO,YAAY,gBAAgB,WAAW;AAE9C,cAAY,aAAa,8BAA8B,IAAI;AAC3D,cAAY,gBAAgB,qCAAqC,IAAI;AAErE,gBAAc,KAAK,YAAY,cAAc,GAAG,aAAa,EAAE,QAAQ,EAAE,CAAC;AAE1E,QAAM,eACH,SAAO;AAAA,IACN,iBACG,SAAO;AAAA,MACN,aAAe,UAAQ,EAAE,SAAS;AAAA,MAClC,gBAAkB,UAAQ,EAAE,SAAS;AAAA,MACrC,OACG,SAAO;AAAA,QACN,6BAA+B,SAAO,EAAE,MAAM,EAAE,SAAS;AAAA,MAC3D,CAAC,EACA,YAAY;AAAA,IACjB,CAAC,EACA,YAAY;AAAA,EACjB,CAAC,EACA,YAAY,EACZ;AAAA,IACC;AAAA,MACE,CAAC;AAAA,MACD,aAAa,KAAK,YAAY,mBAAmB,CAAC;AAAA,MAClD,aAAa,KAAK,YAAY,eAAe,CAAC;AAAA,IAChD;AAAA,EACF;AAEF,SAAO,aAAa,gBAAgB;AACpC,SAAO,aAAa,gBAAgB;AAEpC,eAAa,gBAAgB,MAAM,2BAA2B,IAAI,CAAC,mBAAmB;AAEtF,gBAAc,KAAK,YAAY,eAAe,GAAG,cAAc,EAAE,QAAQ,EAAE,CAAC;AAE5E,aAAW,KAAK,YAAY,KAAK,CAAC;AACpC;;;AErHA,OAAOC,YAAW;AAClB,SAAS,KAAAC,UAAS;;;ACHlB,YAAYC,QAAO;AACnB,SAAS,oBAAoB;AAEtB,IAAM,QAAQ,CAAI,MAAe,WAA2B;AACjE,MAAI;AACF,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B,SAAS,OAAP;AACA,QAAI,iBAAmB,aAAU;AAC/B,cAAQ,MAAM,aAAa,KAAK,EAAE,SAAS,CAAC;AAAA,IAC9C;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;ADkBA,IAAM,uBAAuBC,GAAE,OAAO;AAAA,EACpC,UAAUA,GAAE,OAAO;AAAA,IACjB,mBAAmBA,GAAE,OAAO;AAAA,MAC1B,QAAQA,GAAE,OAAO;AAAA,MACjB,0BAA0BA,GAAE,OAAO;AAAA,IACrC,CAAC;AAAA,EACH,CAAC;AACH,CAAC;AAID,IAAM,iCAAiC,CAAI,WACzCA,GAAE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAMA,GAAE,OAAO,CAAC,CAAC;AACnB,CAAC;AAEH,IAAM,sCAAsC;AAAA,EAC1CA,GAAE;AAAA,IACAA,GAAE,OAAO;AAAA,MACP,IAAIA,GAAE,OAAO;AAAA,MACb,MAAMA,GAAE,OAAO;AAAA,MACf,QAAQA,GAAE,OAAO;AAAA,MACjB,UAAUA,GAAE,OAAO;AAAA,IACrB,CAAC;AAAA,EACH;AACF;AAIO,IAAM,QAAN,MAAY;AAAA,EAYjB,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAgB;AAjBhB,kCAAyB;AAkBvB,SAAK,oBAAoB,qBAAqB;AAC9C,SAAK,qBAAqB,sBAAsB;AAChD,SAAK,mBAAmB,oBAAoB;AAC5C,SAAK,YAAY,aAAa;AAC9B,SAAK,cAAc,eAAe;AAAA,EACpC;AAAA,EAEA,KAAK,MAAc,OAAoB,CAAC,GAAG;AACzC,QAAI,CAAC,KAAK,oBAAoB;AAC5B,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AAEA,UAAkC,WAA1B,YAAU,CAAC,EA5FvB,IA4FsC,IAAT,iBAAS,IAAT,CAAjB;AAER,UAAM,UAAU;AAAA,MACd,QAAQ;AAAA,MACR,SAAS,iCACJ,UADI;AAAA,QAEP,QAAQ;AAAA,QACR,gBAAgB;AAAA,MAClB;AAAA,OACG;AAGL,WAAO,MAAM,GAAG,KAAK,qBAAqB,QAAQ,OAAO;AAAA,EAC3D;AAAA,EAEM,gBAAgB;AAAA;AACpB,YAAM,WAAW,MAAM,KAAK,KAAK,iBAAiB;AAAA,QAChD,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,EAAE,KAAK,GAAG;AAAA,UACV,WAAW,KAAK;AAAA,QAClB,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ;AAAA,UACNC,OAAM,IAAI;AAAA,6BAAgC,SAAS,UAAU,SAAS;AAAA,CAAc;AAAA,QACtF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,mBAAmBD,GAAE,OAAO;AAAA,QAChC,aAAaA,GAAE,OAAO;AAAA,QACtB,WAAWA,GAAE,OAAO;AAAA,QACpB,kBAAkBA,GAAE,OAAO;AAAA,QAC3B,YAAYA,GAAE,OAAO;AAAA,QACrB,UAAUA,GAAE,OAAO;AAAA,MACrB,CAAC;AAED,aAAO,MAAM,MAAM,SAAS,KAAK,GAAG,gBAAgB;AAAA,IACtD;AAAA;AAAA,EAEM,gBAAgB,YAAoB;AAAA;AACxC,YAAM,WAAW,MAAM,KAAK,KAAK,iBAAiB;AAAA,QAChD,MAAM,KAAK,UAAU;AAAA,UACnB,aAAa;AAAA,UACb,WAAW,KAAK;AAAA,QAClB,CAAC;AAAA,MACH,CAAC;AAED,UAAI,SAAS,WAAW,KAAK;AAC3B,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AAEA,YAAM,0BAA0BA,GAAE,OAAO;AAAA,QACvC,cAAcA,GAAE,OAAO;AAAA,QACvB,YAAYA,GAAE,OAAO;AAAA,QACrB,SAASA,GAAE,OAAO;AAAA,QAClB,SAASA,GAAE,OAAO,EAAE,IAAI;AAAA,MAC1B,CAAC;AAED,aAAO,MAAM,MAAM,SAAS,KAAK,GAAG,uBAAuB;AAAA,IAC7D;AAAA;AAAA,EAEA,IAAI,MAAc,OAAoB,CAAC,GAAG;AACxC,QAAI,CAAC,KAAK,qBAAqB,CAAC,KAAK,aAAa,CAAC,KAAK,aAAa;AACnE,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAkC,WAA1B,YAAU,CAAC,EA1KvB,IA0KsC,IAAT,iBAAS,IAAT,CAAjB;AAER,UAAM,UAAU;AAAA,MACd,SAAS,iCACJ,UADI;AAAA,QAEP,QAAQ;AAAA,QACR,gBAAgB,KAAK;AAAA,MACvB;AAAA,OACG;AAGL,WAAO,MAAM,GAAG,KAAK,4BAA4B,KAAK,YAAY,QAAQ,OAAO;AAAA,EACnF;AAAA,EAEM,mBAAmB;AAAA;AACvB,YAAM,MAAM,MAAM,KAAK,IAAI,WAAW;AAEtC,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ,MAAMC,OAAM,IAAI;AAAA,wBAA2B,IAAI,UAAU,IAAI;AAAA,CAAc,CAAC;AACpF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,aAAO,MAAM,MAAM,IAAI,KAAK,GAAG,oBAAoB;AAAA,IACrD;AAAA;AAAA,EAEM,SAAS,QAAQ,IAAI;AAAA;AACzB,YAAM,MAAM,MAAM,KAAK,IAAI,eAAe,OAAO;AAEjD,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ,MAAMA,OAAM,IAAI;AAAA,2BAA8B,IAAI,UAAU,IAAI;AAAA,CAAc,CAAC;AACvF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,aAAO,MAAM,MAAM,IAAI,KAAK,GAAG,mCAAmC;AAAA,IACpE;AAAA;AAAA,EAEM,2BAA2B,WAAmB;AAAA;AAClD,YAAM,MAAM,MAAM,KAAK,IAAI,mDAAmD;AAAA,QAC5E,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,YAAY,YAAY,YAAY,UAAU,CAAC;AAAA,MACxE,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ;AAAA,UACNA,OAAM;AAAA,YACJ;AAAA,+DAAkE,IAAI,UAAU,IAAI;AAAA;AAAA,UACtF;AAAA,QACF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,8CAA8CD,GAAE,OAAO;AAAA,QAC3D,MAAMA,GAAE,OAAO;AAAA,UACb,OAAOA,GAAE,OAAO;AAAA,QAClB,CAAC;AAAA,MACH,CAAC;AAED,aAAO,MAAM,MAAM,IAAI,KAAK,GAAG,2CAA2C;AAAA,IAC5E;AAAA;AAAA,EAEA,cAAc,MAAc,OAAoB,CAAC,GAAG;AAClD,QAAI,CAAC,KAAK,oBAAoB,CAAC,KAAK,aAAa,CAAC,KAAK,aAAa;AAClE,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAkC,WAA1B,YAAU,CAAC,EA9OvB,IA8OsC,IAAT,iBAAS,IAAT,CAAjB;AAER,UAAM,UAAU;AAAA,MACd,QAAQ;AAAA,MACR,SAAS,iCACJ,UADI;AAAA,QAEP,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,gBAAgB,KAAK;AAAA,MACvB;AAAA,OACG;AAGL,WAAO,MAAM,GAAG,KAAK,2BAA2B,KAAK,YAAY,QAAQ,OAAO;AAAA,EAClF;AAAA,EAEM,cAAc,aAAqB;AAAA;AACvC,YAAM,MAAM,MAAM,KAAK,cAAc,yBAAyB;AAAA,QAC5D,MAAM,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAAA,MAC5C,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,gBAAQ;AAAA,UACNC,OAAM,IAAI;AAAA,qCAAwC,IAAI,UAAU,IAAI;AAAA,CAAc;AAAA,QACpF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,gCAAgCD,GAAE,OAAO;AAAA,QAC7C,MAAMA,GAAE,OAAO;AAAA,UACb,IAAIA,GAAE,OAAO;AAAA,UACb,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,UACtB,sBAAsBA,GAAE,OAAO;AAAA,QACjC,CAAC;AAAA,MACH,CAAC;AAED,aAAO,MAAM,MAAM,IAAI,KAAK,GAAG,6BAA6B;AAAA,IAC9D;AAAA;AACF;;;AEpRA,OAAOE,YAAW;AAClB,SAAS,uBAAuB,mBAAmB;AAK5C,IAAM,sBAAsB,CAAO,YAAoB,mBAAgC;AAC5F,iBAAQ,YAAY,EAAE,KAAK,YAAY,QAAQ,MAAM,eAAe,CAAC,GAAG;AAAA,IACtE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU,CAAC,QAAQC,OAAM,IAAI,mCAAmC,IAAI,SAAS;AAAA,EAC/E,CAAC;AAAA;;;ACTH,SAAS,cAAc;AACvB,OAAOC,YAAW;AAKlB,IAAM,OAAO,CAAO,MAAa,YAAoB,UAAkB,cAAsB;AAC3F,QAAM,aAAa,WAAW;AAC9B,QAAM,cAAc,YAAY;AAChC,QAAM,UAAU,cAAc;AAE9B,WAAS,IAAI,GAAG,IAAI,SAAS,KAAK,GAAG;AACnC,QAAI;AACF,aAAO,MAAM,KAAK,gBAAgB,UAAU;AAAA,IAC9C,SAAS,KAAP;AAAA,IAEF;AAEA,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,UAAU,CAAC;AAAA,EAChE;AAEA,UAAQ,MAAMC,OAAM,IAAI,4CAA4C,CAAC;AACrE,UAAQ,KAAK,CAAC;AAChB;AAEO,IAAM,QAAQ,CACnB,oBACA,WACA,gBACG;AACH,MAAI,aAAa,aAAa;AAC5B,WAAO,EAAE,WAAW,YAAY;AAAA,EAClC;AAEA,QAAM,cAAc,MAAM,OAAO;AAAA,IAC/B,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,OAAO,OAAO,KAAK;AAAA,MAC3B,EAAE,MAAM,MAAM,OAAO,MAAM;AAAA,IAC7B;AAAA,EACF,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO,EAAE,WAAW,YAAY;AAAA,EAClC;AAEA,QAAM,OAAO,IAAI,MAAM,EAAE,mBAAmB,CAAC;AAE7C,QAAM,aAAa,MAAM,KAAK,cAAc;AAE5C,UAAQ;AAAA,IACN;AAAA,MACE;AAAA,eAAkBA,OAAM,KAAK,WAAW,gBAAgB,yBAAyBA,OAAM;AAAA,QACrF,WAAW;AAAA,MACb;AAAA;AAAA,MACA,2BAA2BA,OAAM,OAAO,GAAG,WAAW,aAAa,YAAY;AAAA;AAAA,IACjF,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,QAAM,EAAE,YAAY,aAAa,IAAI,MAAM;AAAA,IACzC,KAAK,MAAM,WAAW,aAAa,WAAW,UAAU,WAAW,UAAU;AAAA,IAC7E;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,aAAa;AAAA,EACf;AACF;;;AC1EA,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,QAAAC,aAAY;AAEd,IAAM,WAAW,CACtB,YACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAMG;AAIH;AAAA,IACEA,MAAK,YAAY,YAAY;AAAA,IAC7B;AAAA,MACE,eAAe,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,MAC7C,0BAA0B;AAAA,MAC1B,0BAA0B;AAAA,MAC1B,4BAA4B;AAAA,MAC5B,4CAA4C;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;;;ARfA,IAAM,OAAO,UAAU,YAAY;AAE5B,IAAM,SAAS,CAAO,YAAkC;AAC7D,QAAM,EAAE,gBAAgB,MAAM,IAAI;AAElC,QAAM,YAAYC,GAAE,OAAO,EAAE,IAAI;AACjC,QAAM,mBAAmB,MAAM,QAAQ,kBAAkB,SAAS;AAClE,QAAM,oBAAoB,MAAM,eAAe,QAAQ,uBAAuB,SAAS;AACvF,QAAM,qBAAqB,MAAM,iBAAiB,QAAQ,uBAAuB,SAAS;AAE1F,MAAI;AACJ,MAAI;AACJ,MAAI,YAAY,QAAQ;AACxB,MAAI,cAAc,QAAQ;AAC1B,MAAI;AACJ,MAAI,6BAA6B,QAAQ;AAEzC,MAAI,QAAQ,WAAW;AACrB,gBAAY,SAAS,QAAQ,WAAW,EAAE;AAAA,EAC5C;AAEA,MAAI,CAAC,eAAe,QAAQ,UAAU,GAAG;AACvC,YAAQ,MAAMC,OAAM,IAAI,uBAAuB,QAAQ;AAAA,CAAkC,CAAC;AAC1F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,QAAQ,aAAa;AACvB,kBAAc,UAAU,QAAQ,WAAW;AAC3C,iBAAaC,MAAK,QAAQ,YAAY,WAAW;AAEjD,QAAI,eAAe,UAAU,GAAG;AAC9B,cAAQ,MAAMD,OAAM,IAAI,UAAU;AAAA,CAA6B,CAAC;AAChE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,aAAa;AACxB,UAAM,sBAAsB,CAAC,MAAc;AACzC,YAAM,YAAY,UAAU,CAAC;AAE7B,UAAI,CAAC;AAAW,eAAO;AAEvB,YAAM,YAAYC,MAAK,QAAQ,YAAY,SAAS;AAEpD,UAAI,eAAe,SAAS;AAAG,eAAO,gBAAgB;AAEtD,oBAAc;AACd,mBAAa;AAEb,aAAO;AAAA,IACT;AAEA,UAAM,MAAM;AAAA,MACV,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,QAAQ,aAAa,CAAC,QAAQ,aAAa;AAC9C,UAAM,cAAc,MAAM,MAAM,kBAAkB;AAElD,gBAAY,YAAY;AACxB,kBAAc,YAAY;AAAA,EAC5B;AAEA,MAAI,CAAC;AAAa,UAAM,IAAI,MAAM,kDAAkD;AACpF,MAAI,CAAC;AAAY,UAAM,IAAI,MAAM,iDAAiD;AAElF,MAAI,CAAC,aAAa,CAAC,aAAa;AAC9B,YAAQ,IAAI;AAAA,YAAe,oBAAoB;AAAA,CAAe;AAE9D,UAAM,cAAc,EAAE,YAAY,aAAa,MAAM,CAAC;AAEtD,YAAQ,IAAI;AAAA,QAAWD,OAAM,KAAK,cAAc;AAAA,CAAK;AAErD,UAAM,oBAAoB,YAAY,cAAc;AAEpD,YAAQ;AAAA,MACN;AAAA,QACE;AAAA,EAAKA,OAAM,MAAM,UAAU,cAAc,oBAAoB;AAAA;AAAA,QAC7D;AAAA,QACAA,OAAM,OAAO;AAAA,OAAU,2CAA2C;AAAA,QAClEA,OAAM,OAAO;AAAA;AAAA,CAAiE;AAAA,MAChF,EAAE,KAAK,IAAI;AAAA,IACb;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,aAAa,CAAC,4BAA4B;AAC7C,UAAM,KAAK,IAAI,MAAM,EAAE,mBAAmB,mBAAmB,WAAW,YAAY,CAAC;AACrF,UAAM,oBAAoB,MAAM,GAAG,SAAS,iCAAiC;AAC7E,UAAM,YAAY,MAAM,GAAG,iBAAiB;AAE5C,UAAM,mBAAmB,qBAAqB,mBAAmB,SAAS;AAE1E,QAAI;AAEJ,QAAI,kBAAkB;AACpB,4BAAsB,MAAME,QAAO;AAAA,QACjC,SAAS;AAAA,QACT,SAAS;AAAA,UACP,EAAE,MAAM,OAAO,OAAO,KAAK;AAAA,UAC3B,EAAE,MAAM,MAAM,OAAO,MAAM;AAAA,QAC7B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,qBAAqB;AACvB,YAAM,iBAAiB,MAAM,MAAM;AAAA,QACjC,SAAS;AAAA,MACX,CAAC;AAED,YAAM,gBAAgB,IAAI,MAAM;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM;AAAA,QACJ,MAAM,EAAE,IAAI,kBAAkB,sBAAsB,mBAAmB;AAAA,MACzE,IAAI,MAAM,cAAc,cAAc,cAAc;AAEpD,kBAAY;AACZ,mCAA6B;AAAA,IAK/B;AAEA,QAAI,CAAC,qBAAqB;AACxB,YAAM,mBAAmB,CAAC,YAAY,QAAQ,aAAa;AAE3D,YAAM,kBAAkB,MAAMA,QAAO;AAAA,QACnC,SAAS;AAAA,QACT,SAAS,kBAAkB,KACxB;AAAA,UACC,CAAC,GAAG,MAAM,iBAAiB,QAAQ,EAAE,QAAQ,IAAI,iBAAiB,QAAQ,EAAE,QAAQ;AAAA,QACtF,EACC,IAAI,CAAC,QAAQ;AAAA,UACZ,MAAM,GAAG;AAAA,UACT,OAAO;AAAA,UACP,aAAa,qBACX,GAAG,aAAa,gBACZ,YACA,GAAG,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,GAAG,SAAS,MAAM,CAAC;AAAA,QAEjE,EAAE;AAAA,MACN,CAAC;AAED,kBAAY,gBAAgB;AAE5B,YAAM;AAAA,QACJ,MAAM,EAAE,MAAM;AAAA,MAChB,IAAI,MAAM,GAAG,2BAA2B,SAAS;AAEjD,mCAA6B;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,CAAC;AAAW,UAAM,IAAI,MAAM,gDAAgD;AAChF,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,iEAAiE;AAEnF,UAAQ,IAAI;AAAA,YAAe,oBAAoB;AAAA,CAAe;AAE9D,QAAM,cAAc,EAAE,YAAY,aAAa,MAAM,CAAC;AAEtD,WAAS,YAAY;AAAA,IACnB,WAAW,UAAU,SAAS;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,UAAQ,IAAI;AAAA,QAAWF,OAAM,KAAK,cAAc;AAAA,CAAK;AAErD,QAAM,oBAAoB,YAAY,cAAc;AAEpD,QAAM,QAAQ,KAAK,GAAG,8BAA8B,EAAE,KAAK,WAAW,CAAC,GAAG;AAAA,IACxE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU,CAAC,QAAQA,OAAM,IAAI,qCAAqC,IAAI,SAAS;AAAA,EACjF,CAAC;AAED,QAAM,QAAQ,KAAK,GAAG,oCAAoC,EAAE,KAAK,WAAW,CAAC,GAAG;AAAA,IAC9E,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU,CAAC,QAAQA,OAAM,IAAI,qCAAqC,IAAI,SAAS;AAAA,EACjF,CAAC;AAED,UAAQ;AAAA,IACN;AAAA,EAAKA,OAAM,MAAM,UAAU,cAAc,oBAAoB;AAAA;AAAA,IAC7D;AAAA,IACAA,OAAM,OAAO;AAAA,KAAQ,kBAAkB;AAAA,CAA0B;AAAA,EACnE;AACF;;;ASzNA,SAAS,SAAAG,QAAO,UAAAC,eAAc;AAC9B,OAAOC,YAAW;AAClB,YAAYC,QAAO;AASZ,IAAM,OAAO,CAAO,YAAgC;AACzD,QAAM,aAAa,QAAQ,IAAI;AAE/B,QAAM,YAAc,UAAO,EAAE,IAAI;AACjC,QAAM,mBAAmB,MAAM,QAAQ,kBAAkB,SAAS;AAClE,QAAM,oBAAoB,eAAe,QAAQ;AACjD,QAAM,qBAAqB,iBAAiB,QAAQ;AAEpD,MAAI,YAAY,QAAQ;AACxB,MAAI,cAAc,QAAQ;AAC1B,MAAI;AACJ,MAAI;AAEJ,MAAI,CAAC,QAAQ,aAAa,CAAC,QAAQ,aAAa;AAC9C,UAAM,cAAc,MAAM,MAAM,kBAAkB;AAElD,gBAAY,YAAY;AACxB,kBAAc,YAAY;AAAA,EAC5B;AAEA,MAAI,CAAC,aAAa,CAAC,aAAa;AAC9B,YAAQ;AAAA,MACNC,OAAM,OAAO,6EAA6E;AAAA,IAC5F;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,KAAK,IAAI,MAAM,EAAE,mBAAmB,WAAW,YAAY,CAAC;AAElE,QAAM,oBAAoB,MAAM,GAAG,SAAS,iCAAiC;AAC7E,QAAM,YAAY,MAAM,GAAG,iBAAiB;AAE5C,QAAM,mBAAmB,qBAAqB,mBAAmB,SAAS;AAE1E,MAAI;AAEJ,MAAI,kBAAkB;AACpB,0BAAsB,MAAMC,QAAO;AAAA,MACjC,SAAS;AAAA,MACT,SAAS;AAAA,QACP,EAAE,MAAM,OAAO,OAAO,KAAK;AAAA,QAC3B,EAAE,MAAM,MAAM,OAAO,MAAM;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,qBAAqB;AACvB,UAAM,iBAAiB,MAAMC,OAAM;AAAA,MACjC,SAAS;AAAA,IACX,CAAC;AAED,UAAM,gBAAgB,IAAI,MAAM;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM;AAAA,MACJ,MAAM,EAAE,IAAI,kBAAkB,sBAAsB,mBAAmB;AAAA,IACzE,IAAI,MAAM,cAAc,cAAc,cAAc;AAEpD,gBAAY;AACZ,iCAA6B;AAAA,EAK/B;AAEA,MAAI,CAAC,qBAAqB;AACxB,UAAM,mBAAmB,CAAC,YAAY,QAAQ,aAAa;AAE3D,UAAM,kBAAkB,MAAMD,QAAO;AAAA,MACnC,SAAS;AAAA,MACT,SAAS,kBAAkB,KACxB,KAAK,CAAC,GAAG,MAAM,iBAAiB,QAAQ,EAAE,QAAQ,IAAI,iBAAiB,QAAQ,EAAE,QAAQ,CAAC,EAC1F,IAAI,CAAC,QAAQ;AAAA,QACZ,MAAM,GAAG;AAAA,QACT,OAAO;AAAA,QACP,aAAa,qBACX,GAAG,aAAa,gBACZ,YACA,GAAG,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,GAAG,SAAS,MAAM,CAAC;AAAA,MAEjE,EAAE;AAAA,IACN,CAAC;AAED,gBAAY,gBAAgB;AAE5B,UAAM;AAAA,MACJ,MAAM,EAAE,MAAM;AAAA,IAChB,IAAI,MAAM,GAAG,2BAA2B,SAAS;AAEjD,iCAA6B;AAAA,EAC/B;AAEA,MAAI,CAAC;AAAW,UAAM,IAAI,MAAM,gDAAgD;AAChF,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,iEAAiE;AAEnF,WAAS,YAAY;AAAA,IACnB,WAAW,UAAU,SAAS;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;;;ACxGO,IAAM,wBAA0C,CAAC,OAAO,QAAQ,MAAM;AAEtE,SAAS,oBAAoC;AAClD,QAAM,YAAY,QAAQ,IAAI,yBAAyB;AAEvD,MAAI,UAAU,WAAW,MAAM,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,WAAW,MAAM,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AZhBA,IAAI,CAAC,UAAU,QAAQ,SAAS,gBAAa,QAAQ,IAAI,GAAG;AAC1D,UAAQ;AAAA,IACNE,OAAM;AAAA,MACJ;AAAA,wBAA2B,QAAQ,8BAA8B,gBAAa,QAAQ;AAAA;AAAA,IACxF;AAAA,EACF;AACA,UAAQ;AAAA,IACNA,OAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACA,UAAQ,KAAK,CAAC;AAChB;AAEA,QAAQ,IAAIA,OAAM,WAAW;AAAA,SAAO,gBAAa,SAAS,gBAAa;AAAA,CAAW,CAAC;AAInF,IAAM,UAAU,IAAI,QAAQ,EACzB,KAAK,gBAAa,IAAI,EACtB,QAAQ,gBAAa,OAAO,EAC5B,YAAY,uDAAuD;AAEtE,IAAM,gBAAgB,QACnB,QAAQ,UAAU,EAAE,WAAW,KAAK,CAAC,EACrC,YAAY,iFAAiF,EAC7F,OAAO,yBAAyB,+BAA+B,EAC/D,OAAO,uBAAuB,6CAA6C,QAAQ,IAAI,CAAC,EACxF,OAAO,kBAAkB,iEAAiE,MAAM,EAChG,OAAO,uBAAuB,wBAAwB,EACtD,OAAO,0BAA0B,0BAA0B,EAC3D,OAAO,qBAAqB,wBAAwB,EACpD,OAAO,0CAA0C,0CAA0C,EAC3F;AAAA,EACC,IAAI,OAAO,qCAAqC,sBAAsB,EACnE,QAAQ,iBAAiB,EACzB,SAAS;AACd,EACC;AAAA,EACC,IAAI,OAAO,+BAA+B,iCAAiC,EACxE,QAAQ,6BAA6B,EACrC,SAAS;AACd,EACC;AAAA,EACC,IAAI,OAAO,0BAA0B,mCAAmC,EACrE,QAAQ,qBAAqB,EAC7B,QAAQ,kBAAkB,CAAC,EAC3B,SAAS;AACd,EACC,OAAO,CAAC,SAAS,OAAO,IAAI,CAAC;AAIhC,IAAM,cAAc,QACjB,QAAQ,MAAM,EACd,YAAY,+DAA+D,EAC3E,OAAO,uBAAuB,wBAAwB,EACtD,OAAO,0BAA0B,0BAA0B,EAC3D;AAAA,EACC,IAAI,OAAO,qCAAqC,sBAAsB,EACnE,QAAQ,iBAAiB,EACzB,SAAS;AACd,EACC;AAAA,EACC,IAAI,OAAO,+BAA+B,iCAAiC,EACxE,QAAQ,6BAA6B,EACrC,SAAS;AACd,EACC,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC;AAI9B,QAAQ,MAAM,QAAQ,IAAI;","names":["chalk","select","chalk","join","z","chalk","chalk","chalk","z","z","z","chalk","chalk","chalk","chalk","chalk","join","z","chalk","join","select","input","select","chalk","z","chalk","select","input","chalk"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bigcommerce/create-catalyst",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=18.17.0"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@commander-js/extra-typings": "^12.0.0",
|
|
14
|
+
"@inquirer/prompts": "^3.3.0",
|
|
15
|
+
"chalk": "^5.3.0",
|
|
16
|
+
"commander": "^12.0.0",
|
|
17
|
+
"fs-extra": "^11.2.0",
|
|
18
|
+
"giget": "^1.2.1",
|
|
19
|
+
"lodash.kebabcase": "^4.1.1",
|
|
20
|
+
"lodash.merge": "^4.6.2",
|
|
21
|
+
"msw": "^2.1.7",
|
|
22
|
+
"nypm": "^0.3.6",
|
|
23
|
+
"ora": "^8.0.1",
|
|
24
|
+
"semver": "^7.6.0",
|
|
25
|
+
"zod": "^3.22.4",
|
|
26
|
+
"zod-validation-error": "^3.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@bigcommerce/eslint-config": "^2.7.0",
|
|
30
|
+
"@swc/core": "^1.3.107",
|
|
31
|
+
"@swc/jest": "^0.2.34",
|
|
32
|
+
"@types/fs-extra": "^11.0.4",
|
|
33
|
+
"@types/jest": "^29.5.11",
|
|
34
|
+
"@types/lodash.kebabcase": "^4.1.9",
|
|
35
|
+
"@types/lodash.merge": "^4.6.9",
|
|
36
|
+
"@types/node": "^18.17.12",
|
|
37
|
+
"@types/prompts": "^2.4.9",
|
|
38
|
+
"@types/semver": "^7.5.7",
|
|
39
|
+
"eslint": "^8.55.0",
|
|
40
|
+
"jest": "^29.7.0",
|
|
41
|
+
"prettier": "^3.1.1",
|
|
42
|
+
"tsup": "^6.7.0",
|
|
43
|
+
"typescript": "^5.3.3",
|
|
44
|
+
"@bigcommerce/eslint-config-catalyst": "^0.1.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"dev": "tsup --watch",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"lint": "eslint . --max-warnings 0",
|
|
50
|
+
"test": "jest",
|
|
51
|
+
"build": "tsup"
|
|
52
|
+
}
|
|
53
|
+
}
|