@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.cjs +340 -0
- package/dist/index.js +278 -426
- package/dist/index.js.map +14 -0
- package/package.json +37 -46
- package/src/index.ts +14 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +0 -453
package/dist/index.js
CHANGED
|
@@ -1,470 +1,322 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
//
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
//
|
|
92
|
-
|
|
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/
|
|
96
|
-
var
|
|
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/
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
);
|
|
220
|
-
|
|
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
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
|
268
|
-
|
|
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
|
|
282
|
-
renderStepTitle("Git in here");
|
|
85
|
+
async function createD1Database(name, cwd) {
|
|
283
86
|
try {
|
|
284
|
-
await
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
|
297
|
-
renderStepTitle("Installing dependencies");
|
|
99
|
+
async function createKVNamespace(name, cwd) {
|
|
298
100
|
try {
|
|
299
|
-
await
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
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
|
|
312
|
-
renderStepTitle("Performing initial commits");
|
|
113
|
+
async function createR2Bucket(name, cwd) {
|
|
313
114
|
try {
|
|
314
|
-
await
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
|
347
|
-
|
|
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
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
|
363
|
-
|
|
364
|
-
|
|
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
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
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
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
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
|
-
|
|
436
|
-
|
|
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
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
)
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
316
|
+
// packages/cli/src/index.ts
|
|
317
|
+
(async () => {
|
|
318
|
+
await create();
|
|
319
|
+
})();
|
|
320
|
+
|
|
321
|
+
//# debugId=5BA343190996B35B64756E2164756E21
|
|
322
|
+
//# sourceMappingURL=index.js.map
|