create-sitekick 0.2.1 → 0.2.3
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 +93 -87
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1269,57 +1269,93 @@ function runInteractive(cmd, opts) {
|
|
|
1269
1269
|
function isInstalled(cmd) {
|
|
1270
1270
|
return run(`which ${cmd}`) !== null;
|
|
1271
1271
|
}
|
|
1272
|
+
var scaffoldedDir = null;
|
|
1273
|
+
function abort(message = "Cancelled.") {
|
|
1274
|
+
if (scaffoldedDir && fs.existsSync(scaffoldedDir)) {
|
|
1275
|
+
fs.rmSync(scaffoldedDir, { recursive: true, force: true });
|
|
1276
|
+
}
|
|
1277
|
+
Ne(message);
|
|
1278
|
+
process.exit(0);
|
|
1279
|
+
}
|
|
1272
1280
|
async function cancelOrContinue(message) {
|
|
1273
1281
|
const result = await Re({ message, initialValue: true });
|
|
1274
|
-
if (Ct(result))
|
|
1275
|
-
|
|
1276
|
-
process.exit(0);
|
|
1277
|
-
}
|
|
1282
|
+
if (Ct(result))
|
|
1283
|
+
abort();
|
|
1278
1284
|
return result;
|
|
1279
1285
|
}
|
|
1280
1286
|
var TOOLS = {
|
|
1281
1287
|
gh: {
|
|
1282
1288
|
name: "GitHub CLI",
|
|
1283
1289
|
cmd: "gh",
|
|
1284
|
-
|
|
1290
|
+
brewPkg: "gh"
|
|
1285
1291
|
},
|
|
1286
1292
|
vercel: {
|
|
1287
1293
|
name: "Vercel CLI",
|
|
1288
1294
|
cmd: "vercel",
|
|
1289
|
-
|
|
1295
|
+
bunPkg: "vercel"
|
|
1290
1296
|
},
|
|
1291
1297
|
neonctl: {
|
|
1292
1298
|
name: "Neon CLI",
|
|
1293
1299
|
cmd: "neonctl",
|
|
1294
|
-
|
|
1300
|
+
bunPkg: "neonctl"
|
|
1295
1301
|
},
|
|
1296
1302
|
sanity: {
|
|
1297
1303
|
name: "Sanity CLI",
|
|
1298
1304
|
cmd: "sanity",
|
|
1299
|
-
|
|
1305
|
+
bunPkg: "sanity"
|
|
1300
1306
|
}
|
|
1301
1307
|
};
|
|
1308
|
+
async function ensureBrew(s) {
|
|
1309
|
+
if (isInstalled("brew"))
|
|
1310
|
+
return true;
|
|
1311
|
+
const shouldInstall = await cancelOrContinue("Homebrew is needed to install some tools. Install it now?");
|
|
1312
|
+
if (!shouldInstall)
|
|
1313
|
+
return false;
|
|
1314
|
+
s.start("Installing Homebrew...");
|
|
1315
|
+
try {
|
|
1316
|
+
execSync('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit" });
|
|
1317
|
+
} catch {
|
|
1318
|
+
s.stop("Failed to install Homebrew");
|
|
1319
|
+
return false;
|
|
1320
|
+
}
|
|
1321
|
+
const brewDirs = ["/opt/homebrew/bin", "/opt/homebrew/sbin", "/usr/local/bin", "/usr/local/sbin"];
|
|
1322
|
+
const currentPath = process.env.PATH || "";
|
|
1323
|
+
const newDirs = brewDirs.filter((d2) => !currentPath.includes(d2));
|
|
1324
|
+
if (newDirs.length > 0) {
|
|
1325
|
+
process.env.PATH = `${newDirs.join(":")}:${currentPath}`;
|
|
1326
|
+
}
|
|
1327
|
+
if (!isInstalled("brew")) {
|
|
1328
|
+
s.stop("Homebrew installed but not found on PATH. Restart your terminal and try again.");
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
s.stop("Homebrew installed");
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1302
1334
|
async function ensureTool(key, s) {
|
|
1303
1335
|
const tool = TOOLS[key];
|
|
1304
1336
|
if (isInstalled(tool.cmd))
|
|
1305
1337
|
return true;
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1338
|
+
const shouldInstall = await cancelOrContinue(`${tool.name} (${tool.cmd}) is not installed. Install it now?`);
|
|
1339
|
+
if (!shouldInstall)
|
|
1340
|
+
return false;
|
|
1341
|
+
let installCmd;
|
|
1342
|
+
if (tool.bunPkg) {
|
|
1343
|
+
installCmd = `bun add -g ${tool.bunPkg}`;
|
|
1344
|
+
} else if (tool.brewPkg) {
|
|
1345
|
+
if (!await ensureBrew(s))
|
|
1314
1346
|
return false;
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
return
|
|
1347
|
+
installCmd = `brew install ${tool.brewPkg}`;
|
|
1348
|
+
} else {
|
|
1349
|
+
return false;
|
|
1318
1350
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1351
|
+
s.start(`Installing ${tool.name}...`);
|
|
1352
|
+
const result = run(installCmd);
|
|
1353
|
+
if (result === null) {
|
|
1354
|
+
s.stop(`Failed to install ${tool.name}`);
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1357
|
+
s.stop(`${tool.name} installed`);
|
|
1358
|
+
return true;
|
|
1323
1359
|
}
|
|
1324
1360
|
async function ensureAuth(toolName, checkCmd, authCmd, s) {
|
|
1325
1361
|
s.start(`Checking ${toolName} authentication...`);
|
|
@@ -1360,10 +1396,8 @@ async function selectGitHubOrg() {
|
|
|
1360
1396
|
...orgs.map((org) => ({ value: org, label: org }))
|
|
1361
1397
|
]
|
|
1362
1398
|
});
|
|
1363
|
-
if (Ct(selected))
|
|
1364
|
-
|
|
1365
|
-
process.exit(0);
|
|
1366
|
-
}
|
|
1399
|
+
if (Ct(selected))
|
|
1400
|
+
abort();
|
|
1367
1401
|
return selected === "__personal__" ? null : selected;
|
|
1368
1402
|
}
|
|
1369
1403
|
async function selectVercelTeam() {
|
|
@@ -1402,10 +1436,8 @@ async function selectVercelTeam() {
|
|
|
1402
1436
|
}))
|
|
1403
1437
|
]
|
|
1404
1438
|
});
|
|
1405
|
-
if (Ct(selected))
|
|
1406
|
-
|
|
1407
|
-
process.exit(0);
|
|
1408
|
-
}
|
|
1439
|
+
if (Ct(selected))
|
|
1440
|
+
abort();
|
|
1409
1441
|
return selected === "__personal__" ? null : selected;
|
|
1410
1442
|
}
|
|
1411
1443
|
async function selectNeonOrg() {
|
|
@@ -1427,10 +1459,8 @@ async function selectNeonOrg() {
|
|
|
1427
1459
|
}))
|
|
1428
1460
|
]
|
|
1429
1461
|
});
|
|
1430
|
-
if (Ct(selected))
|
|
1431
|
-
|
|
1432
|
-
process.exit(0);
|
|
1433
|
-
}
|
|
1462
|
+
if (Ct(selected))
|
|
1463
|
+
abort();
|
|
1434
1464
|
return selected === "__personal__" ? null : selected;
|
|
1435
1465
|
} catch {
|
|
1436
1466
|
return null;
|
|
@@ -1449,10 +1479,8 @@ async function setupGitHub(projectName, targetDir, s) {
|
|
|
1449
1479
|
{ value: "skip", label: "Skip GitHub setup" }
|
|
1450
1480
|
]
|
|
1451
1481
|
});
|
|
1452
|
-
if (Ct(existing))
|
|
1453
|
-
|
|
1454
|
-
process.exit(0);
|
|
1455
|
-
}
|
|
1482
|
+
if (Ct(existing))
|
|
1483
|
+
abort();
|
|
1456
1484
|
if (existing === "skip")
|
|
1457
1485
|
return null;
|
|
1458
1486
|
if (existing === "existing") {
|
|
@@ -1464,10 +1492,8 @@ async function setupGitHub(projectName, targetDir, s) {
|
|
|
1464
1492
|
return "Repo URL is required";
|
|
1465
1493
|
}
|
|
1466
1494
|
});
|
|
1467
|
-
if (Ct(repoUrl2))
|
|
1468
|
-
|
|
1469
|
-
process.exit(0);
|
|
1470
|
-
}
|
|
1495
|
+
if (Ct(repoUrl2))
|
|
1496
|
+
abort();
|
|
1471
1497
|
s.start("Linking to existing repo...");
|
|
1472
1498
|
run(`git remote add origin ${repoUrl2}`, { cwd: targetDir });
|
|
1473
1499
|
s.stop("Linked to existing repo");
|
|
@@ -1481,10 +1507,8 @@ async function setupGitHub(projectName, targetDir, s) {
|
|
|
1481
1507
|
{ value: "public", label: "Public" }
|
|
1482
1508
|
]
|
|
1483
1509
|
});
|
|
1484
|
-
if (Ct(visibility))
|
|
1485
|
-
|
|
1486
|
-
process.exit(0);
|
|
1487
|
-
}
|
|
1510
|
+
if (Ct(visibility))
|
|
1511
|
+
abort();
|
|
1488
1512
|
const repoFullName = ghOrg ? `${ghOrg}/${projectName}` : projectName;
|
|
1489
1513
|
s.start(`Creating GitHub repo ${import_picocolors3.default.cyan(repoFullName)}...`);
|
|
1490
1514
|
const result = run(`gh repo create ${repoFullName} --${visibility} --source . --remote origin`, { cwd: targetDir });
|
|
@@ -1509,10 +1533,8 @@ async function setupNeon(projectName, s) {
|
|
|
1509
1533
|
{ value: "skip", label: "Skip database setup" }
|
|
1510
1534
|
]
|
|
1511
1535
|
});
|
|
1512
|
-
if (Ct(existing))
|
|
1513
|
-
|
|
1514
|
-
process.exit(0);
|
|
1515
|
-
}
|
|
1536
|
+
if (Ct(existing))
|
|
1537
|
+
abort();
|
|
1516
1538
|
if (existing === "skip")
|
|
1517
1539
|
return null;
|
|
1518
1540
|
if (existing === "existing") {
|
|
@@ -1526,10 +1548,8 @@ async function setupNeon(projectName, s) {
|
|
|
1526
1548
|
return "Must be a PostgreSQL connection string";
|
|
1527
1549
|
}
|
|
1528
1550
|
});
|
|
1529
|
-
if (Ct(connStr))
|
|
1530
|
-
|
|
1531
|
-
process.exit(0);
|
|
1532
|
-
}
|
|
1551
|
+
if (Ct(connStr))
|
|
1552
|
+
abort();
|
|
1533
1553
|
return connStr;
|
|
1534
1554
|
}
|
|
1535
1555
|
const neonOrgId = await selectNeonOrg();
|
|
@@ -1583,10 +1603,8 @@ async function setupSanityProject(projectName, s) {
|
|
|
1583
1603
|
{ value: "skip", label: "Skip Sanity setup" }
|
|
1584
1604
|
]
|
|
1585
1605
|
});
|
|
1586
|
-
if (Ct(existing))
|
|
1587
|
-
|
|
1588
|
-
process.exit(0);
|
|
1589
|
-
}
|
|
1606
|
+
if (Ct(existing))
|
|
1607
|
+
abort();
|
|
1590
1608
|
if (existing === "skip")
|
|
1591
1609
|
return null;
|
|
1592
1610
|
if (existing === "existing") {
|
|
@@ -1598,19 +1616,15 @@ async function setupSanityProject(projectName, s) {
|
|
|
1598
1616
|
return "Project ID is required";
|
|
1599
1617
|
}
|
|
1600
1618
|
});
|
|
1601
|
-
if (Ct(projectId))
|
|
1602
|
-
|
|
1603
|
-
process.exit(0);
|
|
1604
|
-
}
|
|
1619
|
+
if (Ct(projectId))
|
|
1620
|
+
abort();
|
|
1605
1621
|
const dataset = await Ze({
|
|
1606
1622
|
message: "Dataset name:",
|
|
1607
1623
|
placeholder: "production",
|
|
1608
1624
|
initialValue: "production"
|
|
1609
1625
|
});
|
|
1610
|
-
if (Ct(dataset))
|
|
1611
|
-
|
|
1612
|
-
process.exit(0);
|
|
1613
|
-
}
|
|
1626
|
+
if (Ct(dataset))
|
|
1627
|
+
abort();
|
|
1614
1628
|
return { projectId, dataset };
|
|
1615
1629
|
}
|
|
1616
1630
|
s.start(`Creating Sanity project ${import_picocolors3.default.cyan(projectName)}...`);
|
|
@@ -1647,10 +1661,8 @@ async function setupVercel(projectName, targetDir, repoUrl, s) {
|
|
|
1647
1661
|
{ value: "skip", label: "Skip Vercel setup" }
|
|
1648
1662
|
]
|
|
1649
1663
|
});
|
|
1650
|
-
if (Ct(existing))
|
|
1651
|
-
|
|
1652
|
-
process.exit(0);
|
|
1653
|
-
}
|
|
1664
|
+
if (Ct(existing))
|
|
1665
|
+
abort();
|
|
1654
1666
|
if (existing === "skip")
|
|
1655
1667
|
return { url: null, scope: null };
|
|
1656
1668
|
const vercelTeam = await selectVercelTeam();
|
|
@@ -1711,10 +1723,8 @@ async function askOpenAIKey() {
|
|
|
1711
1723
|
{ value: "skip", label: "Skip — set up later" }
|
|
1712
1724
|
]
|
|
1713
1725
|
});
|
|
1714
|
-
if (Ct(setup))
|
|
1715
|
-
|
|
1716
|
-
process.exit(0);
|
|
1717
|
-
}
|
|
1726
|
+
if (Ct(setup))
|
|
1727
|
+
abort();
|
|
1718
1728
|
if (setup === "skip")
|
|
1719
1729
|
return null;
|
|
1720
1730
|
const key = await Ze({
|
|
@@ -1727,10 +1737,8 @@ async function askOpenAIKey() {
|
|
|
1727
1737
|
return "OpenAI keys start with sk-";
|
|
1728
1738
|
}
|
|
1729
1739
|
});
|
|
1730
|
-
if (Ct(key))
|
|
1731
|
-
|
|
1732
|
-
process.exit(0);
|
|
1733
|
-
}
|
|
1740
|
+
if (Ct(key))
|
|
1741
|
+
abort();
|
|
1734
1742
|
return key;
|
|
1735
1743
|
}
|
|
1736
1744
|
function configureTemplate(targetDir, cms, projectName) {
|
|
@@ -1862,10 +1870,8 @@ async function main() {
|
|
|
1862
1870
|
return "Use lowercase letters, numbers, and hyphens only";
|
|
1863
1871
|
}
|
|
1864
1872
|
});
|
|
1865
|
-
if (Ct(projectName))
|
|
1866
|
-
|
|
1867
|
-
process.exit(0);
|
|
1868
|
-
}
|
|
1873
|
+
if (Ct(projectName))
|
|
1874
|
+
abort();
|
|
1869
1875
|
const cms = await Je({
|
|
1870
1876
|
message: "Which CMS do you want to use?",
|
|
1871
1877
|
options: [
|
|
@@ -1881,19 +1887,19 @@ async function main() {
|
|
|
1881
1887
|
}
|
|
1882
1888
|
]
|
|
1883
1889
|
});
|
|
1884
|
-
if (Ct(cms))
|
|
1885
|
-
|
|
1886
|
-
process.exit(0);
|
|
1887
|
-
}
|
|
1890
|
+
if (Ct(cms))
|
|
1891
|
+
abort();
|
|
1888
1892
|
const targetDir = path.resolve(process.cwd(), projectName);
|
|
1889
1893
|
if (fs.existsSync(targetDir)) {
|
|
1890
1894
|
Ne(`Directory ${import_picocolors3.default.cyan(projectName)} already exists.`);
|
|
1891
1895
|
process.exit(1);
|
|
1892
1896
|
}
|
|
1893
1897
|
const s = bt2();
|
|
1898
|
+
await ensureBrew(s);
|
|
1894
1899
|
s.start("Cloning sitekick-starter...");
|
|
1895
1900
|
execSync(`git clone --depth 1 https://github.com/sitekickcodes/sitekick-starter.git ${targetDir}`, { stdio: "pipe" });
|
|
1896
1901
|
fs.rmSync(path.join(targetDir, ".git"), { recursive: true, force: true });
|
|
1902
|
+
scaffoldedDir = targetDir;
|
|
1897
1903
|
s.stop("Cloned template");
|
|
1898
1904
|
s.start(`Configuring for ${cms === "payload" ? "Payload CMS" : "Sanity"}...`);
|
|
1899
1905
|
configureTemplate(targetDir, cms, projectName);
|