@by-association-only/cli 3.4.0 → 4.0.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 CHANGED
@@ -1,470 +1,322 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __defProps = Object.defineProperties;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
8
- var __getOwnPropNames = Object.getOwnPropertyNames;
9
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
10
- var __getProtoOf = Object.getPrototypeOf;
11
- var __hasOwnProp = Object.prototype.hasOwnProperty;
12
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
13
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
- var __spreadValues = (a, b) => {
15
- for (var prop in b || (b = {}))
16
- if (__hasOwnProp.call(b, prop))
17
- __defNormalProp(a, prop, b[prop]);
18
- if (__getOwnPropSymbols)
19
- for (var prop of __getOwnPropSymbols(b)) {
20
- if (__propIsEnum.call(b, prop))
21
- __defNormalProp(a, prop, b[prop]);
22
- }
23
- return a;
24
- };
25
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
26
- var __copyProps = (to, from, except, desc) => {
27
- if (from && typeof from === "object" || typeof from === "function") {
28
- for (let key of __getOwnPropNames(from))
29
- if (!__hasOwnProp.call(to, key) && key !== except)
30
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
- }
32
- return to;
33
- };
34
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
35
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
36
- mod
37
- ));
38
-
39
- // src/index.ts
40
- var import_commander = require("commander");
1
+ // packages/cli/src/commands/create.ts
2
+ import * as fs from "node:fs";
3
+ import { intro, log, note, outro, spinner, text } from "@clack/prompts";
4
+ import * as path from "node:path";
5
+ import { Octokit } from "octokit";
41
6
 
42
- // package.json
43
- var package_default = {
44
- name: "@by-association-only/cli",
45
- version: "3.3.0",
46
- description: "By Association Only CLI",
47
- private: false,
48
- author: "BAO Agency",
49
- license: "MIT",
50
- main: "./dist/index.js",
51
- module: "./dist/index.mjs",
52
- types: "./dist/index.d.ts",
53
- bin: {
54
- bao: "./dist/index.mjs"
55
- },
56
- files: [
57
- "dist"
58
- ],
59
- exports: {
60
- ".": {
61
- require: "./dist/index.js",
62
- import: "./dist/index.mjs",
63
- types: "./dist/index.d.ts"
64
- }
65
- },
66
- scripts: {
67
- dev: "npm run build -- --watch",
68
- build: "tsup src/index.ts --dts --format cjs,esm",
69
- watch: "tsup src/index.ts --dts --format cjs,esm --watch",
70
- lint: "eslint **/*.{t,j}s --fix",
71
- test: "vitest run"
72
- },
73
- peerDependencies: {
74
- vite: "^4.0.4"
75
- },
76
- devDependencies: {
77
- "@types/inquirer": "^9.0.3",
78
- tsconfig: "workspace:*",
79
- "type-fest": "^3.5.1",
80
- vitest: "^0.25.7"
81
- },
82
- dependencies: {
83
- "@octokit/rest": "^19.0.7",
84
- "@sindresorhus/slugify": "^2.1.1",
85
- commander: "^9.5.0",
86
- inquirer: "^9.1.4",
87
- kleur: "^4.1.5"
88
- }
7
+ // packages/cli/src/utils.ts
8
+ var PACKAGE_RUNNER_COMMAND = "bunx";
9
+ var GITHUB_INFO = {
10
+ organization: "baoagency",
11
+ templateRepository: "unisian"
89
12
  };
90
13
 
91
- // src/commands/create/index.ts
92
- var import_inquirer = __toESM(require("inquirer"));
93
- var import_kleur4 = __toESM(require("kleur"));
14
+ // packages/cli/src/wrangler.ts
15
+ import { cancel, confirm, isCancel } from "@clack/prompts";
94
16
 
95
- // src/commands/config.ts
96
- var os = __toESM(require("os"));
97
- var fs = __toESM(require("fs"));
98
- var config = {
99
- get localProjectDirectory() {
100
- if (process.env.BAO_CODE_DIRECTORY) {
101
- if (fs.existsSync(process.env.BAO_CODE_DIRECTORY)) {
102
- return process.env.BAO_CODE_DIRECTORY;
103
- }
104
- }
105
- return `${os.homedir()}/Code`;
106
- },
107
- get githubToken() {
108
- return process.env.GITHUB_AUTH_TOKEN;
109
- },
110
- get githubOrganizationName() {
111
- return "baoagency";
112
- },
113
- get starterThemeGitUrl() {
114
- return "git@github.com:baoagency/do-not-look.git";
115
- }
116
- };
17
+ // packages/cli/src/constants.ts
18
+ var APP_REFERENCE_NAME = "Unisian";
117
19
 
118
- // src/commands/utils.ts
119
- var import_node_child_process = require("child_process");
120
- var import_kleur = __toESM(require("kleur"));
121
- function executableIsAvailable(name) {
122
- const shell = (command) => (0, import_node_child_process.execSync)(command, { encoding: "utf8" });
123
- try {
124
- shell(`which ${name}`);
125
- return true;
126
- } catch (e) {
127
- return false;
128
- }
129
- }
130
- function renderStepTitle(title) {
131
- console.info(`
132
- ${import_kleur.default.magenta().bold().underline(title)}`);
133
- }
134
- function renderStepSuccess(text) {
135
- console.info(`
136
- ${import_kleur.default.green().bold(`\u2714 ${text}`)}`);
137
- }
138
- function renderStepError(text, error) {
139
- console.info(`
140
- ${import_kleur.default.bgRed().underline(`\u2716 ${text}`)}`);
141
- throw new Error(error || text);
142
- }
143
- function spawnPromise(command, ...args) {
20
+ // packages/cli/src/wrangler.ts
21
+ import { readFile, writeFile } from "node:fs/promises";
22
+ async function runWranglerCommand(command, cwd) {
23
+ const child = Bun.spawn([PACKAGE_RUNNER_COMMAND, "wrangler@latest", ...command], {
24
+ stdin: "pipe",
25
+ stderr: "pipe",
26
+ cwd,
27
+ env: {
28
+ ...process.env,
29
+ CLOUDFLARE_ACCOUNT_ID: "824c12820335788e8daf77dba7e7891e"
30
+ }
31
+ });
32
+ const stdout = await new Response(child.stdout).text();
33
+ const stderr = await new Response(child.stderr).text();
34
+ const code = await child.exited;
144
35
  return new Promise((resolve, reject) => {
145
- const child = (0, import_node_child_process.spawn)(command, ...args);
146
- child.on("close", (code) => resolve(code));
147
- child.on("error", (err) => reject(err));
36
+ if (code === 0) {
37
+ resolve({
38
+ code,
39
+ stdout,
40
+ stderr
41
+ });
42
+ }
43
+ reject({
44
+ code,
45
+ stdout,
46
+ stderr
47
+ });
148
48
  });
149
49
  }
150
-
151
- // src/commands/create/local.ts
152
- var process2 = __toESM(require("process"));
153
- var fs2 = __toESM(require("fs"));
154
- var import_kleur2 = __toESM(require("kleur"));
155
- async function checkLocalDependencies() {
156
- renderStepTitle("Checking dependencies");
157
- const hasGithubToken = process2.env.GITHUB_AUTH_TOKEN !== void 0;
158
- const gitExists = await executableIsAvailable("git");
159
- const pnpmExists = await executableIsAvailable("pnpm");
160
- const codeDirectoryExists = fs2.existsSync(config.localProjectDirectory);
161
- const passed = hasGithubToken && gitExists && pnpmExists && codeDirectoryExists;
162
- const renderIcon = (exists) => exists ? import_kleur2.default.green("\u2714") : import_kleur2.default.red("\u2716");
163
- console.info(
164
- `
165
- ${renderIcon(hasGithubToken)} GITHUB_AUTH_TOKEN
166
- ${renderIcon(gitExists)} git
167
- ${renderIcon(pnpmExists)} pnpm
168
- ${renderIcon(codeDirectoryExists)} ~/Code exists`
169
- );
170
- if (!hasGithubToken) {
171
- console.info(`
172
- You're missing an environment variable for ${import_kleur2.default.red().bold("GITHUB_AUTH_TOKEN")}. This is needed so we can create the repository on GitHub. Please go here: https://github.com/settings/tokens/new and create a new personal access token. Set the expiration to none, unless you want to keep remaking it, which is fine. You'll need the "repo" scope ticked as well.
173
-
174
- Once that's been generated you will need to add it to your .bash_profile or .zshrc. Once that's been added you can run source ~/.bash_profile or source ~/.zshrc, depending on which shell you use, and run the script again.
175
- `);
176
- }
177
- passed ? renderStepSuccess("yay dependencies") : renderStepError("Dependencies failed");
178
- return passed;
179
- }
180
-
181
- // src/commands/create/starter-theme/index.ts
182
- var fs3 = __toESM(require("fs"));
183
- var import_promises = require("fs/promises");
184
- async function setupStarterTheme(config2, answers) {
185
- await cloneStarterThemeRepository(config2);
186
- await moveStarterThemeToProjectLocation(config2);
187
- await rewriteWorkspacePackageVersions(config2);
188
- await addHuskyPrepareLine(config2);
189
- await gitInit(config2);
190
- await pnpmInstall(config2);
191
- await doInitialCommits(config2);
192
- await changeShopifyStoreName(config2, answers);
193
- await removeTemporaryClone(config2);
194
- }
195
- async function cloneStarterThemeRepository(config2) {
196
- renderStepTitle("Cloning starter theme repository");
50
+ async function ensureWranglerAuthenticated() {
197
51
  try {
198
- await spawnPromise(
199
- "git",
200
- [
201
- "clone",
202
- config2.starterThemeGitUrl,
203
- config2.temporaryCloneLocation
204
- ],
205
- { stdio: "inherit" }
206
- );
207
- renderStepSuccess("yay, starter theme");
208
- } catch (e) {
209
- renderStepError("Git clone failed", e);
52
+ const result = await runWranglerCommand(["whoami"]);
53
+ return !result.stdout.includes("You are not authenticated");
54
+ } catch {
55
+ return false;
210
56
  }
211
57
  }
212
- async function moveStarterThemeToProjectLocation(config2) {
213
- renderStepTitle("Extracting starter theme");
214
- const themeLocation = `${config2.temporaryCloneLocation}/themes/starter-theme`;
215
- try {
216
- await spawnPromise(
217
- "mv",
218
- [themeLocation, config2.localProjectLocation]
219
- );
220
- renderStepSuccess(`Moved theme to ${config2.localProjectLocation}`);
221
- } catch (e) {
222
- renderStepError("Git clone failed", e);
223
- }
58
+ async function wranglerLogin() {
59
+ const child = Bun.spawn([PACKAGE_RUNNER_COMMAND, "wrangler", "login"], { stdin: "inherit" });
60
+ const code = await child.exited;
61
+ return await new Promise((resolve, reject) => {
62
+ if (code === 0) {
63
+ resolve();
64
+ }
65
+ reject();
66
+ });
224
67
  }
225
- async function rewriteWorkspacePackageVersions(config2) {
226
- renderStepTitle("Fixing package.json versions");
227
- const packageJson = loadPackageJson(config2.localProjectLocation);
228
- const rewrittenPackageJson = await rewritePackages(packageJson);
229
- try {
230
- await (0, import_promises.writeFile)(
231
- `${config2.localProjectLocation}/package.json`,
232
- JSON.stringify(rewrittenPackageJson, null, 2)
233
- );
234
- renderStepSuccess("Updated package.json dependency versions");
235
- } catch (e) {
236
- renderStepError("Rewriting package.json versions failed", e);
237
- }
238
- async function findVersionForPackage(packageName) {
239
- const packagesLocation = `${config2.temporaryCloneLocation}/packages`;
240
- const folders = (await (0, import_promises.readdir)(packagesLocation, { withFileTypes: true })).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
241
- const foundPackage = folders.map((folder) => loadPackageJson(`${packagesLocation}/${folder}`)).find((packageJSON) => packageJSON.name === packageName);
242
- if (!foundPackage)
243
- return null;
244
- return `^${foundPackage.version}`;
245
- }
246
- async function rewritePackages(packageJson2) {
247
- await rewriteListOfPackages("dependencies");
248
- await rewriteListOfPackages("devDependencies");
249
- await rewriteListOfPackages("peerDependencies");
250
- return packageJson2;
251
- async function rewriteListOfPackages(key) {
252
- const dependencies = packageJson2[key];
253
- if (typeof dependencies === "undefined")
254
- return;
255
- for (const [packageName, version] of Object.entries(dependencies)) {
256
- if (version !== "workspace:*")
257
- continue;
258
- const packageVersion = await findVersionForPackage(packageName);
259
- if (!packageVersion)
260
- continue;
261
- dependencies[packageName] = packageVersion;
262
- }
263
- return packageJson2;
68
+ async function ensureWranglerSessionExists(s) {
69
+ s.message("Checking to make sure you have the Wrangler CLI installed and authenticated...");
70
+ if (!await ensureWranglerAuthenticated()) {
71
+ s.stop("Hmm. Looks like you're not logged in yet.");
72
+ const wantsToLogIn = await confirm({
73
+ message: `You need to be logged into wrangler to setup a ${APP_REFERENCE_NAME} app. Log in now?`
74
+ });
75
+ if (isCancel(wantsToLogIn) || !wantsToLogIn) {
76
+ cancel(`You need to be logged into wrangler to be able to setup a ${APP_REFERENCE_NAME} app.`);
77
+ process.exit(0);
264
78
  }
79
+ await wranglerLogin();
265
80
  }
266
81
  }
267
- async function addHuskyPrepareLine(config2) {
268
- renderStepTitle("Setting up Husky");
269
- const packageJson = loadPackageJson(config2.localProjectLocation);
270
- packageJson.scripts.prepare = "husky install";
271
- try {
272
- await (0, import_promises.writeFile)(
273
- `${config2.localProjectLocation}/package.json`,
274
- JSON.stringify(packageJson, null, 2)
275
- );
276
- renderStepSuccess("Added Husky prepare script");
277
- } catch (e) {
278
- renderStepError("Setting up Husky failed", e);
279
- }
82
+ async function writeWranglerConfig(location, config) {
83
+ return await writeFile(location, JSON.stringify(config, null, 2));
280
84
  }
281
- async function gitInit(config2) {
282
- renderStepTitle("Git in here");
85
+ async function createD1Database(name, cwd) {
283
86
  try {
284
- await spawnPromise(
285
- "git",
286
- [
287
- "init"
288
- ],
289
- { stdio: "inherit", cwd: config2.localProjectLocation }
290
- );
291
- renderStepSuccess("Git is in here");
292
- } catch (e) {
293
- renderStepError("Git isn't here", e);
87
+ await runWranglerCommand(["d1", "create", name, "--binding=DB", "--update-config=true"], cwd);
88
+ return {
89
+ success: true,
90
+ message: `✅ D1 Database: ${name} created!`
91
+ };
92
+ } catch (error) {
93
+ return {
94
+ success: false,
95
+ message: `❌ D1 Database: ${error.stderr || error.stdout || error.message}`
96
+ };
294
97
  }
295
98
  }
296
- async function pnpmInstall(config2) {
297
- renderStepTitle("Installing dependencies");
99
+ async function createKVNamespace(name, cwd) {
298
100
  try {
299
- await spawnPromise(
300
- "pnpm",
301
- [
302
- "install"
303
- ],
304
- { stdio: "inherit", cwd: config2.localProjectLocation }
305
- );
306
- renderStepSuccess("Dependencies installed");
307
- } catch (e) {
308
- renderStepError("Installing dependencies failed", e);
101
+ await runWranglerCommand(["kv", "namespace", "create", name, "--binding=BUCKET", "--update-config=true"], cwd);
102
+ return {
103
+ success: true,
104
+ message: `✅ KV Namespace: ${name} created!`
105
+ };
106
+ } catch (error) {
107
+ return {
108
+ success: false,
109
+ message: `❌ KV Namespace: ${error.stderr || error.stdout || error.message}`
110
+ };
309
111
  }
310
112
  }
311
- async function doInitialCommits(config2) {
312
- renderStepTitle("Performing initial commits");
113
+ async function createR2Bucket(name, cwd) {
313
114
  try {
314
- await spawnPromise(
315
- "git",
316
- ["add", "."],
317
- { cwd: config2.localProjectLocation }
318
- );
319
- await spawnPromise(
320
- "git",
321
- ["commit", "-m", "Initial commit"],
322
- { cwd: config2.localProjectLocation }
323
- );
324
- renderStepSuccess("Doned");
325
- } catch (e) {
326
- renderStepError("Performing initial commits failed", e);
115
+ await runWranglerCommand(["r2", "bucket", "create", name, "--binding=BUCKET", "--update-config=true"], cwd);
116
+ return {
117
+ success: true,
118
+ message: `✅ KV Namespace: ${name} created!`
119
+ };
120
+ } catch (error) {
121
+ return {
122
+ success: false,
123
+ message: `❌ KV Namespace: ${error.stderr || error.stdout || error.message}`
124
+ };
327
125
  }
328
126
  }
329
- async function changeShopifyStoreName(config2, answers) {
330
- renderStepTitle(`Changing dev store name to ${answers.shopName}`);
331
- const packageJson = loadPackageJson(config2.localProjectLocation);
332
- if (!packageJson.scripts) {
333
- return renderStepError("package.json has no scripts key");
334
- }
335
- packageJson.scripts["shopify:serve"] = `shopify theme dev -s ${answers.shopName} --live-reload full-page`;
336
- try {
337
- await (0, import_promises.writeFile)(
338
- `${config2.localProjectLocation}/package.json`,
339
- JSON.stringify(packageJson, null, 2)
340
- );
341
- renderStepSuccess("Added \u{1F44D}");
342
- } catch (e) {
343
- renderStepError(`Changing dev store name to ${answers.shopName} failed`, e);
127
+
128
+ // packages/cli/src/commands/create.ts
129
+ import color from "picocolors";
130
+ async function create() {
131
+ const initialContext = await initializeContext();
132
+ const context = await validateEnvironment(initialContext);
133
+ await createGithubRepository(context);
134
+ await cloneGithubRepository(context);
135
+ await provisionCloudflareResources(context);
136
+ await cleanup(context);
137
+ note([
138
+ `1. cd ${context.localPath}`,
139
+ "2. shopify app config link",
140
+ "3. bun run dev"
141
+ ].join(`
142
+ `), `${color.bgYellow(color.black("Next steps."))}`);
143
+ outro(`Go and build something ${color.underline(color.italic(color.yellow("stupendous")))}.`);
144
+ }
145
+ async function initializeContext() {
146
+ intro(`Setting up a new BAO ${APP_REFERENCE_NAME} project`);
147
+ const appName = await text({
148
+ message: "What is the name of your project?",
149
+ placeholder: `my-${APP_REFERENCE_NAME.toLowerCase()}-project`,
150
+ validate: (value) => {
151
+ if (!value.match(/^[a-z0-9-]+$/)) {
152
+ return `Invalid app name: ${value}. App names can only contain lowercase letters, numbers, and dashes.`;
153
+ }
154
+ }
155
+ });
156
+ const repoName = `${String(appName)}-app`;
157
+ const localPath = `./${repoName}`;
158
+ if (fs.existsSync(localPath)) {
159
+ log.error(`Unable to continue as ${localPath} already exists`);
160
+ process.exit(0);
344
161
  }
162
+ const s = spinner();
163
+ return {
164
+ appName: String(appName),
165
+ repoName,
166
+ localPath,
167
+ spinner: s
168
+ };
345
169
  }
346
- async function removeTemporaryClone(config2) {
347
- renderStepTitle(`Removing ${config2.temporaryCloneLocation}`);
170
+ async function validateEnvironment(initialContext) {
171
+ initialContext.spinner.start("Welcome! Checking to make sure your environment is set up correctly.");
172
+ const hasEnvironmentAccessToken = typeof process.env.GITHUB_TOKEN !== "undefined" && process.env.GITHUB_TOKEN.trim() !== "";
173
+ if (!hasEnvironmentAccessToken) {
174
+ log.warning(`Unable to find a GITHUB_TOKEN environment variable. Please go to https://github.com/settings/tokens/new and create an access token to be able to use the CLI.`);
175
+ }
176
+ const githubAccessToken = process.env.GITHUB_TOKEN || await text({
177
+ message: "Access token"
178
+ });
348
179
  try {
349
- await spawnPromise(
350
- "rm",
351
- [
352
- "-rf",
353
- config2.temporaryCloneLocation
354
- ],
355
- { stdio: "inherit" }
356
- );
357
- renderStepSuccess("All cleaned up");
358
- } catch (e) {
359
- renderStepError(`Removing ${config2.temporaryCloneLocation} failed`, e);
180
+ await testGithubAccessTokenIsValid(String(githubAccessToken));
181
+ } catch (error) {
182
+ log.error(`Invalid access token: ${error.message}`);
183
+ process.exit(0);
360
184
  }
185
+ await ensureWranglerSessionExists(initialContext.spinner);
186
+ initialContext.spinner.stop("Validated environment");
187
+ note(`Before using R2, Queues, and Durable objects,
188
+ ` + `make sure you've enabled them in the Cloudflare Dashboard.
189
+ ` + `https://dash.cloudflare.com/
190
+ ` + "Otherwise, the following commands might fail! \uD83D\uDE2C", "\uD83D\uDC4B Heads-up:");
191
+ return {
192
+ ...initialContext,
193
+ githubPersonalAccessToken: String(githubAccessToken),
194
+ cloudflare: {}
195
+ };
361
196
  }
362
- function loadPackageJson(location) {
363
- return JSON.parse(
364
- fs3.readFileSync(`${location}/package.json`).toString()
365
- );
366
- }
367
-
368
- // src/commands/create/git/index.ts
369
- var import_rest = require("@octokit/rest");
370
- var import_kleur3 = __toESM(require("kleur"));
371
-
372
- // src/commands/create/git/utils.ts
373
- var import_slugify = __toESM(require("@sindresorhus/slugify"));
374
- function getRepoName(answers) {
375
- return (0, import_slugify.default)(answers.projectName);
197
+ async function testGithubAccessTokenIsValid(accessToken) {
198
+ const octokit = new Octokit({
199
+ auth: accessToken
200
+ });
201
+ const { data: { login } } = await octokit.rest.users.getAuthenticated();
202
+ return login;
376
203
  }
377
-
378
- // src/commands/create/git/index.ts
379
- async function setupGitHub(config2, answers) {
380
- const octokit = new import_rest.Octokit({
381
- auth: config2.githubToken
204
+ async function createGithubRepository(context) {
205
+ context.spinner.start(`Creating GitHub Repository ${context.repoName}`);
206
+ const octokit = new Octokit({
207
+ auth: context.githubPersonalAccessToken
382
208
  });
383
- renderStepTitle("Creating project on Github");
384
209
  try {
385
- const project = await createRemoteRepository();
386
- import_kleur3.default.green(" \u2714 created project on Github");
387
- await spawnPromise("git", ["remote", "add", "origin", project.data.ssh_url], { cwd: config2.localProjectLocation });
388
- await spawnPromise("git", ["push", "-u", "origin", "master"], { cwd: config2.localProjectLocation });
389
- import_kleur3.default.green(" \u2714 pushed master");
390
- renderStepSuccess("Github project has been created and pushed up");
391
- } catch (e) {
392
- renderStepError("Github project creation failed", e);
393
- }
394
- function createRemoteRepository() {
395
- return octokit.repos.createInOrg({
396
- org: config2.githubOrganizationName,
397
- name: getRepoName(answers),
210
+ const appRepo = await octokit.rest.repos.createUsingTemplate({
211
+ template_owner: GITHUB_INFO.organization,
212
+ template_repo: GITHUB_INFO.templateRepository,
213
+ owner: GITHUB_INFO.organization,
214
+ name: context.repoName,
398
215
  private: true
399
216
  });
217
+ context.repoHttpUrl = appRepo.data.html_url;
218
+ context.repoSshUrl = appRepo.data.ssh_url;
219
+ } catch (error) {
220
+ log.error(`Unable to create Github Repository ${context.repoName}`);
221
+ log.error(error);
222
+ process.exit(0);
400
223
  }
224
+ context.spinner.stop("Github repository created! ⭐");
401
225
  }
402
-
403
- // src/commands/create/index.ts
404
- async function createProject() {
405
- const answers = await import_inquirer.default.prompt(prompts);
406
- const createConfig = __spreadProps(__spreadValues({}, config), {
407
- localProjectLocation: `${config.localProjectDirectory}/${answers.projectName.toLowerCase().replaceAll(" ", "-")}`,
408
- temporaryCloneLocation: `/tmp/${answers.projectName.toLowerCase().replaceAll(" ", "-")}`
226
+ async function cloneGithubRepository(context) {
227
+ if (typeof context.repoSshUrl === "undefined") {
228
+ log.error(`Unable to clone Github repository ${context.repoName} as can't find the .git URL`);
229
+ process.exit(0);
230
+ }
231
+ context.spinner.start(`Cloning ${context.repoName} from GitHub`);
232
+ await new Promise((resolve) => setTimeout(resolve, 5000));
233
+ const child = Bun.spawn(["git", "clone", context.repoSshUrl, context.localPath], {
234
+ stderr: "ignore",
235
+ stdout: "ignore"
409
236
  });
410
- await checkLocalDependencies();
411
- await setupStarterTheme(createConfig, answers);
412
- await setupGitHub(createConfig, answers);
413
- await finish(createConfig, answers);
237
+ await child.exited;
238
+ if (fs.existsSync(context.localPath)) {
239
+ context.spinner.stop(`Successfully cloned repository to ${context.localPath}`);
240
+ return;
241
+ }
242
+ context.spinner.stop();
243
+ log.error(`Unable to clone repository`);
244
+ process.exit(0);
414
245
  }
415
- var prompts = [
416
- {
417
- type: "input",
418
- name: "projectName",
419
- message: "Project name",
420
- validate(input) {
421
- return new Promise((resolve) => {
422
- resolve(input.length > 0);
423
- });
424
- }
425
- },
426
- {
427
- type: "input",
428
- name: "shopName",
429
- message: "Shopify store name",
430
- validate(input) {
431
- return new Promise((resolve) => {
432
- resolve(input.length > 0);
433
- });
246
+ async function provisionCloudflareResources(context) {
247
+ note(["Creating the following Cloudflare resources:", "- KV", "- D1", "- R2 Bucket"].join(`
248
+ `));
249
+ context.spinner.start(`Creating Cloudflare resources`);
250
+ const wranglerConfig = {
251
+ $schema: "node_modules/wrangler/config-schema.json",
252
+ name: context.appName,
253
+ compatibility_date: "2025-09-21",
254
+ compatibility_flags: ["nodejs_compat"],
255
+ main: "@tanstack/react-start/server-entry",
256
+ dev: {
257
+ ip: "0.0.0.0",
258
+ port: 8647
434
259
  },
435
- filter(input) {
436
- return input.replace(".myshopify.com", "");
260
+ upload_source_maps: true,
261
+ placement: {
262
+ mode: "smart"
263
+ },
264
+ observability: {
265
+ enabled: true
266
+ }
267
+ };
268
+ await writeWranglerConfig(`${context.localPath}/wrangler.json`, wranglerConfig);
269
+ const results = [];
270
+ context.spinner.message(`Creating KV namespace`);
271
+ results.push(await createKVNamespace(context.appName, context.localPath));
272
+ context.spinner.message(`Creating D1 database`);
273
+ results.push(await createD1Database(context.appName, context.localPath));
274
+ context.spinner.message(`Creating R2 bucket`);
275
+ results.push(await createR2Bucket(context.appName, context.localPath));
276
+ for (const result of results) {
277
+ if (!result.success) {
278
+ log.error(result.message);
279
+ process.exit(0);
437
280
  }
438
281
  }
439
- ];
440
- async function finish(config2, answers) {
441
- console.info(import_kleur4.default.bold().yellow("\nCongratulations! \u{1F973}\n"));
442
- console.info(import_kleur4.default.cyan("Just to recap what we've just done:"));
443
- console.info(import_kleur4.default.cyan(`- Cloned down the latest starter theme to ${config2.localProjectLocation}`));
444
- console.info(import_kleur4.default.cyan(`- Prepared it with Git, installed all of the packages and setup the "${import_kleur4.default.bold().magenta("pnpm run dev")}" command ready for you`));
445
- console.info(import_kleur4.default.cyan(`- Created a GitHub repository at ${import_kleur4.default.magenta(`https://github.com/${config2.githubOrganizationName}/${getRepoName(
446
- answers
447
- )}`)}`));
448
- console.info();
449
- console.info(import_kleur4.default.yellow("Not bad for running just 1 command! Happy dev'ing \u270C\uFE0F\n"));
450
- const otherAnswers = await import_inquirer.default.prompt([{
451
- type: "confirm",
452
- name: "runDev",
453
- message: 'Would you like me to run "pnpm run dev" for you?'
454
- }]);
455
- if (otherAnswers.runDev) {
456
- await spawnPromise(
457
- "pnpm",
458
- [
459
- "run",
460
- "dev"
461
- ],
462
- { stdio: "inherit" }
463
- );
464
- }
282
+ context.spinner.stop("Cloudflare resources created and wrangler.json updated");
283
+ const allResults = results.map((r) => r.message);
284
+ note(allResults.join(`
285
+ `), "Here's what we did:");
286
+ }
287
+ async function cleanup(context) {
288
+ context.spinner.start("Removing unnecessary files from the template");
289
+ note("Removing default shopify.app.toml", "\uD83E\uDDF9 Cleaning up");
290
+ fs.unlinkSync(path.join(context.localPath, "shopify.app.toml"));
291
+ note("Removing default shopify.app.production.toml", "\uD83E\uDDF9 Cleaning up");
292
+ fs.unlinkSync(path.join(context.localPath, "shopify.app.production.toml"));
293
+ context.spinner.message("Installing packages");
294
+ const packageInstall = Bun.spawn(["bun", "install"], {
295
+ stderr: "ignore",
296
+ stdout: "ignore",
297
+ cwd: context.localPath
298
+ });
299
+ await packageInstall.exited;
300
+ context.spinner.message("Finalising app setup");
301
+ const gitAdd = Bun.spawn(["git", "add", "."], {
302
+ stderr: "ignore",
303
+ stdout: "ignore",
304
+ cwd: context.localPath
305
+ });
306
+ await gitAdd.exited;
307
+ const gitCommit = Bun.spawn(["git", "commit", "-m", "App setup"], {
308
+ stderr: "ignore",
309
+ stdout: "ignore",
310
+ cwd: context.localPath
311
+ });
312
+ await gitCommit.exited;
313
+ context.spinner.stop();
465
314
  }
466
315
 
467
- // src/index.ts
468
- import_commander.program.version(package_default.version).description(package_default.description);
469
- import_commander.program.command("create").alias("c").description("Create a Shopify theme project").action(async () => await createProject());
470
- import_commander.program.parse(process.argv);
316
+ // packages/cli/src/index.ts
317
+ (async () => {
318
+ await create();
319
+ })();
320
+
321
+ //# debugId=5BA343190996B35B64756E2164756E21
322
+ //# sourceMappingURL=index.js.map