create-nextly-app 0.0.2-alpha.4 → 0.0.2-alpha.6

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/cli.cjs CHANGED
@@ -6259,7 +6259,7 @@ var require_package = __commonJS({
6259
6259
  "package.json"(exports$1, module) {
6260
6260
  module.exports = {
6261
6261
  name: "create-nextly-app",
6262
- version: "0.0.2-alpha.4",
6262
+ version: "0.0.2-alpha.6",
6263
6263
  description: "CLI to scaffold Nextly in your Next.js project",
6264
6264
  license: "MIT",
6265
6265
  type: "module",
@@ -21581,9 +21581,6 @@ var import_fs_extra = __toESM(require_lib());
21581
21581
  var ADMIN_PAGE_TEMPLATE = `"use client";
21582
21582
 
21583
21583
  import "@nextlyhq/admin/style.css";
21584
- import "@nextlyhq/plugin-form-builder/admin";
21585
- import "@nextlyhq/plugin-form-builder/styles/builder.css";
21586
- import "@nextlyhq/plugin-form-builder/styles/submissions-filter.css";
21587
21584
  import { RootLayout, QueryProvider, ErrorBoundary } from "@nextlyhq/admin";
21588
21585
 
21589
21586
  export default function AdminPage() {
@@ -28434,6 +28431,316 @@ createExeca(mapNode);
28434
28431
  createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
28435
28432
  getIpcExport();
28436
28433
 
28434
+ // src/utils/template.ts
28435
+ var import_fs_extra8 = __toESM(require_lib());
28436
+ var PROJECT_TYPES_WITH_FORM_BUILDER = /* @__PURE__ */ new Set([
28437
+ "blog"
28438
+ ]);
28439
+ function projectUsesFormBuilder(projectType) {
28440
+ return PROJECT_TYPES_WITH_FORM_BUILDER.has(projectType);
28441
+ }
28442
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
28443
+ ".ts",
28444
+ ".tsx",
28445
+ ".js",
28446
+ ".jsx",
28447
+ ".json",
28448
+ ".env",
28449
+ ".md",
28450
+ ".css",
28451
+ ".html",
28452
+ ".mjs",
28453
+ ".cjs"
28454
+ ]);
28455
+ var SKIP_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", ".gitkeep"]);
28456
+ function resolveTemplatePath(localTemplatePath) {
28457
+ const __dirname = path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))));
28458
+ const fromDist = path__default.default.resolve(__dirname, "../templates");
28459
+ if (import_fs_extra8.default.existsSync(fromDist)) {
28460
+ return fromDist;
28461
+ }
28462
+ const fromSrc = path__default.default.resolve(__dirname, "../../templates");
28463
+ if (import_fs_extra8.default.existsSync(fromSrc)) {
28464
+ return fromSrc;
28465
+ }
28466
+ throw new Error(
28467
+ "Could not find templates directory. Use --local-template to specify the templates path, or ensure templates are bundled."
28468
+ );
28469
+ }
28470
+ function buildPlaceholderMap(options) {
28471
+ const { database, databaseUrl } = options;
28472
+ return {
28473
+ "{{databaseDialect}}": database.type,
28474
+ "{{databaseUrl}}": databaseUrl || database.envExample
28475
+ };
28476
+ }
28477
+ async function replacePlaceholdersInFile(filePath, placeholders) {
28478
+ const ext = path__default.default.extname(filePath).toLowerCase();
28479
+ const basename = path__default.default.basename(filePath);
28480
+ const isTextFile = TEXT_EXTENSIONS.has(ext) || basename.startsWith(".env") || basename === ".gitignore";
28481
+ if (!isTextFile) return;
28482
+ let content = await import_fs_extra8.default.readFile(filePath, "utf-8");
28483
+ let changed = false;
28484
+ for (const [placeholder, value] of Object.entries(placeholders)) {
28485
+ if (content.includes(placeholder)) {
28486
+ content = content.replaceAll(placeholder, value);
28487
+ changed = true;
28488
+ }
28489
+ }
28490
+ if (changed) {
28491
+ await import_fs_extra8.default.writeFile(filePath, content, "utf-8");
28492
+ }
28493
+ }
28494
+ async function replacePlaceholders(dir, placeholders) {
28495
+ const entries = await import_fs_extra8.default.readdir(dir, { withFileTypes: true });
28496
+ for (const entry of entries) {
28497
+ const fullPath = path__default.default.join(dir, entry.name);
28498
+ if (entry.isDirectory()) {
28499
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
28500
+ await replacePlaceholders(fullPath, placeholders);
28501
+ } else if (entry.isFile()) {
28502
+ await replacePlaceholdersInFile(fullPath, placeholders);
28503
+ }
28504
+ }
28505
+ }
28506
+ var PINNED_VERSIONS = {
28507
+ // Next.js ecosystem — resolved at runtime via fetchLatestVersion()
28508
+ // (see generatePackageJson)
28509
+ react: "^19.1.0",
28510
+ "react-dom": "^19.1.0",
28511
+ // Dev dependencies
28512
+ typescript: "^5",
28513
+ "@types/node": "^20",
28514
+ "@types/react": "^19",
28515
+ "@types/react-dom": "^19",
28516
+ "@tailwindcss/postcss": "^4",
28517
+ tailwindcss: "^4",
28518
+ eslint: "^9"
28519
+ };
28520
+ var RUNTIME_RESOLVED_PACKAGES = ["next", "eslint-config-next"];
28521
+ var NEXTLY_PACKAGES = [
28522
+ "nextly",
28523
+ "@nextlyhq/admin",
28524
+ "@nextlyhq/adapter-drizzle",
28525
+ "@nextlyhq/adapter-postgres",
28526
+ "@nextlyhq/adapter-mysql",
28527
+ "@nextlyhq/adapter-sqlite"
28528
+ ];
28529
+ var resolvedNextlyVersions = null;
28530
+ async function fetchLatestVersion(pkg2) {
28531
+ try {
28532
+ const res = await fetch(
28533
+ `https://registry.npmjs.org/-/package/${encodeURIComponent(pkg2)}/dist-tags`,
28534
+ { signal: AbortSignal.timeout(5e3) }
28535
+ );
28536
+ if (!res.ok) return "latest";
28537
+ const data = await res.json();
28538
+ return data.latest ? `^${data.latest}` : "latest";
28539
+ } catch {
28540
+ return "latest";
28541
+ }
28542
+ }
28543
+ async function resolveNextlyVersions() {
28544
+ if (resolvedNextlyVersions) return resolvedNextlyVersions;
28545
+ const entries = await Promise.all(
28546
+ NEXTLY_PACKAGES.map(
28547
+ async (pkg2) => [pkg2, await fetchLatestVersion(pkg2)]
28548
+ )
28549
+ );
28550
+ resolvedNextlyVersions = Object.fromEntries(entries);
28551
+ return resolvedNextlyVersions;
28552
+ }
28553
+ var resolvedRuntimeVersions = null;
28554
+ async function resolveRuntimeVersions() {
28555
+ if (resolvedRuntimeVersions) return resolvedRuntimeVersions;
28556
+ const FALLBACKS = {
28557
+ next: "^16.1.0",
28558
+ "eslint-config-next": "^16.1.0"
28559
+ };
28560
+ const entries = await Promise.all(
28561
+ RUNTIME_RESOLVED_PACKAGES.map(async (pkg2) => {
28562
+ const version2 = await fetchLatestVersion(pkg2);
28563
+ return [pkg2, version2 === "latest" ? FALLBACKS[pkg2] : version2];
28564
+ })
28565
+ );
28566
+ resolvedRuntimeVersions = Object.fromEntries(entries);
28567
+ return resolvedRuntimeVersions;
28568
+ }
28569
+ async function generatePackageJson(projectName, database, useYalc = false, projectType = "blank") {
28570
+ const runtimeVersions = await resolveRuntimeVersions();
28571
+ const dependencies = {
28572
+ next: runtimeVersions.next,
28573
+ react: PINNED_VERSIONS.react,
28574
+ "react-dom": PINNED_VERSIONS["react-dom"]
28575
+ };
28576
+ dependencies["@tanstack/react-query"] = "^5.62.0";
28577
+ if (!useYalc) {
28578
+ const versions = await resolveNextlyVersions();
28579
+ dependencies["nextly"] = versions["nextly"];
28580
+ dependencies["@nextlyhq/admin"] = versions["@nextlyhq/admin"];
28581
+ dependencies["@nextlyhq/ui"] = versions["@nextlyhq/ui"] || "latest";
28582
+ dependencies["@nextlyhq/adapter-drizzle"] = versions["@nextlyhq/adapter-drizzle"];
28583
+ dependencies[database.adapter] = versions[database.adapter] || "latest";
28584
+ if (projectUsesFormBuilder(projectType)) {
28585
+ dependencies["@nextlyhq/plugin-form-builder"] = versions["@nextlyhq/plugin-form-builder"] || "latest";
28586
+ }
28587
+ }
28588
+ const devDependencies = {
28589
+ typescript: PINNED_VERSIONS.typescript,
28590
+ "@types/node": PINNED_VERSIONS["@types/node"],
28591
+ "@types/react": PINNED_VERSIONS["@types/react"],
28592
+ "@types/react-dom": PINNED_VERSIONS["@types/react-dom"],
28593
+ "@tailwindcss/postcss": PINNED_VERSIONS["@tailwindcss/postcss"],
28594
+ tailwindcss: PINNED_VERSIONS.tailwindcss,
28595
+ eslint: PINNED_VERSIONS.eslint,
28596
+ "eslint-config-next": runtimeVersions["eslint-config-next"],
28597
+ // Pagefind powers /search in the blog template. Zero-config
28598
+ // static index generated at `next build` time. Templates that
28599
+ // don't ship a /search page simply won't invoke it.
28600
+ pagefind: "^1.1.0"
28601
+ };
28602
+ const pkg2 = {
28603
+ name: projectName,
28604
+ version: "0.1.0",
28605
+ private: true,
28606
+ scripts: {
28607
+ // F1 PR 4: dev now boots Nextly in single-process mode via `next dev`.
28608
+ // The lazy drizzle-kit/api import (PR 1) plus the in-process HMR
28609
+ // listener (PR 2) replaced the wrapper that previously owned the
28610
+ // terminal, schema prompts, and child supervision. `nextly dev` is
28611
+ // gone; the only supported dev command is the standard `next dev`.
28612
+ dev: "next dev --turbopack",
28613
+ // Build: migrate DB + compile Next.js + (if present) generate
28614
+ // the Pagefind search index. Templates without the search
28615
+ // script silently skip the last step.
28616
+ build: "nextly migrate && next build && (test -f scripts/build-search-index.mjs && node scripts/build-search-index.mjs || true)",
28617
+ "search:index": "node scripts/build-search-index.mjs",
28618
+ start: "next start",
28619
+ lint: "next lint",
28620
+ nextly: "nextly",
28621
+ // First-time setup: sync schema + seed system permissions. Demo
28622
+ // content is seeded separately from the admin UI (visit /welcome
28623
+ // after running `pnpm dev` and completing /admin/setup).
28624
+ "db:setup": "nextly db:sync",
28625
+ "db:migrate": "nextly migrate",
28626
+ "db:migrate:status": "nextly migrate:status",
28627
+ "db:migrate:fresh": "nextly migrate:fresh",
28628
+ "db:migrate:reset": "nextly migrate:reset",
28629
+ "types:generate": "nextly generate:types"
28630
+ },
28631
+ dependencies,
28632
+ devDependencies
28633
+ };
28634
+ return JSON.stringify(pkg2, null, 2) + "\n";
28635
+ }
28636
+ async function copyTemplate(options) {
28637
+ const {
28638
+ projectName,
28639
+ projectType,
28640
+ targetDir,
28641
+ database,
28642
+ databaseUrl,
28643
+ useYalc = false,
28644
+ approach,
28645
+ templateSource
28646
+ } = options;
28647
+ if (targetDir !== process.cwd() && await import_fs_extra8.default.pathExists(targetDir)) {
28648
+ throw new Error(
28649
+ `Directory "${path__default.default.basename(targetDir)}" already exists. Please choose a different name.`
28650
+ );
28651
+ }
28652
+ let baseDir;
28653
+ let typeDir;
28654
+ if (templateSource) {
28655
+ baseDir = templateSource.basePath;
28656
+ typeDir = templateSource.templatePath;
28657
+ } else {
28658
+ const templatesRoot = resolveTemplatePath();
28659
+ baseDir = path__default.default.join(templatesRoot, "base");
28660
+ typeDir = path__default.default.join(templatesRoot, projectType);
28661
+ }
28662
+ if (!await import_fs_extra8.default.pathExists(baseDir)) {
28663
+ throw new Error(
28664
+ `Base template not found at ${baseDir}. The package may be corrupted or the download failed.`
28665
+ );
28666
+ }
28667
+ if (!await import_fs_extra8.default.pathExists(typeDir)) {
28668
+ throw new Error(
28669
+ `Template "${projectType}" not found at ${typeDir}. Available templates: blank, blog.`
28670
+ );
28671
+ }
28672
+ await import_fs_extra8.default.copy(baseDir, targetDir, {
28673
+ filter: (_src) => {
28674
+ const basename = path__default.default.basename(_src);
28675
+ return !SKIP_FILES.has(basename);
28676
+ }
28677
+ });
28678
+ const templateSrcDir = path__default.default.join(typeDir, "src");
28679
+ if (await import_fs_extra8.default.pathExists(templateSrcDir)) {
28680
+ await import_fs_extra8.default.copy(templateSrcDir, path__default.default.join(targetDir, "src"), {
28681
+ overwrite: true,
28682
+ filter: (_src) => {
28683
+ const basename = path__default.default.basename(_src);
28684
+ return !SKIP_FILES.has(basename);
28685
+ }
28686
+ });
28687
+ }
28688
+ const templateRootConfig = path__default.default.join(typeDir, "nextly.config.ts");
28689
+ if (await import_fs_extra8.default.pathExists(templateRootConfig)) {
28690
+ await import_fs_extra8.default.copy(
28691
+ templateRootConfig,
28692
+ path__default.default.join(targetDir, "nextly.config.ts"),
28693
+ { overwrite: true }
28694
+ );
28695
+ }
28696
+ const configsDir = path__default.default.join(typeDir, "configs");
28697
+ if (approach && await import_fs_extra8.default.pathExists(configsDir)) {
28698
+ const configFileName = approach === "code-first" ? "codefirst.config.ts" : `${approach}.config.ts`;
28699
+ const configSrc = path__default.default.join(configsDir, configFileName);
28700
+ if (await import_fs_extra8.default.pathExists(configSrc)) {
28701
+ await import_fs_extra8.default.copy(configSrc, path__default.default.join(targetDir, "nextly.config.ts"), {
28702
+ overwrite: true
28703
+ });
28704
+ }
28705
+ const sharedSrc = path__default.default.join(configsDir, "shared.ts");
28706
+ if (await import_fs_extra8.default.pathExists(sharedSrc)) {
28707
+ await import_fs_extra8.default.copy(sharedSrc, path__default.default.join(targetDir, "shared.ts"), {
28708
+ overwrite: true
28709
+ });
28710
+ }
28711
+ }
28712
+ const frontendPagePath = path__default.default.join(
28713
+ targetDir,
28714
+ "src",
28715
+ "app",
28716
+ "(frontend)",
28717
+ "page.tsx"
28718
+ );
28719
+ const basePagePath = path__default.default.join(targetDir, "src", "app", "page.tsx");
28720
+ if (await import_fs_extra8.default.pathExists(frontendPagePath) && await import_fs_extra8.default.pathExists(basePagePath)) {
28721
+ await import_fs_extra8.default.remove(basePagePath);
28722
+ }
28723
+ const packageJsonContent = await generatePackageJson(
28724
+ projectName,
28725
+ database,
28726
+ useYalc,
28727
+ projectType
28728
+ );
28729
+ await import_fs_extra8.default.writeFile(
28730
+ path__default.default.join(targetDir, "package.json"),
28731
+ packageJsonContent,
28732
+ "utf-8"
28733
+ );
28734
+ if (database.type === "sqlite") {
28735
+ await import_fs_extra8.default.ensureDir(path__default.default.join(targetDir, "data"));
28736
+ }
28737
+ const placeholders = buildPlaceholderMap({ database, databaseUrl });
28738
+ if (approach) {
28739
+ placeholders["{{approach}}"] = approach;
28740
+ }
28741
+ await replacePlaceholders(targetDir, placeholders);
28742
+ }
28743
+
28437
28744
  // src/installers/dependencies.ts
28438
28745
  var INSTALL_COMMANDS = {
28439
28746
  npm: ["npm", "install"],
@@ -28453,14 +28760,16 @@ var ALL_ADAPTER_PACKAGES = [
28453
28760
  "@nextlyhq/adapter-mysql",
28454
28761
  "@nextlyhq/adapter-sqlite"
28455
28762
  ];
28456
- var TEMPLATE_PLUGIN_PACKAGES = [
28457
- "@nextlyhq/plugin-form-builder"
28458
- ];
28763
+ var TEMPLATE_PLUGIN_PACKAGES = ["@nextlyhq/plugin-form-builder"];
28764
+ function templatePluginPackages(projectType) {
28765
+ return projectType && projectUsesFormBuilder(projectType) ? TEMPLATE_PLUGIN_PACKAGES : [];
28766
+ }
28459
28767
  function getPackagesToInstall(database) {
28460
28768
  return [...CORE_PACKAGES, database.adapter];
28461
28769
  }
28462
- async function installDependencies(cwd, projectInfo, database, useYalc = false, isFreshProject = false) {
28770
+ async function installDependencies(cwd, projectInfo, database, useYalc = false, isFreshProject = false, projectType) {
28463
28771
  const pm = projectInfo.packageManager;
28772
+ const pluginPackages = templatePluginPackages(projectType);
28464
28773
  if (isFreshProject) {
28465
28774
  if (useYalc) {
28466
28775
  const yalcPackages = [
@@ -28470,7 +28779,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
28470
28779
  "@nextlyhq/ui",
28471
28780
  "@nextlyhq/adapter-drizzle",
28472
28781
  ...ALL_ADAPTER_PACKAGES,
28473
- ...TEMPLATE_PLUGIN_PACKAGES
28782
+ ...pluginPackages
28474
28783
  ])
28475
28784
  ];
28476
28785
  await execa(pm, ["install"], { cwd });
@@ -28491,7 +28800,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
28491
28800
  "@nextlyhq/ui",
28492
28801
  "@nextlyhq/adapter-drizzle",
28493
28802
  ...ALL_ADAPTER_PACKAGES,
28494
- ...TEMPLATE_PLUGIN_PACKAGES
28803
+ ...pluginPackages
28495
28804
  ])
28496
28805
  ];
28497
28806
  for (const pkg2 of yalcPackages) {
@@ -28506,7 +28815,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
28506
28815
  }
28507
28816
 
28508
28817
  // src/lib/download-template.ts
28509
- var import_fs_extra8 = __toESM(require_lib());
28818
+ var import_fs_extra9 = __toESM(require_lib());
28510
28819
  var kr = Object.defineProperty;
28511
28820
  var vr = (s3, t2) => {
28512
28821
  for (var e in t2) kr(s3, e, { get: t2[e], enumerable: true });
@@ -30582,7 +30891,7 @@ var Vn = 512 * 1024;
30582
30891
  var $n = pr | ur | dr | mr;
30583
30892
  var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
30584
30893
  var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
30585
- var fs9 = (s3, t2, e) => {
30894
+ var fs10 = (s3, t2, e) => {
30586
30895
  try {
30587
30896
  return fs__default.default.lchownSync(s3, t2, e);
30588
30897
  } catch (i2) {
@@ -30622,7 +30931,7 @@ var ds = (s3, t2, e, i2) => {
30622
30931
  });
30623
30932
  };
30624
30933
  var qn = (s3, t2, e, i2) => {
30625
- t2.isDirectory() && us(path__default.default.resolve(s3, t2.name), e, i2), fs9(path__default.default.resolve(s3, t2.name), e, i2);
30934
+ t2.isDirectory() && us(path__default.default.resolve(s3, t2.name), e, i2), fs10(path__default.default.resolve(s3, t2.name), e, i2);
30626
30935
  };
30627
30936
  var us = (s3, t2, e) => {
30628
30937
  let i2;
@@ -30631,11 +30940,11 @@ var us = (s3, t2, e) => {
30631
30940
  } catch (r) {
30632
30941
  let n2 = r;
30633
30942
  if (n2?.code === "ENOENT") return;
30634
- if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP") return fs9(s3, t2, e);
30943
+ if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP") return fs10(s3, t2, e);
30635
30944
  throw n2;
30636
30945
  }
30637
30946
  for (let r of i2) qn(s3, r, t2, e);
30638
- return fs9(s3, t2, e);
30947
+ return fs10(s3, t2, e);
30639
30948
  };
30640
30949
  var we2 = class extends Error {
30641
30950
  path;
@@ -31380,7 +31689,7 @@ async function downloadTemplate(templateName, branch = "main") {
31380
31689
  process.env.TMPDIR || "/tmp",
31381
31690
  `nextly-template-${Date.now()}`
31382
31691
  );
31383
- await import_fs_extra8.default.ensureDir(tmpDir);
31692
+ await import_fs_extra9.default.ensureDir(tmpDir);
31384
31693
  const repoPrefix = `${GITHUB_REPO}-${branch}`;
31385
31694
  const baseFilter = `${repoPrefix}/templates/base/`;
31386
31695
  const templateFilter = `${repoPrefix}/templates/${templateName}/`;
@@ -31409,7 +31718,7 @@ async function downloadTemplate(templateName, branch = "main") {
31409
31718
  })
31410
31719
  );
31411
31720
  } catch (error) {
31412
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
31721
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
31413
31722
  });
31414
31723
  if (error instanceof Error && error.name === "TimeoutError") {
31415
31724
  throw new Error(
@@ -31420,15 +31729,15 @@ async function downloadTemplate(templateName, branch = "main") {
31420
31729
  }
31421
31730
  const basePath = path__default.default.join(tmpDir, "templates", "base");
31422
31731
  const templatePath = path__default.default.join(tmpDir, "templates", templateName);
31423
- if (!await import_fs_extra8.default.pathExists(basePath)) {
31424
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
31732
+ if (!await import_fs_extra9.default.pathExists(basePath)) {
31733
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
31425
31734
  });
31426
31735
  throw new Error(
31427
31736
  `Base template not found in downloaded archive. The branch "${branch}" may not contain templates.`
31428
31737
  );
31429
31738
  }
31430
- if (!await import_fs_extra8.default.pathExists(templatePath)) {
31431
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
31739
+ if (!await import_fs_extra9.default.pathExists(templatePath)) {
31740
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
31432
31741
  });
31433
31742
  throw new Error(
31434
31743
  `Template "${templateName}" not found in downloaded archive. Available templates may differ on branch "${branch}".`
@@ -31439,12 +31748,12 @@ async function downloadTemplate(templateName, branch = "main") {
31439
31748
  async function resolveLocalTemplate(localPath, templateName) {
31440
31749
  const basePath = path__default.default.join(localPath, "base");
31441
31750
  const templatePath = path__default.default.join(localPath, templateName);
31442
- if (!await import_fs_extra8.default.pathExists(basePath)) {
31751
+ if (!await import_fs_extra9.default.pathExists(basePath)) {
31443
31752
  throw new Error(
31444
31753
  `Base template not found at ${basePath}. Check the --local-template path points to the templates/ directory.`
31445
31754
  );
31446
31755
  }
31447
- if (!await import_fs_extra8.default.pathExists(templatePath)) {
31756
+ if (!await import_fs_extra9.default.pathExists(templatePath)) {
31448
31757
  throw new Error(
31449
31758
  `Template "${templateName}" not found at ${templatePath}. Check the --local-template path points to the templates/ directory.`
31450
31759
  );
@@ -31462,7 +31771,7 @@ async function cleanupDownload(source) {
31462
31771
  const tmpBase = process.env.TMPDIR || "/tmp";
31463
31772
  if (source.basePath.startsWith(tmpBase)) {
31464
31773
  const extractionRoot = path__default.default.resolve(source.basePath, "../..");
31465
- await import_fs_extra8.default.remove(extractionRoot).catch(() => {
31774
+ await import_fs_extra9.default.remove(extractionRoot).catch(() => {
31466
31775
  });
31467
31776
  }
31468
31777
  }
@@ -31562,419 +31871,118 @@ var DATABASE_LABELS = {
31562
31871
  mysql: {
31563
31872
  label: "MySQL",
31564
31873
  hint: "Popular alternative for production"
31565
- }
31566
- };
31567
-
31568
- // src/prompts/project-name.ts
31569
- var import_fs_extra9 = __toESM(require_lib());
31570
- async function isExistingNextProject(cwd) {
31571
- const packageJsonPath = path__default.default.join(cwd, "package.json");
31572
- if (!await import_fs_extra9.default.pathExists(packageJsonPath)) return false;
31573
- try {
31574
- const packageJson = await import_fs_extra9.default.readJson(packageJsonPath);
31575
- const deps = {
31576
- ...packageJson.dependencies,
31577
- ...packageJson.devDependencies
31578
- };
31579
- return "next" in deps;
31580
- } catch {
31581
- return false;
31582
- }
31583
- }
31584
-
31585
- // src/prompts/template.ts
31586
- var import_picocolors2 = __toESM(require_picocolors2());
31587
- function getTemplatePromptOptions() {
31588
- return [
31589
- {
31590
- value: "blank",
31591
- label: "Blank project",
31592
- hint: "Start fresh with an empty config"
31593
- },
31594
- {
31595
- value: "blog",
31596
- label: "Blog",
31597
- hint: "Posts, authors, categories, clean design"
31598
- },
31599
- {
31600
- value: "_coming_soon",
31601
- label: import_picocolors2.default.dim("More templates coming soon"),
31602
- hint: "website, portfolio, e-commerce"
31603
- }
31604
- ];
31605
- }
31606
- function isValidTemplateSelection(value) {
31607
- return value !== "_coming_soon";
31608
- }
31609
-
31610
- // src/utils/detect.ts
31611
- var import_fs_extra10 = __toESM(require_lib());
31612
-
31613
- // src/utils/detect-pm-from-user-agent.ts
31614
- function detectPmFromUserAgent(userAgent) {
31615
- if (!userAgent) return null;
31616
- if (userAgent.startsWith("pnpm/")) return "pnpm";
31617
- if (userAgent.startsWith("yarn/")) return "yarn";
31618
- if (userAgent.startsWith("bun/")) return "bun";
31619
- if (userAgent.startsWith("npm/")) return "npm";
31620
- return null;
31621
- }
31622
-
31623
- // src/utils/detect.ts
31624
- async function detectPackageManager2(cwd) {
31625
- const fromUa = detectPmFromUserAgent(process.env.npm_config_user_agent);
31626
- if (fromUa) return fromUa;
31627
- if (await import_fs_extra10.default.pathExists(path__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
31628
- if (await import_fs_extra10.default.pathExists(path__default.default.join(cwd, "yarn.lock"))) return "yarn";
31629
- if (await import_fs_extra10.default.pathExists(path__default.default.join(cwd, "bun.lockb"))) return "bun";
31630
- return "npm";
31631
- }
31632
- async function detectProject(cwd) {
31633
- const packageJsonPath = path__default.default.join(cwd, "package.json");
31634
- if (!await import_fs_extra10.default.pathExists(packageJsonPath)) {
31635
- throw new Error(
31636
- "No package.json found. Please run this command in a Next.js project."
31637
- );
31638
- }
31639
- const packageJson = await import_fs_extra10.default.readJson(packageJsonPath);
31640
- const deps = {
31641
- ...packageJson.dependencies,
31642
- ...packageJson.devDependencies
31643
- };
31644
- const isNextJs = "next" in deps;
31645
- if (!isNextJs) {
31646
- throw new Error(
31647
- "Next.js not found in dependencies. Please run this in a Next.js project."
31648
- );
31649
- }
31650
- const nextVersion = deps.next?.replace(/[\^~]/, "") || null;
31651
- const srcDir = await import_fs_extra10.default.pathExists(path__default.default.join(cwd, "src"));
31652
- const appDirPaths = srcDir ? [path__default.default.join(cwd, "src", "app")] : [path__default.default.join(cwd, "app")];
31653
- let isAppRouter = false;
31654
- for (const appPath of appDirPaths) {
31655
- if (await import_fs_extra10.default.pathExists(appPath)) {
31656
- isAppRouter = true;
31657
- break;
31658
- }
31659
- }
31660
- if (!isAppRouter) {
31661
- throw new Error(
31662
- "App Router not detected. Nextly requires Next.js App Router (app/ directory)."
31663
- );
31664
- }
31665
- const hasTypescript = await import_fs_extra10.default.pathExists(path__default.default.join(cwd, "tsconfig.json"));
31666
- const packageManager = await detectPackageManager2(cwd);
31667
- const appDir = srcDir ? "src/app" : "app";
31668
- return {
31669
- isNextJs,
31670
- isAppRouter,
31671
- hasTypescript,
31672
- packageManager,
31673
- nextVersion,
31674
- srcDir,
31675
- appDir
31676
- };
31677
- }
31678
-
31679
- // src/utils/template.ts
31680
- var import_fs_extra11 = __toESM(require_lib());
31681
- var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
31682
- ".ts",
31683
- ".tsx",
31684
- ".js",
31685
- ".jsx",
31686
- ".json",
31687
- ".env",
31688
- ".md",
31689
- ".css",
31690
- ".html",
31691
- ".mjs",
31692
- ".cjs"
31693
- ]);
31694
- var SKIP_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", ".gitkeep"]);
31695
- function resolveTemplatePath(localTemplatePath) {
31696
- const __dirname = path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))));
31697
- const fromDist = path__default.default.resolve(__dirname, "../templates");
31698
- if (import_fs_extra11.default.existsSync(fromDist)) {
31699
- return fromDist;
31700
- }
31701
- const fromSrc = path__default.default.resolve(__dirname, "../../templates");
31702
- if (import_fs_extra11.default.existsSync(fromSrc)) {
31703
- return fromSrc;
31704
- }
31705
- throw new Error(
31706
- "Could not find templates directory. Use --local-template to specify the templates path, or ensure templates are bundled."
31707
- );
31708
- }
31709
- function buildPlaceholderMap(options) {
31710
- const { database, databaseUrl } = options;
31711
- return {
31712
- "{{databaseDialect}}": database.type,
31713
- "{{databaseUrl}}": databaseUrl || database.envExample
31714
- };
31715
- }
31716
- async function replacePlaceholdersInFile(filePath, placeholders) {
31717
- const ext = path__default.default.extname(filePath).toLowerCase();
31718
- const basename = path__default.default.basename(filePath);
31719
- const isTextFile = TEXT_EXTENSIONS.has(ext) || basename.startsWith(".env") || basename === ".gitignore";
31720
- if (!isTextFile) return;
31721
- let content = await import_fs_extra11.default.readFile(filePath, "utf-8");
31722
- let changed = false;
31723
- for (const [placeholder, value] of Object.entries(placeholders)) {
31724
- if (content.includes(placeholder)) {
31725
- content = content.replaceAll(placeholder, value);
31726
- changed = true;
31727
- }
31728
- }
31729
- if (changed) {
31730
- await import_fs_extra11.default.writeFile(filePath, content, "utf-8");
31731
- }
31732
- }
31733
- async function replacePlaceholders(dir, placeholders) {
31734
- const entries = await import_fs_extra11.default.readdir(dir, { withFileTypes: true });
31735
- for (const entry of entries) {
31736
- const fullPath = path__default.default.join(dir, entry.name);
31737
- if (entry.isDirectory()) {
31738
- if (entry.name === "node_modules" || entry.name === ".git") continue;
31739
- await replacePlaceholders(fullPath, placeholders);
31740
- } else if (entry.isFile()) {
31741
- await replacePlaceholdersInFile(fullPath, placeholders);
31742
- }
31743
- }
31744
- }
31745
- var PINNED_VERSIONS = {
31746
- // Next.js ecosystem — resolved at runtime via fetchLatestVersion()
31747
- // (see generatePackageJson)
31748
- react: "^19.1.0",
31749
- "react-dom": "^19.1.0",
31750
- // Dev dependencies
31751
- typescript: "^5",
31752
- "@types/node": "^20",
31753
- "@types/react": "^19",
31754
- "@types/react-dom": "^19",
31755
- "@tailwindcss/postcss": "^4",
31756
- tailwindcss: "^4",
31757
- eslint: "^9"
31758
- };
31759
- var RUNTIME_RESOLVED_PACKAGES = ["next", "eslint-config-next"];
31760
- var NEXTLY_PACKAGES = [
31761
- "nextly",
31762
- "@nextlyhq/admin",
31763
- "@nextlyhq/adapter-drizzle",
31764
- "@nextlyhq/adapter-postgres",
31765
- "@nextlyhq/adapter-mysql",
31766
- "@nextlyhq/adapter-sqlite"
31767
- ];
31768
- var resolvedNextlyVersions = null;
31769
- async function fetchLatestVersion(pkg2) {
31874
+ }
31875
+ };
31876
+
31877
+ // src/prompts/project-name.ts
31878
+ var import_fs_extra10 = __toESM(require_lib());
31879
+ async function isExistingNextProject(cwd) {
31880
+ const packageJsonPath = path__default.default.join(cwd, "package.json");
31881
+ if (!await import_fs_extra10.default.pathExists(packageJsonPath)) return false;
31770
31882
  try {
31771
- const res = await fetch(
31772
- `https://registry.npmjs.org/-/package/${encodeURIComponent(pkg2)}/dist-tags`,
31773
- { signal: AbortSignal.timeout(5e3) }
31774
- );
31775
- if (!res.ok) return "latest";
31776
- const data = await res.json();
31777
- return data.latest ? `^${data.latest}` : "latest";
31883
+ const packageJson = await import_fs_extra10.default.readJson(packageJsonPath);
31884
+ const deps = {
31885
+ ...packageJson.dependencies,
31886
+ ...packageJson.devDependencies
31887
+ };
31888
+ return "next" in deps;
31778
31889
  } catch {
31779
- return "latest";
31890
+ return false;
31780
31891
  }
31781
31892
  }
31782
- async function resolveNextlyVersions() {
31783
- if (resolvedNextlyVersions) return resolvedNextlyVersions;
31784
- const entries = await Promise.all(
31785
- NEXTLY_PACKAGES.map(
31786
- async (pkg2) => [pkg2, await fetchLatestVersion(pkg2)]
31787
- )
31788
- );
31789
- resolvedNextlyVersions = Object.fromEntries(entries);
31790
- return resolvedNextlyVersions;
31893
+
31894
+ // src/prompts/template.ts
31895
+ var import_picocolors2 = __toESM(require_picocolors2());
31896
+ function getTemplatePromptOptions() {
31897
+ return [
31898
+ {
31899
+ value: "blank",
31900
+ label: "Blank project",
31901
+ hint: "Start fresh with an empty config"
31902
+ },
31903
+ {
31904
+ value: "blog",
31905
+ label: "Blog",
31906
+ hint: "Posts, authors, categories, clean design"
31907
+ },
31908
+ {
31909
+ value: "_coming_soon",
31910
+ label: import_picocolors2.default.dim("More templates coming soon"),
31911
+ hint: "website, portfolio, e-commerce"
31912
+ }
31913
+ ];
31791
31914
  }
31792
- var resolvedRuntimeVersions = null;
31793
- async function resolveRuntimeVersions() {
31794
- if (resolvedRuntimeVersions) return resolvedRuntimeVersions;
31795
- const FALLBACKS = {
31796
- next: "^16.1.0",
31797
- "eslint-config-next": "^16.1.0"
31798
- };
31799
- const entries = await Promise.all(
31800
- RUNTIME_RESOLVED_PACKAGES.map(async (pkg2) => {
31801
- const version2 = await fetchLatestVersion(pkg2);
31802
- return [pkg2, version2 === "latest" ? FALLBACKS[pkg2] : version2];
31803
- })
31804
- );
31805
- resolvedRuntimeVersions = Object.fromEntries(entries);
31806
- return resolvedRuntimeVersions;
31915
+ function isValidTemplateSelection(value) {
31916
+ return value !== "_coming_soon";
31807
31917
  }
31808
- async function generatePackageJson(projectName, database, useYalc = false) {
31809
- const runtimeVersions = await resolveRuntimeVersions();
31810
- const dependencies = {
31811
- next: runtimeVersions.next,
31812
- react: PINNED_VERSIONS.react,
31813
- "react-dom": PINNED_VERSIONS["react-dom"]
31814
- };
31815
- dependencies["@tanstack/react-query"] = "^5.62.0";
31816
- if (!useYalc) {
31817
- const versions = await resolveNextlyVersions();
31818
- dependencies["nextly"] = versions["nextly"];
31819
- dependencies["@nextlyhq/admin"] = versions["@nextlyhq/admin"];
31820
- dependencies["@nextlyhq/ui"] = versions["@nextlyhq/ui"] || "latest";
31821
- dependencies["@nextlyhq/adapter-drizzle"] = versions["@nextlyhq/adapter-drizzle"];
31822
- dependencies[database.adapter] = versions[database.adapter] || "latest";
31823
- dependencies["@nextlyhq/plugin-form-builder"] = versions["@nextlyhq/plugin-form-builder"] || "latest";
31824
- }
31825
- const devDependencies = {
31826
- typescript: PINNED_VERSIONS.typescript,
31827
- "@types/node": PINNED_VERSIONS["@types/node"],
31828
- "@types/react": PINNED_VERSIONS["@types/react"],
31829
- "@types/react-dom": PINNED_VERSIONS["@types/react-dom"],
31830
- "@tailwindcss/postcss": PINNED_VERSIONS["@tailwindcss/postcss"],
31831
- tailwindcss: PINNED_VERSIONS.tailwindcss,
31832
- eslint: PINNED_VERSIONS.eslint,
31833
- "eslint-config-next": runtimeVersions["eslint-config-next"],
31834
- // Pagefind powers /search in the blog template. Zero-config
31835
- // static index generated at `next build` time. Templates that
31836
- // don't ship a /search page simply won't invoke it.
31837
- pagefind: "^1.1.0"
31838
- };
31839
- const pkg2 = {
31840
- name: projectName,
31841
- version: "0.1.0",
31842
- private: true,
31843
- scripts: {
31844
- // F1 PR 4: dev now boots Nextly in single-process mode via `next dev`.
31845
- // The lazy drizzle-kit/api import (PR 1) plus the in-process HMR
31846
- // listener (PR 2) replaced the wrapper that previously owned the
31847
- // terminal, schema prompts, and child supervision. `nextly dev` is
31848
- // gone; the only supported dev command is the standard `next dev`.
31849
- dev: "next dev --turbopack",
31850
- // Build: migrate DB + compile Next.js + (if present) generate
31851
- // the Pagefind search index. Templates without the search
31852
- // script silently skip the last step.
31853
- build: "nextly migrate && next build && (test -f scripts/build-search-index.mjs && node scripts/build-search-index.mjs || true)",
31854
- "search:index": "node scripts/build-search-index.mjs",
31855
- start: "next start",
31856
- lint: "next lint",
31857
- nextly: "nextly",
31858
- // First-time setup: sync schema + seed system permissions. Demo
31859
- // content is seeded separately from the admin UI (visit /welcome
31860
- // after running `pnpm dev` and completing /admin/setup).
31861
- "db:setup": "nextly db:sync",
31862
- "db:migrate": "nextly migrate",
31863
- "db:migrate:status": "nextly migrate:status",
31864
- "db:migrate:fresh": "nextly migrate:fresh",
31865
- "db:migrate:reset": "nextly migrate:reset",
31866
- "types:generate": "nextly generate:types"
31867
- },
31868
- dependencies,
31869
- devDependencies
31870
- };
31871
- return JSON.stringify(pkg2, null, 2) + "\n";
31918
+
31919
+ // src/utils/detect.ts
31920
+ var import_fs_extra11 = __toESM(require_lib());
31921
+
31922
+ // src/utils/detect-pm-from-user-agent.ts
31923
+ function detectPmFromUserAgent(userAgent) {
31924
+ if (!userAgent) return null;
31925
+ if (userAgent.startsWith("pnpm/")) return "pnpm";
31926
+ if (userAgent.startsWith("yarn/")) return "yarn";
31927
+ if (userAgent.startsWith("bun/")) return "bun";
31928
+ if (userAgent.startsWith("npm/")) return "npm";
31929
+ return null;
31872
31930
  }
31873
- async function copyTemplate(options) {
31874
- const {
31875
- projectName,
31876
- projectType,
31877
- targetDir,
31878
- database,
31879
- databaseUrl,
31880
- useYalc = false,
31881
- approach,
31882
- templateSource
31883
- } = options;
31884
- if (targetDir !== process.cwd() && await import_fs_extra11.default.pathExists(targetDir)) {
31885
- throw new Error(
31886
- `Directory "${path__default.default.basename(targetDir)}" already exists. Please choose a different name.`
31887
- );
31888
- }
31889
- let baseDir;
31890
- let typeDir;
31891
- if (templateSource) {
31892
- baseDir = templateSource.basePath;
31893
- typeDir = templateSource.templatePath;
31894
- } else {
31895
- const templatesRoot = resolveTemplatePath();
31896
- baseDir = path__default.default.join(templatesRoot, "base");
31897
- typeDir = path__default.default.join(templatesRoot, projectType);
31898
- }
31899
- if (!await import_fs_extra11.default.pathExists(baseDir)) {
31931
+
31932
+ // src/utils/detect.ts
31933
+ async function detectPackageManager2(cwd) {
31934
+ const fromUa = detectPmFromUserAgent(process.env.npm_config_user_agent);
31935
+ if (fromUa) return fromUa;
31936
+ if (await import_fs_extra11.default.pathExists(path__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
31937
+ if (await import_fs_extra11.default.pathExists(path__default.default.join(cwd, "yarn.lock"))) return "yarn";
31938
+ if (await import_fs_extra11.default.pathExists(path__default.default.join(cwd, "bun.lockb"))) return "bun";
31939
+ return "npm";
31940
+ }
31941
+ async function detectProject(cwd) {
31942
+ const packageJsonPath = path__default.default.join(cwd, "package.json");
31943
+ if (!await import_fs_extra11.default.pathExists(packageJsonPath)) {
31900
31944
  throw new Error(
31901
- `Base template not found at ${baseDir}. The package may be corrupted or the download failed.`
31945
+ "No package.json found. Please run this command in a Next.js project."
31902
31946
  );
31903
31947
  }
31904
- if (!await import_fs_extra11.default.pathExists(typeDir)) {
31948
+ const packageJson = await import_fs_extra11.default.readJson(packageJsonPath);
31949
+ const deps = {
31950
+ ...packageJson.dependencies,
31951
+ ...packageJson.devDependencies
31952
+ };
31953
+ const isNextJs = "next" in deps;
31954
+ if (!isNextJs) {
31905
31955
  throw new Error(
31906
- `Template "${projectType}" not found at ${typeDir}. Available templates: blank, blog.`
31956
+ "Next.js not found in dependencies. Please run this in a Next.js project."
31907
31957
  );
31908
31958
  }
31909
- await import_fs_extra11.default.copy(baseDir, targetDir, {
31910
- filter: (_src) => {
31911
- const basename = path__default.default.basename(_src);
31912
- return !SKIP_FILES.has(basename);
31959
+ const nextVersion = deps.next?.replace(/[\^~]/, "") || null;
31960
+ const srcDir = await import_fs_extra11.default.pathExists(path__default.default.join(cwd, "src"));
31961
+ const appDirPaths = srcDir ? [path__default.default.join(cwd, "src", "app")] : [path__default.default.join(cwd, "app")];
31962
+ let isAppRouter = false;
31963
+ for (const appPath of appDirPaths) {
31964
+ if (await import_fs_extra11.default.pathExists(appPath)) {
31965
+ isAppRouter = true;
31966
+ break;
31913
31967
  }
31914
- });
31915
- const templateSrcDir = path__default.default.join(typeDir, "src");
31916
- if (await import_fs_extra11.default.pathExists(templateSrcDir)) {
31917
- await import_fs_extra11.default.copy(templateSrcDir, path__default.default.join(targetDir, "src"), {
31918
- overwrite: true,
31919
- filter: (_src) => {
31920
- const basename = path__default.default.basename(_src);
31921
- return !SKIP_FILES.has(basename);
31922
- }
31923
- });
31924
31968
  }
31925
- const templateRootConfig = path__default.default.join(typeDir, "nextly.config.ts");
31926
- if (await import_fs_extra11.default.pathExists(templateRootConfig)) {
31927
- await import_fs_extra11.default.copy(
31928
- templateRootConfig,
31929
- path__default.default.join(targetDir, "nextly.config.ts"),
31930
- { overwrite: true }
31969
+ if (!isAppRouter) {
31970
+ throw new Error(
31971
+ "App Router not detected. Nextly requires Next.js App Router (app/ directory)."
31931
31972
  );
31932
31973
  }
31933
- const configsDir = path__default.default.join(typeDir, "configs");
31934
- if (approach && await import_fs_extra11.default.pathExists(configsDir)) {
31935
- const configFileName = approach === "code-first" ? "codefirst.config.ts" : `${approach}.config.ts`;
31936
- const configSrc = path__default.default.join(configsDir, configFileName);
31937
- if (await import_fs_extra11.default.pathExists(configSrc)) {
31938
- await import_fs_extra11.default.copy(configSrc, path__default.default.join(targetDir, "nextly.config.ts"), {
31939
- overwrite: true
31940
- });
31941
- }
31942
- const sharedSrc = path__default.default.join(configsDir, "shared.ts");
31943
- if (await import_fs_extra11.default.pathExists(sharedSrc)) {
31944
- await import_fs_extra11.default.copy(sharedSrc, path__default.default.join(targetDir, "shared.ts"), {
31945
- overwrite: true
31946
- });
31947
- }
31948
- }
31949
- const frontendPagePath = path__default.default.join(
31950
- targetDir,
31951
- "src",
31952
- "app",
31953
- "(frontend)",
31954
- "page.tsx"
31955
- );
31956
- const basePagePath = path__default.default.join(targetDir, "src", "app", "page.tsx");
31957
- if (await import_fs_extra11.default.pathExists(frontendPagePath) && await import_fs_extra11.default.pathExists(basePagePath)) {
31958
- await import_fs_extra11.default.remove(basePagePath);
31959
- }
31960
- const packageJsonContent = await generatePackageJson(
31961
- projectName,
31962
- database,
31963
- useYalc
31964
- );
31965
- await import_fs_extra11.default.writeFile(
31966
- path__default.default.join(targetDir, "package.json"),
31967
- packageJsonContent,
31968
- "utf-8"
31969
- );
31970
- if (database.type === "sqlite") {
31971
- await import_fs_extra11.default.ensureDir(path__default.default.join(targetDir, "data"));
31972
- }
31973
- const placeholders = buildPlaceholderMap({ database, databaseUrl });
31974
- if (approach) {
31975
- placeholders["{{approach}}"] = approach;
31976
- }
31977
- await replacePlaceholders(targetDir, placeholders);
31974
+ const hasTypescript = await import_fs_extra11.default.pathExists(path__default.default.join(cwd, "tsconfig.json"));
31975
+ const packageManager = await detectPackageManager2(cwd);
31976
+ const appDir = srcDir ? "src/app" : "app";
31977
+ return {
31978
+ isNextJs,
31979
+ isAppRouter,
31980
+ hasTypescript,
31981
+ packageManager,
31982
+ nextVersion,
31983
+ srcDir,
31984
+ appDir
31985
+ };
31978
31986
  }
31979
31987
 
31980
31988
  // src/create-nextly.ts
@@ -32230,7 +32238,8 @@ async function createNextly(options = {}) {
32230
32238
  projectInfo,
32231
32239
  database,
32232
32240
  useYalc,
32233
- isFreshProject
32241
+ isFreshProject,
32242
+ projectType
32234
32243
  );
32235
32244
  s3.stop("Dependencies installed");
32236
32245
  capture("install_completed", {