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.
Files changed (2) hide show
  1. package/dist/index.js +84 -38
  2. 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.45";
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 spinner = ora4("Creating Next.js project...").start();
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
- spinner.succeed("Next.js project created");
1280
+ ora4().succeed("Next.js project created");
1261
1281
  } catch (error) {
1262
- spinner.fail("Failed to create Next.js project");
1263
- logger.error(String(error));
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" ? "pnpx" : pm === "yarn" ? "yarn dlx" : "bunx";
1284
- const shadcnArgs = pm === "yarn" ? ["shadcn@latest", "init", "--yes", "--defaults"] : ["shadcn@latest", "init", "--yes", "--defaults"];
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
- shadcnSpinner.succeed("shadcn/ui initialized");
1335
+ ora4().succeed("shadcn/ui initialized");
1290
1336
  } catch (error) {
1291
- shadcnSpinner.warn("Failed to initialize shadcn/ui (you can run `npx shadcn@latest init` later)");
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((resolve2, reject) => {
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
- resolve2(readFileSync3(filePath, "utf-8").trim());
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((resolve2) => setTimeout(resolve2, 500));
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((resolve2) => {
1599
+ await new Promise((resolve3) => {
1554
1600
  const keepAlive = setInterval(() => {
1555
1601
  }, 1e6);
1556
1602
  process.once("beforeExit", () => {
1557
1603
  clearInterval(keepAlive);
1558
- resolve2();
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((resolve2) => setTimeout(resolve2, 500));
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((resolve2) => {
1719
+ await new Promise((resolve3) => {
1674
1720
  const keepAlive = setInterval(() => {
1675
1721
  }, 1e6);
1676
1722
  process.once("beforeExit", () => {
1677
1723
  clearInterval(keepAlive);
1678
- resolve2();
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((resolve2, reject) => {
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
- resolve2();
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((resolve2) => {
2622
+ return new Promise((resolve3) => {
2577
2623
  const server = net.createServer();
2578
2624
  server.once("error", () => {
2579
2625
  server.close();
2580
- resolve2(false);
2626
+ resolve3(false);
2581
2627
  });
2582
2628
  server.once("listening", () => {
2583
2629
  server.close();
2584
- resolve2(true);
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((resolve2, reject) => {
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
- resolve2();
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((resolve2, reject) => {
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
- resolve2();
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 dirname2 } from "path";
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 = dirname2(__filename);
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 = resolve(cwd, file);
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 = resolve(cwd, file);
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.45",
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.42"
81
+ "@spfn/core": "0.2.0-beta.45"
82
82
  },
83
83
  "scripts": {
84
84
  "build": "tsup && node scripts/copy-templates.js",