spfn 0.2.0-beta.45 → 0.2.0-beta.46
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 +84 -38
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -755,7 +755,7 @@ var init_deployment_config = __esm({
|
|
|
755
755
|
|
|
756
756
|
// src/utils/version.ts
|
|
757
757
|
function getCliVersion() {
|
|
758
|
-
return "0.2.0-beta.
|
|
758
|
+
return "0.2.0-beta.46";
|
|
759
759
|
}
|
|
760
760
|
function getTagFromVersion(version) {
|
|
761
761
|
const match = version.match(/-([a-z]+)\./i);
|
|
@@ -1197,11 +1197,23 @@ init_logger();
|
|
|
1197
1197
|
init_package_manager();
|
|
1198
1198
|
import { Command as Command3 } from "commander";
|
|
1199
1199
|
import { existsSync as existsSync10 } from "fs";
|
|
1200
|
-
import { join as join10 } from "path";
|
|
1200
|
+
import { join as join10, resolve, dirname as dirname2 } from "path";
|
|
1201
1201
|
import prompts2 from "prompts";
|
|
1202
1202
|
import ora4 from "ora";
|
|
1203
1203
|
import { execa as execa3 } from "execa";
|
|
1204
1204
|
import chalk4 from "chalk";
|
|
1205
|
+
function findPnpmWorkspaceRoot(startDir) {
|
|
1206
|
+
let dir = resolve(startDir);
|
|
1207
|
+
while (true) {
|
|
1208
|
+
if (existsSync10(join10(dir, "pnpm-workspace.yaml"))) {
|
|
1209
|
+
return dir;
|
|
1210
|
+
}
|
|
1211
|
+
const parent = dirname2(dir);
|
|
1212
|
+
if (parent === dir) break;
|
|
1213
|
+
dir = parent;
|
|
1214
|
+
}
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1205
1217
|
async function createProject(projectName, options) {
|
|
1206
1218
|
const cwd = process.cwd();
|
|
1207
1219
|
const projectPath = join10(cwd, projectName);
|
|
@@ -1230,7 +1242,11 @@ async function createProject(projectName, options) {
|
|
|
1230
1242
|
pm = selectedPm;
|
|
1231
1243
|
}
|
|
1232
1244
|
logger.step(`Using package manager: ${pm}`);
|
|
1233
|
-
const
|
|
1245
|
+
const workspaceRoot = pm === "pnpm" ? findPnpmWorkspaceRoot(cwd) : null;
|
|
1246
|
+
const isInWorkspace = workspaceRoot !== null;
|
|
1247
|
+
if (isInWorkspace) {
|
|
1248
|
+
logger.info(`Detected pnpm workspace at ${workspaceRoot}`);
|
|
1249
|
+
}
|
|
1234
1250
|
try {
|
|
1235
1251
|
const createNextAppArgs = [
|
|
1236
1252
|
"create-next-app@latest",
|
|
@@ -1242,10 +1258,11 @@ async function createProject(projectName, options) {
|
|
|
1242
1258
|
"@/*",
|
|
1243
1259
|
"--tailwind",
|
|
1244
1260
|
"--no-eslint",
|
|
1245
|
-
"--yes"
|
|
1261
|
+
"--yes",
|
|
1246
1262
|
// Skip prompts
|
|
1263
|
+
`--use-${pm}`
|
|
1247
1264
|
];
|
|
1248
|
-
if (options.skipInstall) {
|
|
1265
|
+
if (options.skipInstall || isInWorkspace) {
|
|
1249
1266
|
createNextAppArgs.push("--skip-install");
|
|
1250
1267
|
}
|
|
1251
1268
|
if (options.skipGit) {
|
|
@@ -1253,16 +1270,43 @@ async function createProject(projectName, options) {
|
|
|
1253
1270
|
}
|
|
1254
1271
|
const createCommand2 = pm === "npm" ? "npx" : pm === "yarn" ? "yarn" : pm === "pnpm" ? "pnpm" : "bunx";
|
|
1255
1272
|
const createArgs = createCommand2 === "npx" ? createNextAppArgs : ["dlx", ...createNextAppArgs];
|
|
1273
|
+
logger.step("Running create-next-app...");
|
|
1256
1274
|
await execa3(createCommand2, createArgs, {
|
|
1257
1275
|
cwd,
|
|
1258
|
-
stdio: "inherit"
|
|
1276
|
+
stdio: "inherit",
|
|
1277
|
+
timeout: 3e5
|
|
1278
|
+
// 5 minutes
|
|
1259
1279
|
});
|
|
1260
|
-
|
|
1280
|
+
ora4().succeed("Next.js project created");
|
|
1261
1281
|
} catch (error) {
|
|
1262
|
-
|
|
1263
|
-
|
|
1282
|
+
ora4().fail("Failed to create Next.js project");
|
|
1283
|
+
if (error.exitCode != null) {
|
|
1284
|
+
logger.error(`create-next-app exited with code ${error.exitCode}`);
|
|
1285
|
+
}
|
|
1286
|
+
if (error.stderr) {
|
|
1287
|
+
logger.error(error.stderr);
|
|
1288
|
+
} else {
|
|
1289
|
+
logger.error(String(error));
|
|
1290
|
+
}
|
|
1264
1291
|
process.exit(1);
|
|
1265
1292
|
}
|
|
1293
|
+
if (isInWorkspace && !options.skipInstall) {
|
|
1294
|
+
const installSpinner = ora4("Installing dependencies from workspace root...").start();
|
|
1295
|
+
try {
|
|
1296
|
+
await execa3("pnpm", ["install"], {
|
|
1297
|
+
cwd: workspaceRoot,
|
|
1298
|
+
stdio: "pipe",
|
|
1299
|
+
timeout: 3e5
|
|
1300
|
+
});
|
|
1301
|
+
installSpinner.succeed("Dependencies installed");
|
|
1302
|
+
} catch (error) {
|
|
1303
|
+
installSpinner.fail("Failed to install dependencies");
|
|
1304
|
+
logger.error("Run `pnpm install` from workspace root manually.");
|
|
1305
|
+
if (error.stderr) {
|
|
1306
|
+
logger.error(error.stderr);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1266
1310
|
process.chdir(projectPath);
|
|
1267
1311
|
logger.info(`
|
|
1268
1312
|
\u{1F4C2} Changed directory to ${projectName}
|
|
@@ -1270,7 +1314,7 @@ async function createProject(projectName, options) {
|
|
|
1270
1314
|
const iconsSpinner = ora4("Setting up SVGR for icon management...").start();
|
|
1271
1315
|
try {
|
|
1272
1316
|
const installArgs = pm === "npm" ? ["install", "--save-dev", "@svgr/webpack"] : pm === "yarn" ? ["add", "-D", "@svgr/webpack"] : pm === "pnpm" ? ["add", "-D", "@svgr/webpack"] : ["add", "-d", "@svgr/webpack"];
|
|
1273
|
-
await execa3(pm, installArgs, { cwd: projectPath });
|
|
1317
|
+
await execa3(pm, installArgs, { cwd: projectPath, timeout: 12e4 });
|
|
1274
1318
|
const { setupIcons: setupIcons2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
1275
1319
|
await setupIcons2();
|
|
1276
1320
|
iconsSpinner.succeed("SVGR setup completed");
|
|
@@ -1278,17 +1322,19 @@ async function createProject(projectName, options) {
|
|
|
1278
1322
|
iconsSpinner.warn("Failed to setup SVGR (you can run `spfn setup icons` later)");
|
|
1279
1323
|
}
|
|
1280
1324
|
if (options.shadcn) {
|
|
1281
|
-
const shadcnSpinner = ora4("Setting up shadcn/ui...").start();
|
|
1282
1325
|
try {
|
|
1283
|
-
const shadcnCommand = pm === "npm" ? "npx" : pm === "pnpm" ? "
|
|
1284
|
-
const
|
|
1326
|
+
const shadcnCommand = pm === "npm" ? "npx" : pm === "pnpm" ? "pnpm" : pm === "yarn" ? "yarn" : "bunx";
|
|
1327
|
+
const shadcnBaseArgs = ["dlx", "shadcn@latest", "init", "--yes", "--defaults"];
|
|
1328
|
+
const shadcnArgs = shadcnCommand === "npx" ? ["shadcn@latest", "init", "--yes", "--defaults"] : shadcnBaseArgs;
|
|
1329
|
+
logger.step("Setting up shadcn/ui...");
|
|
1285
1330
|
await execa3(shadcnCommand, shadcnArgs, {
|
|
1286
1331
|
cwd: projectPath,
|
|
1287
|
-
stdio: "inherit"
|
|
1332
|
+
stdio: "inherit",
|
|
1333
|
+
timeout: 3e5
|
|
1288
1334
|
});
|
|
1289
|
-
|
|
1335
|
+
ora4().succeed("shadcn/ui initialized");
|
|
1290
1336
|
} catch (error) {
|
|
1291
|
-
|
|
1337
|
+
ora4().warn("Failed to initialize shadcn/ui (you can run `npx shadcn@latest init` later)");
|
|
1292
1338
|
}
|
|
1293
1339
|
}
|
|
1294
1340
|
const initSpinner = ora4("Initializing SPFN...").start();
|
|
@@ -1339,7 +1385,7 @@ import { join as join11 } from "path";
|
|
|
1339
1385
|
import { execa as execa4 } from "execa";
|
|
1340
1386
|
import chokidar from "chokidar";
|
|
1341
1387
|
function waitForReadyFile(filePath, timeoutMs = 3e4) {
|
|
1342
|
-
return new Promise((
|
|
1388
|
+
return new Promise((resolve3, reject) => {
|
|
1343
1389
|
if (existsSync11(filePath)) {
|
|
1344
1390
|
unlinkSync(filePath);
|
|
1345
1391
|
}
|
|
@@ -1353,7 +1399,7 @@ function waitForReadyFile(filePath, timeoutMs = 3e4) {
|
|
|
1353
1399
|
if (name === fileName && existsSync11(filePath)) {
|
|
1354
1400
|
watcher.close();
|
|
1355
1401
|
clearTimeout(timer);
|
|
1356
|
-
|
|
1402
|
+
resolve3(readFileSync3(filePath, "utf-8").trim());
|
|
1357
1403
|
}
|
|
1358
1404
|
});
|
|
1359
1405
|
});
|
|
@@ -1506,7 +1552,7 @@ catch (error)
|
|
|
1506
1552
|
serverProcess2.kill("SIGTERM");
|
|
1507
1553
|
await serverProcess2.catch(() => {
|
|
1508
1554
|
});
|
|
1509
|
-
await new Promise((
|
|
1555
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
1510
1556
|
} catch (error) {
|
|
1511
1557
|
}
|
|
1512
1558
|
}
|
|
@@ -1550,12 +1596,12 @@ catch (error)
|
|
|
1550
1596
|
process.on("SIGTERM", cleanup2);
|
|
1551
1597
|
startWatcher2();
|
|
1552
1598
|
startServer2();
|
|
1553
|
-
await new Promise((
|
|
1599
|
+
await new Promise((resolve3) => {
|
|
1554
1600
|
const keepAlive = setInterval(() => {
|
|
1555
1601
|
}, 1e6);
|
|
1556
1602
|
process.once("beforeExit", () => {
|
|
1557
1603
|
clearInterval(keepAlive);
|
|
1558
|
-
|
|
1604
|
+
resolve3();
|
|
1559
1605
|
});
|
|
1560
1606
|
});
|
|
1561
1607
|
return;
|
|
@@ -1615,7 +1661,7 @@ catch (error)
|
|
|
1615
1661
|
serverProcess.kill("SIGTERM");
|
|
1616
1662
|
await serverProcess.catch(() => {
|
|
1617
1663
|
});
|
|
1618
|
-
await new Promise((
|
|
1664
|
+
await new Promise((resolve3) => setTimeout(resolve3, 500));
|
|
1619
1665
|
} catch (error) {
|
|
1620
1666
|
}
|
|
1621
1667
|
}
|
|
@@ -1670,12 +1716,12 @@ catch (error)
|
|
|
1670
1716
|
logger.warn(`[SPFN] Server readiness check timed out, starting Next.js anyway...`);
|
|
1671
1717
|
}
|
|
1672
1718
|
startNext();
|
|
1673
|
-
await new Promise((
|
|
1719
|
+
await new Promise((resolve3) => {
|
|
1674
1720
|
const keepAlive = setInterval(() => {
|
|
1675
1721
|
}, 1e6);
|
|
1676
1722
|
process.once("beforeExit", () => {
|
|
1677
1723
|
clearInterval(keepAlive);
|
|
1678
|
-
|
|
1724
|
+
resolve3();
|
|
1679
1725
|
});
|
|
1680
1726
|
});
|
|
1681
1727
|
});
|
|
@@ -2228,7 +2274,7 @@ async function runDrizzleCommand(command) {
|
|
|
2228
2274
|
}
|
|
2229
2275
|
const args = command.split(" ");
|
|
2230
2276
|
args.push(`--config=${configPath}`);
|
|
2231
|
-
return new Promise((
|
|
2277
|
+
return new Promise((resolve3, reject) => {
|
|
2232
2278
|
const drizzleProcess = spawn("drizzle-kit", args, {
|
|
2233
2279
|
stdio: "inherit",
|
|
2234
2280
|
// Allow interactive input
|
|
@@ -2243,7 +2289,7 @@ async function runDrizzleCommand(command) {
|
|
|
2243
2289
|
drizzleProcess.on("close", (code) => {
|
|
2244
2290
|
cleanup();
|
|
2245
2291
|
if (code === 0) {
|
|
2246
|
-
|
|
2292
|
+
resolve3();
|
|
2247
2293
|
} else {
|
|
2248
2294
|
reject(new Error(`drizzle-kit ${command} exited with code ${code}`));
|
|
2249
2295
|
}
|
|
@@ -2573,15 +2619,15 @@ function parseDatabaseUrl(dbUrl) {
|
|
|
2573
2619
|
}
|
|
2574
2620
|
}
|
|
2575
2621
|
async function isPortAvailable(port) {
|
|
2576
|
-
return new Promise((
|
|
2622
|
+
return new Promise((resolve3) => {
|
|
2577
2623
|
const server = net.createServer();
|
|
2578
2624
|
server.once("error", () => {
|
|
2579
2625
|
server.close();
|
|
2580
|
-
|
|
2626
|
+
resolve3(false);
|
|
2581
2627
|
});
|
|
2582
2628
|
server.once("listening", () => {
|
|
2583
2629
|
server.close();
|
|
2584
|
-
|
|
2630
|
+
resolve3(true);
|
|
2585
2631
|
});
|
|
2586
2632
|
server.listen(port, "127.0.0.1");
|
|
2587
2633
|
});
|
|
@@ -2837,7 +2883,7 @@ async function dbBackup(options) {
|
|
|
2837
2883
|
pgDump.stderr?.on("data", (data) => {
|
|
2838
2884
|
errorOutput += data.toString();
|
|
2839
2885
|
});
|
|
2840
|
-
await new Promise((
|
|
2886
|
+
await new Promise((resolve3, reject) => {
|
|
2841
2887
|
pgDump.on("close", async (code) => {
|
|
2842
2888
|
if (code === 0) {
|
|
2843
2889
|
try {
|
|
@@ -2874,7 +2920,7 @@ async function dbBackup(options) {
|
|
|
2874
2920
|
tags: tags.length > 0 ? tags : void 0
|
|
2875
2921
|
};
|
|
2876
2922
|
await saveBackupMetadata(metadata, filename);
|
|
2877
|
-
|
|
2923
|
+
resolve3();
|
|
2878
2924
|
} catch (error) {
|
|
2879
2925
|
reject(error);
|
|
2880
2926
|
}
|
|
@@ -3263,7 +3309,7 @@ async function dbRestore(backupFile, options = {}) {
|
|
|
3263
3309
|
spinner.start();
|
|
3264
3310
|
}
|
|
3265
3311
|
});
|
|
3266
|
-
await new Promise((
|
|
3312
|
+
await new Promise((resolve3, reject) => {
|
|
3267
3313
|
restoreProcess.on("close", (code) => {
|
|
3268
3314
|
if (code === 0) {
|
|
3269
3315
|
const summary = objectCount > 0 ? ` (${objectCount} objects)` : "";
|
|
@@ -3277,7 +3323,7 @@ async function dbRestore(backupFile, options = {}) {
|
|
|
3277
3323
|
}
|
|
3278
3324
|
}
|
|
3279
3325
|
console.log(chalk21.green("\n\u2705 Database restored successfully"));
|
|
3280
|
-
|
|
3326
|
+
resolve3();
|
|
3281
3327
|
} else {
|
|
3282
3328
|
spinner.fail("Restore failed");
|
|
3283
3329
|
if (errors.length > 0) {
|
|
@@ -3735,11 +3781,11 @@ function toSafeSchemaName(str) {
|
|
|
3735
3781
|
|
|
3736
3782
|
// src/commands/generate/template-loader.ts
|
|
3737
3783
|
import { readFileSync as readFileSync8, existsSync as existsSync22 } from "fs";
|
|
3738
|
-
import { join as join19, dirname as
|
|
3784
|
+
import { join as join19, dirname as dirname3 } from "path";
|
|
3739
3785
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3740
3786
|
function findTemplatesPath2() {
|
|
3741
3787
|
const __filename = fileURLToPath2(import.meta.url);
|
|
3742
|
-
const __dirname2 =
|
|
3788
|
+
const __dirname2 = dirname3(__filename);
|
|
3743
3789
|
const distPath = join19(__dirname2, "commands", "generate", "templates");
|
|
3744
3790
|
if (existsSync22(distPath)) {
|
|
3745
3791
|
return distPath;
|
|
@@ -4919,7 +4965,7 @@ generateCommand.command("fn").description("Generate a new SPFN function module")
|
|
|
4919
4965
|
import { Command as Command12 } from "commander";
|
|
4920
4966
|
import chalk28 from "chalk";
|
|
4921
4967
|
import { existsSync as existsSync25, readFileSync as readFileSync9, writeFileSync as writeFileSync19 } from "fs";
|
|
4922
|
-
import { resolve } from "path";
|
|
4968
|
+
import { resolve as resolve2 } from "path";
|
|
4923
4969
|
import { parse } from "dotenv";
|
|
4924
4970
|
var VALID_ENVS = ["local", "development", "staging", "production", "test"];
|
|
4925
4971
|
var BASE_ENV_FILES = {
|
|
@@ -5201,7 +5247,7 @@ async function initEnvFiles(options) {
|
|
|
5201
5247
|
}
|
|
5202
5248
|
}
|
|
5203
5249
|
function writeEnvTemplate(cwd, file, vars, force) {
|
|
5204
|
-
const filePath =
|
|
5250
|
+
const filePath = resolve2(cwd, file);
|
|
5205
5251
|
if (existsSync25(filePath) && !force) {
|
|
5206
5252
|
console.log(chalk28.yellow(` \u23ED\uFE0F ${file} already exists (use --force to overwrite)`));
|
|
5207
5253
|
return;
|
|
@@ -5250,7 +5296,7 @@ async function checkEnvFiles(options) {
|
|
|
5250
5296
|
const issues = [];
|
|
5251
5297
|
const warnings = [];
|
|
5252
5298
|
for (const file of filesToCheck) {
|
|
5253
|
-
const filePath =
|
|
5299
|
+
const filePath = resolve2(cwd, file);
|
|
5254
5300
|
if (!existsSync25(filePath)) {
|
|
5255
5301
|
continue;
|
|
5256
5302
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spfn",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.46",
|
|
4
4
|
"description": "Superfunction CLI - Add SPFN to your Next.js project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"concurrently": "^9.2.1",
|
|
79
79
|
"tsx": "^4.20.6",
|
|
80
80
|
"typescript": "^5.3.3",
|
|
81
|
-
"@spfn/core": "0.2.0-beta.
|
|
81
|
+
"@spfn/core": "0.2.0-beta.45"
|
|
82
82
|
},
|
|
83
83
|
"scripts": {
|
|
84
84
|
"build": "tsup && node scripts/copy-templates.js",
|