create-nextly-app 0.0.2-alpha.5 → 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/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var module$1 = require('module');
4
- var path17 = require('path');
4
+ var path14 = require('path');
5
5
  var util = require('util');
6
6
  var process4 = require('process');
7
7
  var k = require('readline');
@@ -43,7 +43,7 @@ function _interopNamespace(e) {
43
43
  return Object.freeze(n);
44
44
  }
45
45
 
46
- var path17__default = /*#__PURE__*/_interopDefault(path17);
46
+ var path14__default = /*#__PURE__*/_interopDefault(path14);
47
47
  var process4__default = /*#__PURE__*/_interopDefault(process4);
48
48
  var k__namespace = /*#__PURE__*/_interopNamespace(k);
49
49
  var tty__default = /*#__PURE__*/_interopDefault(tty);
@@ -12905,12 +12905,12 @@ function createModulerModifier() {
12905
12905
  return frames;
12906
12906
  };
12907
12907
  }
12908
- function createGetModuleFromFilename(basePath = process.argv[1] ? path17.dirname(process.argv[1]) : process.cwd(), isWindows = "\\" === path17.sep) {
12908
+ function createGetModuleFromFilename(basePath = process.argv[1] ? path14.dirname(process.argv[1]) : process.cwd(), isWindows = "\\" === path14.sep) {
12909
12909
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
12910
12910
  return (filename) => {
12911
12911
  if (!filename) return;
12912
12912
  const normalizedFilename = isWindows ? normalizeWindowsPath(filename) : filename;
12913
- let { dir, base: file, ext } = path17.posix.parse(normalizedFilename);
12913
+ let { dir, base: file, ext } = path14.posix.parse(normalizedFilename);
12914
12914
  if (".js" === ext || ".mjs" === ext || ".cjs" === ext) file = file.slice(0, -1 * ext.length);
12915
12915
  const decodedFile = decodeURIComponent(file);
12916
12916
  if (!dir) dir = ".";
@@ -13997,7 +13997,7 @@ var Temp = {
13997
13997
  }
13998
13998
  },
13999
13999
  truncate: (filePath) => {
14000
- const basename = path17__default.default.basename(filePath);
14000
+ const basename = path14__default.default.basename(filePath);
14001
14001
  if (basename.length <= LIMIT_BASENAME_LENGTH)
14002
14002
  return filePath;
14003
14003
  const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(basename);
@@ -14050,9 +14050,6 @@ var import_fs_extra = __toESM(require_lib());
14050
14050
  var ADMIN_PAGE_TEMPLATE = `"use client";
14051
14051
 
14052
14052
  import "@nextlyhq/admin/style.css";
14053
- import "@nextlyhq/plugin-form-builder/admin";
14054
- import "@nextlyhq/plugin-form-builder/styles/builder.css";
14055
- import "@nextlyhq/plugin-form-builder/styles/submissions-filter.css";
14056
14053
  import { RootLayout, QueryProvider, ErrorBoundary } from "@nextlyhq/admin";
14057
14054
 
14058
14055
  export default function AdminPage() {
@@ -14094,9 +14091,9 @@ export default function AdminLayout({
14094
14091
  `;
14095
14092
  }
14096
14093
  async function generateAdminPage(cwd, projectInfo) {
14097
- const adminDir = path17__default.default.join(cwd, projectInfo.appDir, "admin", "[[...params]]");
14098
- const pagePath = path17__default.default.join(adminDir, "page.tsx");
14099
- const layoutPath = path17__default.default.join(adminDir, "layout.tsx");
14094
+ const adminDir = path14__default.default.join(cwd, projectInfo.appDir, "admin", "[[...params]]");
14095
+ const pagePath = path14__default.default.join(adminDir, "page.tsx");
14096
+ const layoutPath = path14__default.default.join(adminDir, "layout.tsx");
14100
14097
  if (await import_fs_extra.default.pathExists(pagePath)) {
14101
14098
  throw new Error(
14102
14099
  "Admin page already exists at admin/[[...params]]/page.tsx"
@@ -14149,7 +14146,7 @@ ${singlesLine}
14149
14146
  return template;
14150
14147
  }
14151
14148
  async function generateConfig(cwd, projectType) {
14152
- const configPath = path17__default.default.join(cwd, "nextly.config.ts");
14149
+ const configPath = path14__default.default.join(cwd, "nextly.config.ts");
14153
14150
  if (await import_fs_extra2.default.pathExists(configPath)) {
14154
14151
  throw new Error(
14155
14152
  "nextly.config.ts already exists. Please remove it first or run in a fresh project."
@@ -14180,8 +14177,8 @@ NEXT_PUBLIC_APP_URL=http://localhost:3000
14180
14177
  `;
14181
14178
  }
14182
14179
  async function generateEnv(cwd, database) {
14183
- const envPath = path17__default.default.join(cwd, ".env");
14184
- const envExamplePath = path17__default.default.join(cwd, ".env.example");
14180
+ const envPath = path14__default.default.join(cwd, ".env");
14181
+ const envExamplePath = path14__default.default.join(cwd, ".env.example");
14185
14182
  const envContent = getEnvTemplate(database);
14186
14183
  await import_fs_extra3.default.writeFile(envExamplePath, envContent, "utf-8");
14187
14184
  if (await import_fs_extra3.default.pathExists(envPath)) {
@@ -14245,25 +14242,25 @@ var HEALTH_ROUTE_TEMPLATE = `/**
14245
14242
  export { GET, HEAD } from "nextly/api/health";
14246
14243
  `;
14247
14244
  async function generateMediaRoutes(cwd, projectInfo) {
14248
- const apiDir = path17__default.default.join(cwd, projectInfo.appDir, "api");
14249
- const mediaDir = path17__default.default.join(apiDir, "media");
14245
+ const apiDir = path14__default.default.join(cwd, projectInfo.appDir, "api");
14246
+ const mediaDir = path14__default.default.join(apiDir, "media");
14250
14247
  if (await import_fs_extra4.default.pathExists(mediaDir)) {
14251
14248
  throw new Error(
14252
14249
  "Media API routes already exist at api/media. Please remove them first."
14253
14250
  );
14254
14251
  }
14255
- const mediaRoutePath = path17__default.default.join(apiDir, "media", "[[...path]]", "route.ts");
14252
+ const mediaRoutePath = path14__default.default.join(apiDir, "media", "[[...path]]", "route.ts");
14256
14253
  const configImportPath = getConfigImportPath(
14257
14254
  projectInfo.appDir.startsWith("src")
14258
14255
  );
14259
- await import_fs_extra4.default.ensureDir(path17__default.default.dirname(mediaRoutePath));
14256
+ await import_fs_extra4.default.ensureDir(path14__default.default.dirname(mediaRoutePath));
14260
14257
  await import_fs_extra4.default.writeFile(
14261
14258
  mediaRoutePath,
14262
14259
  MEDIA_CATCH_ALL_TEMPLATE(configImportPath),
14263
14260
  "utf-8"
14264
14261
  );
14265
- const healthRoutePath = path17__default.default.join(apiDir, "health", "route.ts");
14266
- await import_fs_extra4.default.ensureDir(path17__default.default.dirname(healthRoutePath));
14262
+ const healthRoutePath = path14__default.default.join(apiDir, "health", "route.ts");
14263
+ await import_fs_extra4.default.ensureDir(path14__default.default.dirname(healthRoutePath));
14267
14264
  await import_fs_extra4.default.writeFile(healthRoutePath, HEALTH_ROUTE_TEMPLATE, "utf-8");
14268
14265
  }
14269
14266
 
@@ -14288,7 +14285,7 @@ async function patchNextConfig(cwd) {
14288
14285
  const candidates = ["next.config.ts", "next.config.mjs", "next.config.js"];
14289
14286
  let configPath = null;
14290
14287
  for (const name of candidates) {
14291
- const full = path17__default.default.join(cwd, name);
14288
+ const full = path14__default.default.join(cwd, name);
14292
14289
  if (await import_fs_extra5.default.pathExists(full)) {
14293
14290
  configPath = full;
14294
14291
  break;
@@ -14341,7 +14338,7 @@ export const DELETE = handlers.DELETE;
14341
14338
  export const OPTIONS = handlers.OPTIONS;
14342
14339
  `;
14343
14340
  async function generateRoutes(cwd, projectInfo) {
14344
- const routePath = path17__default.default.join(
14341
+ const routePath = path14__default.default.join(
14345
14342
  cwd,
14346
14343
  projectInfo.appDir,
14347
14344
  "admin",
@@ -14354,7 +14351,7 @@ async function generateRoutes(cwd, projectInfo) {
14354
14351
  "API route already exists at admin/api/[[...params]]/route.ts"
14355
14352
  );
14356
14353
  }
14357
- await import_fs_extra6.default.ensureDir(path17__default.default.dirname(routePath));
14354
+ await import_fs_extra6.default.ensureDir(path14__default.default.dirname(routePath));
14358
14355
  await import_fs_extra6.default.writeFile(routePath, API_ROUTE_TEMPLATE, "utf-8");
14359
14356
  }
14360
14357
 
@@ -14362,13 +14359,13 @@ async function generateRoutes(cwd, projectInfo) {
14362
14359
  var import_fs_extra7 = __toESM(require_lib());
14363
14360
  async function generateTypesDirectory(cwd, projectInfo) {
14364
14361
  const baseDir = projectInfo.srcDir ? "src" : ".";
14365
- const typesDir = path17__default.default.join(cwd, baseDir, "types", "generated");
14362
+ const typesDir = path14__default.default.join(cwd, baseDir, "types", "generated");
14366
14363
  await import_fs_extra7.default.ensureDir(typesDir);
14367
- const gitkeepPath = path17__default.default.join(typesDir, ".gitkeep");
14364
+ const gitkeepPath = path14__default.default.join(typesDir, ".gitkeep");
14368
14365
  if (!await import_fs_extra7.default.pathExists(gitkeepPath)) {
14369
14366
  await import_fs_extra7.default.writeFile(gitkeepPath, "", "utf-8");
14370
14367
  }
14371
- const placeholderPath = path17__default.default.join(typesDir, "nextly-types.ts");
14368
+ const placeholderPath = path14__default.default.join(typesDir, "nextly-types.ts");
14372
14369
  if (!await import_fs_extra7.default.pathExists(placeholderPath)) {
14373
14370
  const placeholderContent = `/**
14374
14371
  * Nextly Generated Types
@@ -15179,12 +15176,12 @@ function toPath(urlOrPath) {
15179
15176
  function traversePathUp(startPath) {
15180
15177
  return {
15181
15178
  *[Symbol.iterator]() {
15182
- let currentPath = path17__default.default.resolve(toPath(startPath));
15179
+ let currentPath = path14__default.default.resolve(toPath(startPath));
15183
15180
  let previousPath;
15184
15181
  while (previousPath !== currentPath) {
15185
15182
  yield currentPath;
15186
15183
  previousPath = currentPath;
15187
- currentPath = path17__default.default.resolve(currentPath, "..");
15184
+ currentPath = path14__default.default.resolve(currentPath, "..");
15188
15185
  }
15189
15186
  }
15190
15187
  };
@@ -15198,27 +15195,27 @@ var npmRunPath = ({
15198
15195
  execPath: execPath2 = process4__default.default.execPath,
15199
15196
  addExecPath = true
15200
15197
  } = {}) => {
15201
- const cwdPath = path17__default.default.resolve(toPath(cwd));
15198
+ const cwdPath = path14__default.default.resolve(toPath(cwd));
15202
15199
  const result = [];
15203
- const pathParts = pathOption.split(path17__default.default.delimiter);
15200
+ const pathParts = pathOption.split(path14__default.default.delimiter);
15204
15201
  if (preferLocal) {
15205
15202
  applyPreferLocal(result, pathParts, cwdPath);
15206
15203
  }
15207
15204
  if (addExecPath) {
15208
15205
  applyExecPath(result, pathParts, execPath2, cwdPath);
15209
15206
  }
15210
- return pathOption === "" || pathOption === path17__default.default.delimiter ? `${result.join(path17__default.default.delimiter)}${pathOption}` : [...result, pathOption].join(path17__default.default.delimiter);
15207
+ return pathOption === "" || pathOption === path14__default.default.delimiter ? `${result.join(path14__default.default.delimiter)}${pathOption}` : [...result, pathOption].join(path14__default.default.delimiter);
15211
15208
  };
15212
15209
  var applyPreferLocal = (result, pathParts, cwdPath) => {
15213
15210
  for (const directory of traversePathUp(cwdPath)) {
15214
- const pathPart = path17__default.default.join(directory, "node_modules/.bin");
15211
+ const pathPart = path14__default.default.join(directory, "node_modules/.bin");
15215
15212
  if (!pathParts.includes(pathPart)) {
15216
15213
  result.push(pathPart);
15217
15214
  }
15218
15215
  }
15219
15216
  };
15220
15217
  var applyExecPath = (result, pathParts, execPath2, cwdPath) => {
15221
- const pathPart = path17__default.default.resolve(cwdPath, toPath(execPath2), "..");
15218
+ const pathPart = path14__default.default.resolve(cwdPath, toPath(execPath2), "..");
15222
15219
  if (!pathParts.includes(pathPart)) {
15223
15220
  result.push(pathPart);
15224
15221
  }
@@ -16351,7 +16348,7 @@ var handleNodeOption = (file, commandArguments, {
16351
16348
  throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.');
16352
16349
  }
16353
16350
  const normalizedNodePath = safeNormalizeFileUrl(nodePath, 'The "nodePath" option');
16354
- const resolvedNodePath = path17__default.default.resolve(cwd, normalizedNodePath);
16351
+ const resolvedNodePath = path14__default.default.resolve(cwd, normalizedNodePath);
16355
16352
  const newOptions = {
16356
16353
  ...options,
16357
16354
  nodePath: resolvedNodePath,
@@ -16361,7 +16358,7 @@ var handleNodeOption = (file, commandArguments, {
16361
16358
  if (!shouldHandleNode) {
16362
16359
  return [file, commandArguments, newOptions];
16363
16360
  }
16364
- if (path17__default.default.basename(file, ".exe") === "node") {
16361
+ if (path14__default.default.basename(file, ".exe") === "node") {
16365
16362
  throw new TypeError('When the "node" option is true, the first argument does not need to be "node".');
16366
16363
  }
16367
16364
  return [
@@ -16447,7 +16444,7 @@ var ENCODING_ALIASES = {
16447
16444
  var serializeEncoding = (encoding) => typeof encoding === "string" ? `"${encoding}"` : String(encoding);
16448
16445
  var normalizeCwd = (cwd = getDefaultCwd()) => {
16449
16446
  const cwdString = safeNormalizeFileUrl(cwd, 'The "cwd" option');
16450
- return path17__default.default.resolve(cwdString);
16447
+ return path14__default.default.resolve(cwdString);
16451
16448
  };
16452
16449
  var getDefaultCwd = () => {
16453
16450
  try {
@@ -16494,7 +16491,7 @@ var normalizeOptions = (filePath, rawArguments, rawOptions) => {
16494
16491
  options.killSignal = normalizeKillSignal(options.killSignal);
16495
16492
  options.forceKillAfterDelay = normalizeForceKillAfterDelay(options.forceKillAfterDelay);
16496
16493
  options.lines = options.lines.map((lines, fdNumber) => lines && !BINARY_ENCODINGS.has(options.encoding) && options.buffer[fdNumber]);
16497
- if (process4__default.default.platform === "win32" && path17__default.default.basename(file, ".exe") === "cmd") {
16494
+ if (process4__default.default.platform === "win32" && path14__default.default.basename(file, ".exe") === "cmd") {
16498
16495
  commandArguments.unshift("/q");
16499
16496
  }
16500
16497
  return { file, commandArguments, options };
@@ -20903,6 +20900,316 @@ createExeca(mapNode);
20903
20900
  createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
20904
20901
  getIpcExport();
20905
20902
 
20903
+ // src/utils/template.ts
20904
+ var import_fs_extra8 = __toESM(require_lib());
20905
+ var PROJECT_TYPES_WITH_FORM_BUILDER = /* @__PURE__ */ new Set([
20906
+ "blog"
20907
+ ]);
20908
+ function projectUsesFormBuilder(projectType) {
20909
+ return PROJECT_TYPES_WITH_FORM_BUILDER.has(projectType);
20910
+ }
20911
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
20912
+ ".ts",
20913
+ ".tsx",
20914
+ ".js",
20915
+ ".jsx",
20916
+ ".json",
20917
+ ".env",
20918
+ ".md",
20919
+ ".css",
20920
+ ".html",
20921
+ ".mjs",
20922
+ ".cjs"
20923
+ ]);
20924
+ var SKIP_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", ".gitkeep"]);
20925
+ function resolveTemplatePath(localTemplatePath) {
20926
+ const __dirname = path14__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
20927
+ const fromDist = path14__default.default.resolve(__dirname, "../templates");
20928
+ if (import_fs_extra8.default.existsSync(fromDist)) {
20929
+ return fromDist;
20930
+ }
20931
+ const fromSrc = path14__default.default.resolve(__dirname, "../../templates");
20932
+ if (import_fs_extra8.default.existsSync(fromSrc)) {
20933
+ return fromSrc;
20934
+ }
20935
+ throw new Error(
20936
+ "Could not find templates directory. Use --local-template to specify the templates path, or ensure templates are bundled."
20937
+ );
20938
+ }
20939
+ function buildPlaceholderMap(options) {
20940
+ const { database, databaseUrl } = options;
20941
+ return {
20942
+ "{{databaseDialect}}": database.type,
20943
+ "{{databaseUrl}}": databaseUrl || database.envExample
20944
+ };
20945
+ }
20946
+ async function replacePlaceholdersInFile(filePath, placeholders) {
20947
+ const ext = path14__default.default.extname(filePath).toLowerCase();
20948
+ const basename = path14__default.default.basename(filePath);
20949
+ const isTextFile = TEXT_EXTENSIONS.has(ext) || basename.startsWith(".env") || basename === ".gitignore";
20950
+ if (!isTextFile) return;
20951
+ let content = await import_fs_extra8.default.readFile(filePath, "utf-8");
20952
+ let changed = false;
20953
+ for (const [placeholder, value] of Object.entries(placeholders)) {
20954
+ if (content.includes(placeholder)) {
20955
+ content = content.replaceAll(placeholder, value);
20956
+ changed = true;
20957
+ }
20958
+ }
20959
+ if (changed) {
20960
+ await import_fs_extra8.default.writeFile(filePath, content, "utf-8");
20961
+ }
20962
+ }
20963
+ async function replacePlaceholders(dir, placeholders) {
20964
+ const entries = await import_fs_extra8.default.readdir(dir, { withFileTypes: true });
20965
+ for (const entry of entries) {
20966
+ const fullPath = path14__default.default.join(dir, entry.name);
20967
+ if (entry.isDirectory()) {
20968
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
20969
+ await replacePlaceholders(fullPath, placeholders);
20970
+ } else if (entry.isFile()) {
20971
+ await replacePlaceholdersInFile(fullPath, placeholders);
20972
+ }
20973
+ }
20974
+ }
20975
+ var PINNED_VERSIONS = {
20976
+ // Next.js ecosystem — resolved at runtime via fetchLatestVersion()
20977
+ // (see generatePackageJson)
20978
+ react: "^19.1.0",
20979
+ "react-dom": "^19.1.0",
20980
+ // Dev dependencies
20981
+ typescript: "^5",
20982
+ "@types/node": "^20",
20983
+ "@types/react": "^19",
20984
+ "@types/react-dom": "^19",
20985
+ "@tailwindcss/postcss": "^4",
20986
+ tailwindcss: "^4",
20987
+ eslint: "^9"
20988
+ };
20989
+ var RUNTIME_RESOLVED_PACKAGES = ["next", "eslint-config-next"];
20990
+ var NEXTLY_PACKAGES = [
20991
+ "nextly",
20992
+ "@nextlyhq/admin",
20993
+ "@nextlyhq/adapter-drizzle",
20994
+ "@nextlyhq/adapter-postgres",
20995
+ "@nextlyhq/adapter-mysql",
20996
+ "@nextlyhq/adapter-sqlite"
20997
+ ];
20998
+ var resolvedNextlyVersions = null;
20999
+ async function fetchLatestVersion(pkg) {
21000
+ try {
21001
+ const res = await fetch(
21002
+ `https://registry.npmjs.org/-/package/${encodeURIComponent(pkg)}/dist-tags`,
21003
+ { signal: AbortSignal.timeout(5e3) }
21004
+ );
21005
+ if (!res.ok) return "latest";
21006
+ const data = await res.json();
21007
+ return data.latest ? `^${data.latest}` : "latest";
21008
+ } catch {
21009
+ return "latest";
21010
+ }
21011
+ }
21012
+ async function resolveNextlyVersions() {
21013
+ if (resolvedNextlyVersions) return resolvedNextlyVersions;
21014
+ const entries = await Promise.all(
21015
+ NEXTLY_PACKAGES.map(
21016
+ async (pkg) => [pkg, await fetchLatestVersion(pkg)]
21017
+ )
21018
+ );
21019
+ resolvedNextlyVersions = Object.fromEntries(entries);
21020
+ return resolvedNextlyVersions;
21021
+ }
21022
+ var resolvedRuntimeVersions = null;
21023
+ async function resolveRuntimeVersions() {
21024
+ if (resolvedRuntimeVersions) return resolvedRuntimeVersions;
21025
+ const FALLBACKS = {
21026
+ next: "^16.1.0",
21027
+ "eslint-config-next": "^16.1.0"
21028
+ };
21029
+ const entries = await Promise.all(
21030
+ RUNTIME_RESOLVED_PACKAGES.map(async (pkg) => {
21031
+ const version = await fetchLatestVersion(pkg);
21032
+ return [pkg, version === "latest" ? FALLBACKS[pkg] : version];
21033
+ })
21034
+ );
21035
+ resolvedRuntimeVersions = Object.fromEntries(entries);
21036
+ return resolvedRuntimeVersions;
21037
+ }
21038
+ async function generatePackageJson(projectName, database, useYalc = false, projectType = "blank") {
21039
+ const runtimeVersions = await resolveRuntimeVersions();
21040
+ const dependencies = {
21041
+ next: runtimeVersions.next,
21042
+ react: PINNED_VERSIONS.react,
21043
+ "react-dom": PINNED_VERSIONS["react-dom"]
21044
+ };
21045
+ dependencies["@tanstack/react-query"] = "^5.62.0";
21046
+ if (!useYalc) {
21047
+ const versions = await resolveNextlyVersions();
21048
+ dependencies["nextly"] = versions["nextly"];
21049
+ dependencies["@nextlyhq/admin"] = versions["@nextlyhq/admin"];
21050
+ dependencies["@nextlyhq/ui"] = versions["@nextlyhq/ui"] || "latest";
21051
+ dependencies["@nextlyhq/adapter-drizzle"] = versions["@nextlyhq/adapter-drizzle"];
21052
+ dependencies[database.adapter] = versions[database.adapter] || "latest";
21053
+ if (projectUsesFormBuilder(projectType)) {
21054
+ dependencies["@nextlyhq/plugin-form-builder"] = versions["@nextlyhq/plugin-form-builder"] || "latest";
21055
+ }
21056
+ }
21057
+ const devDependencies = {
21058
+ typescript: PINNED_VERSIONS.typescript,
21059
+ "@types/node": PINNED_VERSIONS["@types/node"],
21060
+ "@types/react": PINNED_VERSIONS["@types/react"],
21061
+ "@types/react-dom": PINNED_VERSIONS["@types/react-dom"],
21062
+ "@tailwindcss/postcss": PINNED_VERSIONS["@tailwindcss/postcss"],
21063
+ tailwindcss: PINNED_VERSIONS.tailwindcss,
21064
+ eslint: PINNED_VERSIONS.eslint,
21065
+ "eslint-config-next": runtimeVersions["eslint-config-next"],
21066
+ // Pagefind powers /search in the blog template. Zero-config
21067
+ // static index generated at `next build` time. Templates that
21068
+ // don't ship a /search page simply won't invoke it.
21069
+ pagefind: "^1.1.0"
21070
+ };
21071
+ const pkg = {
21072
+ name: projectName,
21073
+ version: "0.1.0",
21074
+ private: true,
21075
+ scripts: {
21076
+ // F1 PR 4: dev now boots Nextly in single-process mode via `next dev`.
21077
+ // The lazy drizzle-kit/api import (PR 1) plus the in-process HMR
21078
+ // listener (PR 2) replaced the wrapper that previously owned the
21079
+ // terminal, schema prompts, and child supervision. `nextly dev` is
21080
+ // gone; the only supported dev command is the standard `next dev`.
21081
+ dev: "next dev --turbopack",
21082
+ // Build: migrate DB + compile Next.js + (if present) generate
21083
+ // the Pagefind search index. Templates without the search
21084
+ // script silently skip the last step.
21085
+ build: "nextly migrate && next build && (test -f scripts/build-search-index.mjs && node scripts/build-search-index.mjs || true)",
21086
+ "search:index": "node scripts/build-search-index.mjs",
21087
+ start: "next start",
21088
+ lint: "next lint",
21089
+ nextly: "nextly",
21090
+ // First-time setup: sync schema + seed system permissions. Demo
21091
+ // content is seeded separately from the admin UI (visit /welcome
21092
+ // after running `pnpm dev` and completing /admin/setup).
21093
+ "db:setup": "nextly db:sync",
21094
+ "db:migrate": "nextly migrate",
21095
+ "db:migrate:status": "nextly migrate:status",
21096
+ "db:migrate:fresh": "nextly migrate:fresh",
21097
+ "db:migrate:reset": "nextly migrate:reset",
21098
+ "types:generate": "nextly generate:types"
21099
+ },
21100
+ dependencies,
21101
+ devDependencies
21102
+ };
21103
+ return JSON.stringify(pkg, null, 2) + "\n";
21104
+ }
21105
+ async function copyTemplate(options) {
21106
+ const {
21107
+ projectName,
21108
+ projectType,
21109
+ targetDir,
21110
+ database,
21111
+ databaseUrl,
21112
+ useYalc = false,
21113
+ approach,
21114
+ templateSource
21115
+ } = options;
21116
+ if (targetDir !== process.cwd() && await import_fs_extra8.default.pathExists(targetDir)) {
21117
+ throw new Error(
21118
+ `Directory "${path14__default.default.basename(targetDir)}" already exists. Please choose a different name.`
21119
+ );
21120
+ }
21121
+ let baseDir;
21122
+ let typeDir;
21123
+ if (templateSource) {
21124
+ baseDir = templateSource.basePath;
21125
+ typeDir = templateSource.templatePath;
21126
+ } else {
21127
+ const templatesRoot = resolveTemplatePath();
21128
+ baseDir = path14__default.default.join(templatesRoot, "base");
21129
+ typeDir = path14__default.default.join(templatesRoot, projectType);
21130
+ }
21131
+ if (!await import_fs_extra8.default.pathExists(baseDir)) {
21132
+ throw new Error(
21133
+ `Base template not found at ${baseDir}. The package may be corrupted or the download failed.`
21134
+ );
21135
+ }
21136
+ if (!await import_fs_extra8.default.pathExists(typeDir)) {
21137
+ throw new Error(
21138
+ `Template "${projectType}" not found at ${typeDir}. Available templates: blank, blog.`
21139
+ );
21140
+ }
21141
+ await import_fs_extra8.default.copy(baseDir, targetDir, {
21142
+ filter: (_src) => {
21143
+ const basename = path14__default.default.basename(_src);
21144
+ return !SKIP_FILES.has(basename);
21145
+ }
21146
+ });
21147
+ const templateSrcDir = path14__default.default.join(typeDir, "src");
21148
+ if (await import_fs_extra8.default.pathExists(templateSrcDir)) {
21149
+ await import_fs_extra8.default.copy(templateSrcDir, path14__default.default.join(targetDir, "src"), {
21150
+ overwrite: true,
21151
+ filter: (_src) => {
21152
+ const basename = path14__default.default.basename(_src);
21153
+ return !SKIP_FILES.has(basename);
21154
+ }
21155
+ });
21156
+ }
21157
+ const templateRootConfig = path14__default.default.join(typeDir, "nextly.config.ts");
21158
+ if (await import_fs_extra8.default.pathExists(templateRootConfig)) {
21159
+ await import_fs_extra8.default.copy(
21160
+ templateRootConfig,
21161
+ path14__default.default.join(targetDir, "nextly.config.ts"),
21162
+ { overwrite: true }
21163
+ );
21164
+ }
21165
+ const configsDir = path14__default.default.join(typeDir, "configs");
21166
+ if (approach && await import_fs_extra8.default.pathExists(configsDir)) {
21167
+ const configFileName = approach === "code-first" ? "codefirst.config.ts" : `${approach}.config.ts`;
21168
+ const configSrc = path14__default.default.join(configsDir, configFileName);
21169
+ if (await import_fs_extra8.default.pathExists(configSrc)) {
21170
+ await import_fs_extra8.default.copy(configSrc, path14__default.default.join(targetDir, "nextly.config.ts"), {
21171
+ overwrite: true
21172
+ });
21173
+ }
21174
+ const sharedSrc = path14__default.default.join(configsDir, "shared.ts");
21175
+ if (await import_fs_extra8.default.pathExists(sharedSrc)) {
21176
+ await import_fs_extra8.default.copy(sharedSrc, path14__default.default.join(targetDir, "shared.ts"), {
21177
+ overwrite: true
21178
+ });
21179
+ }
21180
+ }
21181
+ const frontendPagePath = path14__default.default.join(
21182
+ targetDir,
21183
+ "src",
21184
+ "app",
21185
+ "(frontend)",
21186
+ "page.tsx"
21187
+ );
21188
+ const basePagePath = path14__default.default.join(targetDir, "src", "app", "page.tsx");
21189
+ if (await import_fs_extra8.default.pathExists(frontendPagePath) && await import_fs_extra8.default.pathExists(basePagePath)) {
21190
+ await import_fs_extra8.default.remove(basePagePath);
21191
+ }
21192
+ const packageJsonContent = await generatePackageJson(
21193
+ projectName,
21194
+ database,
21195
+ useYalc,
21196
+ projectType
21197
+ );
21198
+ await import_fs_extra8.default.writeFile(
21199
+ path14__default.default.join(targetDir, "package.json"),
21200
+ packageJsonContent,
21201
+ "utf-8"
21202
+ );
21203
+ if (database.type === "sqlite") {
21204
+ await import_fs_extra8.default.ensureDir(path14__default.default.join(targetDir, "data"));
21205
+ }
21206
+ const placeholders = buildPlaceholderMap({ database, databaseUrl });
21207
+ if (approach) {
21208
+ placeholders["{{approach}}"] = approach;
21209
+ }
21210
+ await replacePlaceholders(targetDir, placeholders);
21211
+ }
21212
+
20906
21213
  // src/installers/dependencies.ts
20907
21214
  var INSTALL_COMMANDS = {
20908
21215
  npm: ["npm", "install"],
@@ -20922,14 +21229,16 @@ var ALL_ADAPTER_PACKAGES = [
20922
21229
  "@nextlyhq/adapter-mysql",
20923
21230
  "@nextlyhq/adapter-sqlite"
20924
21231
  ];
20925
- var TEMPLATE_PLUGIN_PACKAGES = [
20926
- "@nextlyhq/plugin-form-builder"
20927
- ];
21232
+ var TEMPLATE_PLUGIN_PACKAGES = ["@nextlyhq/plugin-form-builder"];
21233
+ function templatePluginPackages(projectType) {
21234
+ return projectType && projectUsesFormBuilder(projectType) ? TEMPLATE_PLUGIN_PACKAGES : [];
21235
+ }
20928
21236
  function getPackagesToInstall(database) {
20929
21237
  return [...CORE_PACKAGES, database.adapter];
20930
21238
  }
20931
- async function installDependencies(cwd, projectInfo, database, useYalc = false, isFreshProject = false) {
21239
+ async function installDependencies(cwd, projectInfo, database, useYalc = false, isFreshProject = false, projectType) {
20932
21240
  const pm = projectInfo.packageManager;
21241
+ const pluginPackages = templatePluginPackages(projectType);
20933
21242
  if (isFreshProject) {
20934
21243
  if (useYalc) {
20935
21244
  const yalcPackages = [
@@ -20939,7 +21248,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
20939
21248
  "@nextlyhq/ui",
20940
21249
  "@nextlyhq/adapter-drizzle",
20941
21250
  ...ALL_ADAPTER_PACKAGES,
20942
- ...TEMPLATE_PLUGIN_PACKAGES
21251
+ ...pluginPackages
20943
21252
  ])
20944
21253
  ];
20945
21254
  await execa(pm, ["install"], { cwd });
@@ -20960,7 +21269,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
20960
21269
  "@nextlyhq/ui",
20961
21270
  "@nextlyhq/adapter-drizzle",
20962
21271
  ...ALL_ADAPTER_PACKAGES,
20963
- ...TEMPLATE_PLUGIN_PACKAGES
21272
+ ...pluginPackages
20964
21273
  ])
20965
21274
  ];
20966
21275
  for (const pkg of yalcPackages) {
@@ -20975,7 +21284,7 @@ async function installDependencies(cwd, projectInfo, database, useYalc = false,
20975
21284
  }
20976
21285
 
20977
21286
  // src/lib/download-template.ts
20978
- var import_fs_extra8 = __toESM(require_lib());
21287
+ var import_fs_extra9 = __toESM(require_lib());
20979
21288
  var kr = Object.defineProperty;
20980
21289
  var vr = (s3, t2) => {
20981
21290
  for (var e in t2) kr(s3, e, { get: t2[e], enumerable: true });
@@ -21868,12 +22177,12 @@ var F = class {
21868
22177
  }
21869
22178
  };
21870
22179
  var an = (s3, t2) => {
21871
- let i2 = s3, r = "", n2, o2 = path17.posix.parse(s3).root || ".";
22180
+ let i2 = s3, r = "", n2, o2 = path14.posix.parse(s3).root || ".";
21872
22181
  if (Buffer.byteLength(i2) < 100) n2 = [i2, r, false];
21873
22182
  else {
21874
- r = path17.posix.dirname(i2), i2 = path17.posix.basename(i2);
22183
+ r = path14.posix.dirname(i2), i2 = path14.posix.basename(i2);
21875
22184
  do
21876
- Buffer.byteLength(i2) <= 100 && Buffer.byteLength(r) <= t2 ? n2 = [i2, r, false] : Buffer.byteLength(i2) > 100 && Buffer.byteLength(r) <= t2 ? n2 = [i2.slice(0, 99), r, true] : (i2 = path17.posix.join(path17.posix.basename(r), i2), r = path17.posix.dirname(r));
22185
+ Buffer.byteLength(i2) <= 100 && Buffer.byteLength(r) <= t2 ? n2 = [i2, r, false] : Buffer.byteLength(i2) > 100 && Buffer.byteLength(r) <= t2 ? n2 = [i2.slice(0, 99), r, true] : (i2 = path14.posix.join(path14.posix.basename(r), i2), r = path14.posix.dirname(r));
21877
22186
  while (r !== o2 && n2 === void 0);
21878
22187
  n2 || (n2 = [s3.slice(0, 99), "", true]);
21879
22188
  }
@@ -21919,7 +22228,7 @@ var ct2 = class s {
21919
22228
  if (t2 === "") return Buffer.allocUnsafe(0);
21920
22229
  let e = Buffer.byteLength(t2), i2 = 512 * Math.ceil(1 + e / 512), r = Buffer.allocUnsafe(i2);
21921
22230
  for (let n2 = 0; n2 < 512; n2++) r[n2] = 0;
21922
- new F({ path: ("PaxHeader/" + path17.basename(this.path ?? "")).slice(0, 99), mode: this.mode || 420, uid: this.uid, gid: this.gid, size: e, mtime: this.mtime, type: this.global ? "GlobalExtendedHeader" : "ExtendedHeader", linkpath: "", uname: this.uname || "", gname: this.gname || "", devmaj: 0, devmin: 0, atime: this.atime, ctime: this.ctime }).encode(r), r.write(t2, 512, e, "utf8");
22231
+ new F({ path: ("PaxHeader/" + path14.basename(this.path ?? "")).slice(0, 99), mode: this.mode || 420, uid: this.uid, gid: this.gid, size: e, mtime: this.mtime, type: this.global ? "GlobalExtendedHeader" : "ExtendedHeader", linkpath: "", uname: this.uname || "", gname: this.gname || "", devmaj: 0, devmin: 0, atime: this.atime, ctime: this.ctime }).encode(r), r.write(t2, 512, e, "utf8");
21923
22232
  for (let n2 = e + 512; n2 < r.length; n2++) r[n2] = 0;
21924
22233
  return r;
21925
22234
  }
@@ -22281,11 +22590,11 @@ var Nn = (s3) => {
22281
22590
  };
22282
22591
  var Ki = (s3, t2) => {
22283
22592
  let e = new Map(t2.map((n2) => [mt3(n2), true])), i2 = s3.filter, r = (n2, o2 = "") => {
22284
- let h3 = o2 || path17.parse(n2).root || ".", a2;
22593
+ let h3 = o2 || path14.parse(n2).root || ".", a2;
22285
22594
  if (n2 === h3) a2 = false;
22286
22595
  else {
22287
22596
  let l = e.get(n2);
22288
- a2 = l !== void 0 ? l : r(path17.dirname(n2), h3);
22597
+ a2 = l !== void 0 ? l : r(path14.dirname(n2), h3);
22289
22598
  }
22290
22599
  return e.set(n2, a2), a2;
22291
22600
  };
@@ -22331,7 +22640,7 @@ var It3 = K2(An, Dn, (s3) => new st2(s3), (s3) => new st2(s3), (s3, t2) => {
22331
22640
  t2?.length && Ki(s3, t2), s3.noResume || Nn(s3);
22332
22641
  });
22333
22642
  var Vi = (s3, t2, e) => (s3 &= 4095, e && (s3 = (s3 | 384) & -19), t2 && (s3 & 256 && (s3 |= 64), s3 & 32 && (s3 |= 8), s3 & 4 && (s3 |= 1)), s3);
22334
- var { isAbsolute: Cn, parse: Ys } = path17.win32;
22643
+ var { isAbsolute: Cn, parse: Ys } = path14.win32;
22335
22644
  var ce2 = (s3) => {
22336
22645
  let t2 = "", e = Ys(s3);
22337
22646
  for (; Cn(s3) || e.root; ) {
@@ -22405,7 +22714,7 @@ var de2 = class extends D3 {
22405
22714
  let [o2, h3] = ce2(this.path);
22406
22715
  o2 && typeof h3 == "string" && (this.path = h3, r = o2);
22407
22716
  }
22408
- this.win32 = !!i2.win32 || process.platform === "win32", this.win32 && (this.path = Ks(this.path.replaceAll(/\\/g, "/")), t2 = t2.replaceAll(/\\/g, "/")), this.absolute = f(i2.absolute || path17__default.default.resolve(this.cwd, t2)), this.path === "" && (this.path = "./"), r && this.warn("TAR_ENTRY_INFO", `stripping ${r} from absolute path`, { entry: this, path: r + this.path });
22717
+ this.win32 = !!i2.win32 || process.platform === "win32", this.win32 && (this.path = Ks(this.path.replaceAll(/\\/g, "/")), t2 = t2.replaceAll(/\\/g, "/")), this.absolute = f(i2.absolute || path14__default.default.resolve(this.cwd, t2)), this.path === "" && (this.path = "./"), r && this.warn("TAR_ENTRY_INFO", `stripping ${r} from absolute path`, { entry: this, path: r + this.path });
22409
22718
  let n2 = this.statCache.get(this.absolute);
22410
22719
  n2 ? this[ei](n2) : this[Qi]();
22411
22720
  }
@@ -22464,7 +22773,7 @@ var de2 = class extends D3 {
22464
22773
  }
22465
22774
  [Qs](t2) {
22466
22775
  if (!this.stat) throw new Error("cannot create link entry without stat");
22467
- this.type = "Link", this.linkpath = f(path17__default.default.relative(this.cwd, t2)), this.stat.size = 0, this[fe2](), this.end();
22776
+ this.type = "Link", this.linkpath = f(path14__default.default.relative(this.cwd, t2)), this.stat.size = 0, this[fe2](), this.end();
22468
22777
  }
22469
22778
  [qs]() {
22470
22779
  if (!this.stat) throw new Error("cannot create file entry without stat");
@@ -22875,7 +23184,7 @@ var Et3 = class extends D3 {
22875
23184
  return t2 instanceof Yt ? this[er](t2) : this[hi](t2), this.flowing;
22876
23185
  }
22877
23186
  [er](t2) {
22878
- let e = f(path17__default.default.resolve(this.cwd, t2.path));
23187
+ let e = f(path14__default.default.resolve(this.cwd, t2.path));
22879
23188
  if (!this.filter(t2.path, t2)) t2.resume();
22880
23189
  else {
22881
23190
  let i2 = new di(t2.path, e);
@@ -22884,7 +23193,7 @@ var Et3 = class extends D3 {
22884
23193
  this[Ft3]();
22885
23194
  }
22886
23195
  [hi](t2) {
22887
- let e = f(path17__default.default.resolve(this.cwd, t2));
23196
+ let e = f(path14__default.default.resolve(this.cwd, t2));
22888
23197
  this[W3].push(new di(t2, e)), this[Ft3]();
22889
23198
  }
22890
23199
  [as](t2) {
@@ -23022,11 +23331,11 @@ var Hn = (s3, t2) => {
23022
23331
  };
23023
23332
  var or = (s3, t2) => {
23024
23333
  t2.forEach((e) => {
23025
- e.charAt(0) === "@" ? It3({ file: path17__default.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
23334
+ e.charAt(0) === "@" ? It3({ file: path14__default.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
23026
23335
  }), s3.end();
23027
23336
  };
23028
23337
  var hr = async (s3, t2) => {
23029
- for (let e of t2) e.charAt(0) === "@" ? await It3({ file: path17__default.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i2) => {
23338
+ for (let e of t2) e.charAt(0) === "@" ? await It3({ file: path14__default.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i2) => {
23030
23339
  s3.add(i2);
23031
23340
  } }) : s3.add(e);
23032
23341
  s3.end();
@@ -23051,7 +23360,7 @@ var Vn = 512 * 1024;
23051
23360
  var $n = pr | ur | dr | mr;
23052
23361
  var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
23053
23362
  var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
23054
- var fs9 = (s3, t2, e) => {
23363
+ var fs10 = (s3, t2, e) => {
23055
23364
  try {
23056
23365
  return u2__default.default.lchownSync(s3, t2, e);
23057
23366
  } catch (i2) {
@@ -23064,13 +23373,13 @@ var ui = (s3, t2, e, i2) => {
23064
23373
  });
23065
23374
  };
23066
23375
  var Xn = (s3, t2, e, i2, r) => {
23067
- if (t2.isDirectory()) ds(path17__default.default.resolve(s3, t2.name), e, i2, (n2) => {
23376
+ if (t2.isDirectory()) ds(path14__default.default.resolve(s3, t2.name), e, i2, (n2) => {
23068
23377
  if (n2) return r(n2);
23069
- let o2 = path17__default.default.resolve(s3, t2.name);
23378
+ let o2 = path14__default.default.resolve(s3, t2.name);
23070
23379
  ui(o2, e, i2, r);
23071
23380
  });
23072
23381
  else {
23073
- let n2 = path17__default.default.resolve(s3, t2.name);
23382
+ let n2 = path14__default.default.resolve(s3, t2.name);
23074
23383
  ui(n2, e, i2, r);
23075
23384
  }
23076
23385
  };
@@ -23091,7 +23400,7 @@ var ds = (s3, t2, e, i2) => {
23091
23400
  });
23092
23401
  };
23093
23402
  var qn = (s3, t2, e, i2) => {
23094
- t2.isDirectory() && us(path17__default.default.resolve(s3, t2.name), e, i2), fs9(path17__default.default.resolve(s3, t2.name), e, i2);
23403
+ t2.isDirectory() && us(path14__default.default.resolve(s3, t2.name), e, i2), fs10(path14__default.default.resolve(s3, t2.name), e, i2);
23095
23404
  };
23096
23405
  var us = (s3, t2, e) => {
23097
23406
  let i2;
@@ -23100,11 +23409,11 @@ var us = (s3, t2, e) => {
23100
23409
  } catch (r) {
23101
23410
  let n2 = r;
23102
23411
  if (n2?.code === "ENOENT") return;
23103
- if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP") return fs9(s3, t2, e);
23412
+ if (n2?.code === "ENOTDIR" || n2?.code === "ENOTSUP") return fs10(s3, t2, e);
23104
23413
  throw n2;
23105
23414
  }
23106
23415
  for (let r of i2) qn(s3, r, t2, e);
23107
- return fs9(s3, t2, e);
23416
+ return fs10(s3, t2, e);
23108
23417
  };
23109
23418
  var we2 = class extends Error {
23110
23419
  path;
@@ -23141,12 +23450,12 @@ var Er = (s3, t2, e) => {
23141
23450
  };
23142
23451
  if (s3 === d) return Qn(s3, S2);
23143
23452
  if (l) return jn__default.default.mkdir(s3, { mode: r, recursive: true }).then((E) => S2(null, E ?? void 0), S2);
23144
- let N3 = f(path17__default.default.relative(d, s3)).split("/");
23453
+ let N3 = f(path14__default.default.relative(d, s3)).split("/");
23145
23454
  ms(d, N3, r, c3, d, void 0, S2);
23146
23455
  };
23147
23456
  var ms = (s3, t2, e, i2, r, n2, o2) => {
23148
23457
  if (t2.length === 0) return o2(null, n2);
23149
- let h3 = t2.shift(), a2 = f(path17__default.default.resolve(s3 + "/" + h3));
23458
+ let h3 = t2.shift(), a2 = f(path14__default.default.resolve(s3 + "/" + h3));
23150
23459
  u2__default.default.mkdir(a2, e, wr(a2, t2, e, i2, r, n2, o2));
23151
23460
  };
23152
23461
  var wr = (s3, t2, e, i2, r, n2, o2) => (h3) => {
@@ -23180,9 +23489,9 @@ var Sr = (s3, t2) => {
23180
23489
  };
23181
23490
  if (s3 === c3) return Jn(c3), d();
23182
23491
  if (a2) return d(u2__default.default.mkdirSync(s3, { mode: i2, recursive: true }) ?? void 0);
23183
- let T2 = f(path17__default.default.relative(c3, s3)).split("/"), N3;
23492
+ let T2 = f(path14__default.default.relative(c3, s3)).split("/"), N3;
23184
23493
  for (let E = T2.shift(), x3 = c3; E && (x3 += "/" + E); E = T2.shift()) {
23185
- x3 = f(path17__default.default.resolve(x3));
23494
+ x3 = f(path14__default.default.resolve(x3));
23186
23495
  try {
23187
23496
  u2__default.default.mkdirSync(x3, i2), N3 = N3 || x3;
23188
23497
  } catch {
@@ -23211,14 +23520,14 @@ var to = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
23211
23520
  var eo = to === "win32";
23212
23521
  var io = (s3) => s3.split("/").slice(0, -1).reduce((e, i2) => {
23213
23522
  let r = e.at(-1);
23214
- return r !== void 0 && (i2 = path17.join(r, i2)), e.push(i2 || "/"), e;
23523
+ return r !== void 0 && (i2 = path14.join(r, i2)), e.push(i2 || "/"), e;
23215
23524
  }, []);
23216
23525
  var Ei = class {
23217
23526
  #t = /* @__PURE__ */ new Map();
23218
23527
  #i = /* @__PURE__ */ new Map();
23219
23528
  #s = /* @__PURE__ */ new Set();
23220
23529
  reserve(t2, e) {
23221
- t2 = eo ? ["win32 parallelization disabled"] : t2.map((r) => mt3(path17.join(Rr(r))));
23530
+ t2 = eo ? ["win32 parallelization disabled"] : t2.map((r) => mt3(path14.join(Rr(r))));
23222
23531
  let i2 = new Set(t2.map((r) => io(r)).reduce((r, n2) => r.concat(n2)));
23223
23532
  this.#i.set(e, { dirs: i2, paths: t2 });
23224
23533
  for (let r of t2) {
@@ -23358,7 +23667,7 @@ var qt = class extends st2 {
23358
23667
  if (t2.preserveOwner) throw new TypeError("cannot preserve owner in archive and also set owner explicitly");
23359
23668
  this.uid = t2.uid, this.gid = t2.gid, this.setOwner = true;
23360
23669
  } else this.uid = void 0, this.gid = void 0, this.setOwner = false;
23361
- this.preserveOwner = t2.preserveOwner === void 0 && typeof t2.uid != "number" ? !!(process.getuid && process.getuid() === 0) : !!t2.preserveOwner, this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? process.getuid() : void 0, this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : void 0, this.maxDepth = typeof t2.maxDepth == "number" ? t2.maxDepth : no, this.forceChown = t2.forceChown === true, this.win32 = !!t2.win32 || Oe2, this.newer = !!t2.newer, this.keep = !!t2.keep, this.noMtime = !!t2.noMtime, this.preservePaths = !!t2.preservePaths, this.unlink = !!t2.unlink, this.cwd = f(path17__default.default.resolve(t2.cwd || process.cwd())), this.strip = Number(t2.strip) || 0, this.processUmask = this.chmod ? typeof t2.processUmask == "number" ? t2.processUmask : _r() : 0, this.umask = typeof t2.umask == "number" ? t2.umask : this.processUmask, this.dmode = t2.dmode || 511 & ~this.umask, this.fmode = t2.fmode || 438 & ~this.umask, this.on("entry", (e) => this[gr](e));
23670
+ this.preserveOwner = t2.preserveOwner === void 0 && typeof t2.uid != "number" ? !!(process.getuid && process.getuid() === 0) : !!t2.preserveOwner, this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? process.getuid() : void 0, this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? process.getgid() : void 0, this.maxDepth = typeof t2.maxDepth == "number" ? t2.maxDepth : no, this.forceChown = t2.forceChown === true, this.win32 = !!t2.win32 || Oe2, this.newer = !!t2.newer, this.keep = !!t2.keep, this.noMtime = !!t2.noMtime, this.preservePaths = !!t2.preservePaths, this.unlink = !!t2.unlink, this.cwd = f(path14__default.default.resolve(t2.cwd || process.cwd())), this.strip = Number(t2.strip) || 0, this.processUmask = this.chmod ? typeof t2.processUmask == "number" ? t2.processUmask : _r() : 0, this.umask = typeof t2.umask == "number" ? t2.umask : this.processUmask, this.dmode = t2.dmode || 511 & ~this.umask, this.fmode = t2.fmode || 438 & ~this.umask, this.on("entry", (e) => this[gr](e));
23362
23671
  }
23363
23672
  warn(t2, e, i2 = {}) {
23364
23673
  return (t2 === "TAR_BAD_ARCHIVE" || t2 === "TAR_ABORT") && (i2.recoverable = false), super.warn(t2, e, i2);
@@ -23372,7 +23681,7 @@ var qt = class extends st2 {
23372
23681
  let [n2, o2] = ce2(i2), h3 = o2.replaceAll(/\\/g, "/").split("/");
23373
23682
  if (h3.includes("..") || Oe2 && /^[a-z]:\.\.$/i.test(h3[0] ?? "")) {
23374
23683
  if (e === "path" || r === "Link") return this.warn("TAR_ENTRY_ERROR", `${e} contains '..'`, { entry: t2, [e]: i2 }), false;
23375
- let a2 = path17__default.default.posix.dirname(t2.path), l = path17__default.default.posix.normalize(path17__default.default.posix.join(a2, h3.join("/")));
23684
+ let a2 = path14__default.default.posix.dirname(t2.path), l = path14__default.default.posix.normalize(path14__default.default.posix.join(a2, h3.join("/")));
23376
23685
  if (l.startsWith("../") || l === "..") return this.warn("TAR_ENTRY_ERROR", `${e} escapes extraction directory`, { entry: t2, [e]: i2 }), false;
23377
23686
  }
23378
23687
  return n2 && (t2[e] = String(o2), this.warn("TAR_ENTRY_INFO", `stripping ${n2} from absolute ${e}`, { entry: t2, [e]: i2 })), true;
@@ -23390,12 +23699,12 @@ var qt = class extends st2 {
23390
23699
  }
23391
23700
  if (isFinite(this.maxDepth) && i2.length > this.maxDepth) return this.warn("TAR_ENTRY_ERROR", "path excessively deep", { entry: t2, path: e, depth: i2.length, maxDepth: this.maxDepth }), false;
23392
23701
  if (!this[Es](t2, "path") || !this[Es](t2, "linkpath")) return false;
23393
- if (t2.absolute = path17__default.default.isAbsolute(t2.path) ? f(path17__default.default.resolve(t2.path)) : f(path17__default.default.resolve(this.cwd, t2.path)), !this.preservePaths && typeof t2.absolute == "string" && t2.absolute.indexOf(this.cwd + "/") !== 0 && t2.absolute !== this.cwd) return this.warn("TAR_ENTRY_ERROR", "path escaped extraction target", { entry: t2, path: f(t2.path), resolvedPath: t2.absolute, cwd: this.cwd }), false;
23702
+ if (t2.absolute = path14__default.default.isAbsolute(t2.path) ? f(path14__default.default.resolve(t2.path)) : f(path14__default.default.resolve(this.cwd, t2.path)), !this.preservePaths && typeof t2.absolute == "string" && t2.absolute.indexOf(this.cwd + "/") !== 0 && t2.absolute !== this.cwd) return this.warn("TAR_ENTRY_ERROR", "path escaped extraction target", { entry: t2, path: f(t2.path), resolvedPath: t2.absolute, cwd: this.cwd }), false;
23394
23703
  if (t2.absolute === this.cwd && t2.type !== "Directory" && t2.type !== "GNUDumpDir") return false;
23395
23704
  if (this.win32) {
23396
- let { root: r } = path17__default.default.win32.parse(String(t2.absolute));
23705
+ let { root: r } = path14__default.default.win32.parse(String(t2.absolute));
23397
23706
  t2.absolute = r + Xi(String(t2.absolute).slice(r.length));
23398
- let { root: n2 } = path17__default.default.win32.parse(t2.path);
23707
+ let { root: n2 } = path14__default.default.win32.parse(t2.path);
23399
23708
  t2.path = n2 + Xi(t2.path.slice(n2.length));
23400
23709
  }
23401
23710
  return true;
@@ -23483,13 +23792,13 @@ var qt = class extends st2 {
23483
23792
  t2.unsupported = true, this.warn("TAR_ENTRY_UNSUPPORTED", `unsupported entry type: ${t2.type}`, { entry: t2 }), t2.resume();
23484
23793
  }
23485
23794
  [Tr](t2, e) {
23486
- let i2 = f(path17__default.default.relative(this.cwd, path17__default.default.resolve(path17__default.default.dirname(String(t2.absolute)), String(t2.linkpath)))).split("/");
23795
+ let i2 = f(path14__default.default.relative(this.cwd, path14__default.default.resolve(path14__default.default.dirname(String(t2.absolute)), String(t2.linkpath)))).split("/");
23487
23796
  this[ye2](t2, this.cwd, i2, () => this[Si](t2, String(t2.linkpath), "symlink", e), (r) => {
23488
23797
  this[O2](r, t2), e();
23489
23798
  });
23490
23799
  }
23491
23800
  [xr](t2, e) {
23492
- let i2 = f(path17__default.default.resolve(this.cwd, String(t2.linkpath))), r = f(String(t2.linkpath)).split("/");
23801
+ let i2 = f(path14__default.default.resolve(this.cwd, String(t2.linkpath))), r = f(String(t2.linkpath)).split("/");
23493
23802
  this[ye2](t2, this.cwd, r, () => this[Si](t2, i2, "link", e), (n2) => {
23494
23803
  this[O2](n2, t2), e();
23495
23804
  });
@@ -23497,10 +23806,10 @@ var qt = class extends st2 {
23497
23806
  [ye2](t2, e, i2, r, n2) {
23498
23807
  let o2 = i2.shift();
23499
23808
  if (this.preservePaths || o2 === void 0) return r();
23500
- let h3 = path17__default.default.resolve(e, o2);
23809
+ let h3 = path14__default.default.resolve(e, o2);
23501
23810
  u2__default.default.lstat(h3, (a2, l) => {
23502
23811
  if (a2) return r();
23503
- if (l?.isSymbolicLink()) return n2(new wt2(h3, path17__default.default.resolve(h3, i2.join("/"))));
23812
+ if (l?.isSymbolicLink()) return n2(new wt2(h3, path14__default.default.resolve(h3, i2.join("/"))));
23504
23813
  this[ye2](t2, h3, i2, r, n2);
23505
23814
  });
23506
23815
  }
@@ -23534,7 +23843,7 @@ var qt = class extends st2 {
23534
23843
  });
23535
23844
  }, n2 = () => {
23536
23845
  if (t2.absolute !== this.cwd) {
23537
- let h3 = f(path17__default.default.dirname(String(t2.absolute)));
23846
+ let h3 = f(path14__default.default.dirname(String(t2.absolute)));
23538
23847
  if (h3 !== this.cwd) return this[St2](h3, this.dmode, (a2) => {
23539
23848
  if (a2) {
23540
23849
  this[O2](a2, t2), i2();
@@ -23609,7 +23918,7 @@ var Te2 = class extends qt {
23609
23918
  this[ge2] = true;
23610
23919
  }
23611
23920
  if (t2.absolute !== this.cwd) {
23612
- let n2 = f(path17__default.default.dirname(String(t2.absolute)));
23921
+ let n2 = f(path14__default.default.dirname(String(t2.absolute)));
23613
23922
  if (n2 !== this.cwd) {
23614
23923
  let o2 = this[St2](n2, this.dmode);
23615
23924
  if (o2) return this[O2](o2, t2);
@@ -23709,10 +24018,10 @@ var Te2 = class extends qt {
23709
24018
  if (this.preservePaths || i2.length === 0) return r();
23710
24019
  let o2 = e;
23711
24020
  for (let h3 of i2) {
23712
- o2 = path17__default.default.resolve(o2, h3);
24021
+ o2 = path14__default.default.resolve(o2, h3);
23713
24022
  let [a2, l] = Se2(() => u2__default.default.lstatSync(o2));
23714
24023
  if (a2) return r();
23715
- if (l.isSymbolicLink()) return n2(new wt2(o2, path17__default.default.resolve(e, i2.join("/"))));
24024
+ if (l.isSymbolicLink()) return n2(new wt2(o2, path14__default.default.resolve(e, i2.join("/"))));
23716
24025
  }
23717
24026
  r();
23718
24027
  }
@@ -23816,11 +24125,11 @@ var mo = (s3, t2) => {
23816
24125
  };
23817
24126
  var po = (s3, t2) => {
23818
24127
  t2.forEach((e) => {
23819
- e.charAt(0) === "@" ? It3({ file: path17__default.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
24128
+ e.charAt(0) === "@" ? It3({ file: path14__default.default.resolve(s3.cwd, e.slice(1)), sync: true, noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
23820
24129
  }), s3.end();
23821
24130
  };
23822
24131
  var Eo = async (s3, t2) => {
23823
- for (let e of t2) e.charAt(0) === "@" ? await It3({ file: path17__default.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
24132
+ for (let e of t2) e.charAt(0) === "@" ? await It3({ file: path14__default.default.resolve(String(s3.cwd), e.slice(1)), noResume: true, onReadEntry: (i2) => s3.add(i2) }) : s3.add(e);
23824
24133
  s3.end();
23825
24134
  };
23826
24135
  var vt3 = K2(fo, mo, () => {
@@ -23845,11 +24154,11 @@ var GITHUB_ORG = "nextlyhq";
23845
24154
  var GITHUB_REPO = "nextly";
23846
24155
  async function downloadTemplate(templateName, branch = "main") {
23847
24156
  const url = `https://codeload.github.com/${GITHUB_ORG}/${GITHUB_REPO}/tar.gz/${branch}`;
23848
- const tmpDir = path17__default.default.join(
24157
+ const tmpDir = path14__default.default.join(
23849
24158
  process.env.TMPDIR || "/tmp",
23850
24159
  `nextly-template-${Date.now()}`
23851
24160
  );
23852
- await import_fs_extra8.default.ensureDir(tmpDir);
24161
+ await import_fs_extra9.default.ensureDir(tmpDir);
23853
24162
  const repoPrefix = `${GITHUB_REPO}-${branch}`;
23854
24163
  const baseFilter = `${repoPrefix}/templates/base/`;
23855
24164
  const templateFilter = `${repoPrefix}/templates/${templateName}/`;
@@ -23878,7 +24187,7 @@ async function downloadTemplate(templateName, branch = "main") {
23878
24187
  })
23879
24188
  );
23880
24189
  } catch (error) {
23881
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
24190
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
23882
24191
  });
23883
24192
  if (error instanceof Error && error.name === "TimeoutError") {
23884
24193
  throw new Error(
@@ -23887,17 +24196,17 @@ async function downloadTemplate(templateName, branch = "main") {
23887
24196
  }
23888
24197
  throw error;
23889
24198
  }
23890
- const basePath = path17__default.default.join(tmpDir, "templates", "base");
23891
- const templatePath = path17__default.default.join(tmpDir, "templates", templateName);
23892
- if (!await import_fs_extra8.default.pathExists(basePath)) {
23893
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
24199
+ const basePath = path14__default.default.join(tmpDir, "templates", "base");
24200
+ const templatePath = path14__default.default.join(tmpDir, "templates", templateName);
24201
+ if (!await import_fs_extra9.default.pathExists(basePath)) {
24202
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
23894
24203
  });
23895
24204
  throw new Error(
23896
24205
  `Base template not found in downloaded archive. The branch "${branch}" may not contain templates.`
23897
24206
  );
23898
24207
  }
23899
- if (!await import_fs_extra8.default.pathExists(templatePath)) {
23900
- await import_fs_extra8.default.remove(tmpDir).catch(() => {
24208
+ if (!await import_fs_extra9.default.pathExists(templatePath)) {
24209
+ await import_fs_extra9.default.remove(tmpDir).catch(() => {
23901
24210
  });
23902
24211
  throw new Error(
23903
24212
  `Template "${templateName}" not found in downloaded archive. Available templates may differ on branch "${branch}".`
@@ -23906,14 +24215,14 @@ async function downloadTemplate(templateName, branch = "main") {
23906
24215
  return { basePath, templatePath };
23907
24216
  }
23908
24217
  async function resolveLocalTemplate(localPath, templateName) {
23909
- const basePath = path17__default.default.join(localPath, "base");
23910
- const templatePath = path17__default.default.join(localPath, templateName);
23911
- if (!await import_fs_extra8.default.pathExists(basePath)) {
24218
+ const basePath = path14__default.default.join(localPath, "base");
24219
+ const templatePath = path14__default.default.join(localPath, templateName);
24220
+ if (!await import_fs_extra9.default.pathExists(basePath)) {
23912
24221
  throw new Error(
23913
24222
  `Base template not found at ${basePath}. Check the --local-template path points to the templates/ directory.`
23914
24223
  );
23915
24224
  }
23916
- if (!await import_fs_extra8.default.pathExists(templatePath)) {
24225
+ if (!await import_fs_extra9.default.pathExists(templatePath)) {
23917
24226
  throw new Error(
23918
24227
  `Template "${templateName}" not found at ${templatePath}. Check the --local-template path points to the templates/ directory.`
23919
24228
  );
@@ -23930,8 +24239,8 @@ async function resolveTemplateSource(templateName, options = {}) {
23930
24239
  async function cleanupDownload(source) {
23931
24240
  const tmpBase = process.env.TMPDIR || "/tmp";
23932
24241
  if (source.basePath.startsWith(tmpBase)) {
23933
- const extractionRoot = path17__default.default.resolve(source.basePath, "../..");
23934
- await import_fs_extra8.default.remove(extractionRoot).catch(() => {
24242
+ const extractionRoot = path14__default.default.resolve(source.basePath, "../..");
24243
+ await import_fs_extra9.default.remove(extractionRoot).catch(() => {
23935
24244
  });
23936
24245
  }
23937
24246
  }
@@ -24035,12 +24344,12 @@ var DATABASE_LABELS = {
24035
24344
  };
24036
24345
 
24037
24346
  // src/prompts/project-name.ts
24038
- var import_fs_extra9 = __toESM(require_lib());
24347
+ var import_fs_extra10 = __toESM(require_lib());
24039
24348
  async function isExistingNextProject(cwd) {
24040
- const packageJsonPath = path17__default.default.join(cwd, "package.json");
24041
- if (!await import_fs_extra9.default.pathExists(packageJsonPath)) return false;
24349
+ const packageJsonPath = path14__default.default.join(cwd, "package.json");
24350
+ if (!await import_fs_extra10.default.pathExists(packageJsonPath)) return false;
24042
24351
  try {
24043
- const packageJson = await import_fs_extra9.default.readJson(packageJsonPath);
24352
+ const packageJson = await import_fs_extra10.default.readJson(packageJsonPath);
24044
24353
  const deps = {
24045
24354
  ...packageJson.dependencies,
24046
24355
  ...packageJson.devDependencies
@@ -24077,7 +24386,7 @@ function isValidTemplateSelection(value) {
24077
24386
  }
24078
24387
 
24079
24388
  // src/utils/detect.ts
24080
- var import_fs_extra10 = __toESM(require_lib());
24389
+ var import_fs_extra11 = __toESM(require_lib());
24081
24390
 
24082
24391
  // src/utils/detect-pm-from-user-agent.ts
24083
24392
  function detectPmFromUserAgent(userAgent) {
@@ -24093,19 +24402,19 @@ function detectPmFromUserAgent(userAgent) {
24093
24402
  async function detectPackageManager(cwd) {
24094
24403
  const fromUa = detectPmFromUserAgent(process.env.npm_config_user_agent);
24095
24404
  if (fromUa) return fromUa;
24096
- if (await import_fs_extra10.default.pathExists(path17__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
24097
- if (await import_fs_extra10.default.pathExists(path17__default.default.join(cwd, "yarn.lock"))) return "yarn";
24098
- if (await import_fs_extra10.default.pathExists(path17__default.default.join(cwd, "bun.lockb"))) return "bun";
24405
+ if (await import_fs_extra11.default.pathExists(path14__default.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
24406
+ if (await import_fs_extra11.default.pathExists(path14__default.default.join(cwd, "yarn.lock"))) return "yarn";
24407
+ if (await import_fs_extra11.default.pathExists(path14__default.default.join(cwd, "bun.lockb"))) return "bun";
24099
24408
  return "npm";
24100
24409
  }
24101
24410
  async function detectProject(cwd) {
24102
- const packageJsonPath = path17__default.default.join(cwd, "package.json");
24103
- if (!await import_fs_extra10.default.pathExists(packageJsonPath)) {
24411
+ const packageJsonPath = path14__default.default.join(cwd, "package.json");
24412
+ if (!await import_fs_extra11.default.pathExists(packageJsonPath)) {
24104
24413
  throw new Error(
24105
24414
  "No package.json found. Please run this command in a Next.js project."
24106
24415
  );
24107
24416
  }
24108
- const packageJson = await import_fs_extra10.default.readJson(packageJsonPath);
24417
+ const packageJson = await import_fs_extra11.default.readJson(packageJsonPath);
24109
24418
  const deps = {
24110
24419
  ...packageJson.dependencies,
24111
24420
  ...packageJson.devDependencies
@@ -24117,11 +24426,11 @@ async function detectProject(cwd) {
24117
24426
  );
24118
24427
  }
24119
24428
  const nextVersion = deps.next?.replace(/[\^~]/, "") || null;
24120
- const srcDir = await import_fs_extra10.default.pathExists(path17__default.default.join(cwd, "src"));
24121
- const appDirPaths = srcDir ? [path17__default.default.join(cwd, "src", "app")] : [path17__default.default.join(cwd, "app")];
24429
+ const srcDir = await import_fs_extra11.default.pathExists(path14__default.default.join(cwd, "src"));
24430
+ const appDirPaths = srcDir ? [path14__default.default.join(cwd, "src", "app")] : [path14__default.default.join(cwd, "app")];
24122
24431
  let isAppRouter = false;
24123
24432
  for (const appPath of appDirPaths) {
24124
- if (await import_fs_extra10.default.pathExists(appPath)) {
24433
+ if (await import_fs_extra11.default.pathExists(appPath)) {
24125
24434
  isAppRouter = true;
24126
24435
  break;
24127
24436
  }
@@ -24131,7 +24440,7 @@ async function detectProject(cwd) {
24131
24440
  "App Router not detected. Nextly requires Next.js App Router (app/ directory)."
24132
24441
  );
24133
24442
  }
24134
- const hasTypescript = await import_fs_extra10.default.pathExists(path17__default.default.join(cwd, "tsconfig.json"));
24443
+ const hasTypescript = await import_fs_extra11.default.pathExists(path14__default.default.join(cwd, "tsconfig.json"));
24135
24444
  const packageManager = await detectPackageManager(cwd);
24136
24445
  const appDir = srcDir ? "src/app" : "app";
24137
24446
  return {
@@ -24145,307 +24454,6 @@ async function detectProject(cwd) {
24145
24454
  };
24146
24455
  }
24147
24456
 
24148
- // src/utils/template.ts
24149
- var import_fs_extra11 = __toESM(require_lib());
24150
- var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
24151
- ".ts",
24152
- ".tsx",
24153
- ".js",
24154
- ".jsx",
24155
- ".json",
24156
- ".env",
24157
- ".md",
24158
- ".css",
24159
- ".html",
24160
- ".mjs",
24161
- ".cjs"
24162
- ]);
24163
- var SKIP_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", ".gitkeep"]);
24164
- function resolveTemplatePath(localTemplatePath) {
24165
- const __dirname = path17__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
24166
- const fromDist = path17__default.default.resolve(__dirname, "../templates");
24167
- if (import_fs_extra11.default.existsSync(fromDist)) {
24168
- return fromDist;
24169
- }
24170
- const fromSrc = path17__default.default.resolve(__dirname, "../../templates");
24171
- if (import_fs_extra11.default.existsSync(fromSrc)) {
24172
- return fromSrc;
24173
- }
24174
- throw new Error(
24175
- "Could not find templates directory. Use --local-template to specify the templates path, or ensure templates are bundled."
24176
- );
24177
- }
24178
- function buildPlaceholderMap(options) {
24179
- const { database, databaseUrl } = options;
24180
- return {
24181
- "{{databaseDialect}}": database.type,
24182
- "{{databaseUrl}}": databaseUrl || database.envExample
24183
- };
24184
- }
24185
- async function replacePlaceholdersInFile(filePath, placeholders) {
24186
- const ext = path17__default.default.extname(filePath).toLowerCase();
24187
- const basename = path17__default.default.basename(filePath);
24188
- const isTextFile = TEXT_EXTENSIONS.has(ext) || basename.startsWith(".env") || basename === ".gitignore";
24189
- if (!isTextFile) return;
24190
- let content = await import_fs_extra11.default.readFile(filePath, "utf-8");
24191
- let changed = false;
24192
- for (const [placeholder, value] of Object.entries(placeholders)) {
24193
- if (content.includes(placeholder)) {
24194
- content = content.replaceAll(placeholder, value);
24195
- changed = true;
24196
- }
24197
- }
24198
- if (changed) {
24199
- await import_fs_extra11.default.writeFile(filePath, content, "utf-8");
24200
- }
24201
- }
24202
- async function replacePlaceholders(dir, placeholders) {
24203
- const entries = await import_fs_extra11.default.readdir(dir, { withFileTypes: true });
24204
- for (const entry of entries) {
24205
- const fullPath = path17__default.default.join(dir, entry.name);
24206
- if (entry.isDirectory()) {
24207
- if (entry.name === "node_modules" || entry.name === ".git") continue;
24208
- await replacePlaceholders(fullPath, placeholders);
24209
- } else if (entry.isFile()) {
24210
- await replacePlaceholdersInFile(fullPath, placeholders);
24211
- }
24212
- }
24213
- }
24214
- var PINNED_VERSIONS = {
24215
- // Next.js ecosystem — resolved at runtime via fetchLatestVersion()
24216
- // (see generatePackageJson)
24217
- react: "^19.1.0",
24218
- "react-dom": "^19.1.0",
24219
- // Dev dependencies
24220
- typescript: "^5",
24221
- "@types/node": "^20",
24222
- "@types/react": "^19",
24223
- "@types/react-dom": "^19",
24224
- "@tailwindcss/postcss": "^4",
24225
- tailwindcss: "^4",
24226
- eslint: "^9"
24227
- };
24228
- var RUNTIME_RESOLVED_PACKAGES = ["next", "eslint-config-next"];
24229
- var NEXTLY_PACKAGES = [
24230
- "nextly",
24231
- "@nextlyhq/admin",
24232
- "@nextlyhq/adapter-drizzle",
24233
- "@nextlyhq/adapter-postgres",
24234
- "@nextlyhq/adapter-mysql",
24235
- "@nextlyhq/adapter-sqlite"
24236
- ];
24237
- var resolvedNextlyVersions = null;
24238
- async function fetchLatestVersion(pkg) {
24239
- try {
24240
- const res = await fetch(
24241
- `https://registry.npmjs.org/-/package/${encodeURIComponent(pkg)}/dist-tags`,
24242
- { signal: AbortSignal.timeout(5e3) }
24243
- );
24244
- if (!res.ok) return "latest";
24245
- const data = await res.json();
24246
- return data.latest ? `^${data.latest}` : "latest";
24247
- } catch {
24248
- return "latest";
24249
- }
24250
- }
24251
- async function resolveNextlyVersions() {
24252
- if (resolvedNextlyVersions) return resolvedNextlyVersions;
24253
- const entries = await Promise.all(
24254
- NEXTLY_PACKAGES.map(
24255
- async (pkg) => [pkg, await fetchLatestVersion(pkg)]
24256
- )
24257
- );
24258
- resolvedNextlyVersions = Object.fromEntries(entries);
24259
- return resolvedNextlyVersions;
24260
- }
24261
- var resolvedRuntimeVersions = null;
24262
- async function resolveRuntimeVersions() {
24263
- if (resolvedRuntimeVersions) return resolvedRuntimeVersions;
24264
- const FALLBACKS = {
24265
- next: "^16.1.0",
24266
- "eslint-config-next": "^16.1.0"
24267
- };
24268
- const entries = await Promise.all(
24269
- RUNTIME_RESOLVED_PACKAGES.map(async (pkg) => {
24270
- const version = await fetchLatestVersion(pkg);
24271
- return [pkg, version === "latest" ? FALLBACKS[pkg] : version];
24272
- })
24273
- );
24274
- resolvedRuntimeVersions = Object.fromEntries(entries);
24275
- return resolvedRuntimeVersions;
24276
- }
24277
- async function generatePackageJson(projectName, database, useYalc = false) {
24278
- const runtimeVersions = await resolveRuntimeVersions();
24279
- const dependencies = {
24280
- next: runtimeVersions.next,
24281
- react: PINNED_VERSIONS.react,
24282
- "react-dom": PINNED_VERSIONS["react-dom"]
24283
- };
24284
- dependencies["@tanstack/react-query"] = "^5.62.0";
24285
- if (!useYalc) {
24286
- const versions = await resolveNextlyVersions();
24287
- dependencies["nextly"] = versions["nextly"];
24288
- dependencies["@nextlyhq/admin"] = versions["@nextlyhq/admin"];
24289
- dependencies["@nextlyhq/ui"] = versions["@nextlyhq/ui"] || "latest";
24290
- dependencies["@nextlyhq/adapter-drizzle"] = versions["@nextlyhq/adapter-drizzle"];
24291
- dependencies[database.adapter] = versions[database.adapter] || "latest";
24292
- dependencies["@nextlyhq/plugin-form-builder"] = versions["@nextlyhq/plugin-form-builder"] || "latest";
24293
- }
24294
- const devDependencies = {
24295
- typescript: PINNED_VERSIONS.typescript,
24296
- "@types/node": PINNED_VERSIONS["@types/node"],
24297
- "@types/react": PINNED_VERSIONS["@types/react"],
24298
- "@types/react-dom": PINNED_VERSIONS["@types/react-dom"],
24299
- "@tailwindcss/postcss": PINNED_VERSIONS["@tailwindcss/postcss"],
24300
- tailwindcss: PINNED_VERSIONS.tailwindcss,
24301
- eslint: PINNED_VERSIONS.eslint,
24302
- "eslint-config-next": runtimeVersions["eslint-config-next"],
24303
- // Pagefind powers /search in the blog template. Zero-config
24304
- // static index generated at `next build` time. Templates that
24305
- // don't ship a /search page simply won't invoke it.
24306
- pagefind: "^1.1.0"
24307
- };
24308
- const pkg = {
24309
- name: projectName,
24310
- version: "0.1.0",
24311
- private: true,
24312
- scripts: {
24313
- // F1 PR 4: dev now boots Nextly in single-process mode via `next dev`.
24314
- // The lazy drizzle-kit/api import (PR 1) plus the in-process HMR
24315
- // listener (PR 2) replaced the wrapper that previously owned the
24316
- // terminal, schema prompts, and child supervision. `nextly dev` is
24317
- // gone; the only supported dev command is the standard `next dev`.
24318
- dev: "next dev --turbopack",
24319
- // Build: migrate DB + compile Next.js + (if present) generate
24320
- // the Pagefind search index. Templates without the search
24321
- // script silently skip the last step.
24322
- build: "nextly migrate && next build && (test -f scripts/build-search-index.mjs && node scripts/build-search-index.mjs || true)",
24323
- "search:index": "node scripts/build-search-index.mjs",
24324
- start: "next start",
24325
- lint: "next lint",
24326
- nextly: "nextly",
24327
- // First-time setup: sync schema + seed system permissions. Demo
24328
- // content is seeded separately from the admin UI (visit /welcome
24329
- // after running `pnpm dev` and completing /admin/setup).
24330
- "db:setup": "nextly db:sync",
24331
- "db:migrate": "nextly migrate",
24332
- "db:migrate:status": "nextly migrate:status",
24333
- "db:migrate:fresh": "nextly migrate:fresh",
24334
- "db:migrate:reset": "nextly migrate:reset",
24335
- "types:generate": "nextly generate:types"
24336
- },
24337
- dependencies,
24338
- devDependencies
24339
- };
24340
- return JSON.stringify(pkg, null, 2) + "\n";
24341
- }
24342
- async function copyTemplate(options) {
24343
- const {
24344
- projectName,
24345
- projectType,
24346
- targetDir,
24347
- database,
24348
- databaseUrl,
24349
- useYalc = false,
24350
- approach,
24351
- templateSource
24352
- } = options;
24353
- if (targetDir !== process.cwd() && await import_fs_extra11.default.pathExists(targetDir)) {
24354
- throw new Error(
24355
- `Directory "${path17__default.default.basename(targetDir)}" already exists. Please choose a different name.`
24356
- );
24357
- }
24358
- let baseDir;
24359
- let typeDir;
24360
- if (templateSource) {
24361
- baseDir = templateSource.basePath;
24362
- typeDir = templateSource.templatePath;
24363
- } else {
24364
- const templatesRoot = resolveTemplatePath();
24365
- baseDir = path17__default.default.join(templatesRoot, "base");
24366
- typeDir = path17__default.default.join(templatesRoot, projectType);
24367
- }
24368
- if (!await import_fs_extra11.default.pathExists(baseDir)) {
24369
- throw new Error(
24370
- `Base template not found at ${baseDir}. The package may be corrupted or the download failed.`
24371
- );
24372
- }
24373
- if (!await import_fs_extra11.default.pathExists(typeDir)) {
24374
- throw new Error(
24375
- `Template "${projectType}" not found at ${typeDir}. Available templates: blank, blog.`
24376
- );
24377
- }
24378
- await import_fs_extra11.default.copy(baseDir, targetDir, {
24379
- filter: (_src) => {
24380
- const basename = path17__default.default.basename(_src);
24381
- return !SKIP_FILES.has(basename);
24382
- }
24383
- });
24384
- const templateSrcDir = path17__default.default.join(typeDir, "src");
24385
- if (await import_fs_extra11.default.pathExists(templateSrcDir)) {
24386
- await import_fs_extra11.default.copy(templateSrcDir, path17__default.default.join(targetDir, "src"), {
24387
- overwrite: true,
24388
- filter: (_src) => {
24389
- const basename = path17__default.default.basename(_src);
24390
- return !SKIP_FILES.has(basename);
24391
- }
24392
- });
24393
- }
24394
- const templateRootConfig = path17__default.default.join(typeDir, "nextly.config.ts");
24395
- if (await import_fs_extra11.default.pathExists(templateRootConfig)) {
24396
- await import_fs_extra11.default.copy(
24397
- templateRootConfig,
24398
- path17__default.default.join(targetDir, "nextly.config.ts"),
24399
- { overwrite: true }
24400
- );
24401
- }
24402
- const configsDir = path17__default.default.join(typeDir, "configs");
24403
- if (approach && await import_fs_extra11.default.pathExists(configsDir)) {
24404
- const configFileName = approach === "code-first" ? "codefirst.config.ts" : `${approach}.config.ts`;
24405
- const configSrc = path17__default.default.join(configsDir, configFileName);
24406
- if (await import_fs_extra11.default.pathExists(configSrc)) {
24407
- await import_fs_extra11.default.copy(configSrc, path17__default.default.join(targetDir, "nextly.config.ts"), {
24408
- overwrite: true
24409
- });
24410
- }
24411
- const sharedSrc = path17__default.default.join(configsDir, "shared.ts");
24412
- if (await import_fs_extra11.default.pathExists(sharedSrc)) {
24413
- await import_fs_extra11.default.copy(sharedSrc, path17__default.default.join(targetDir, "shared.ts"), {
24414
- overwrite: true
24415
- });
24416
- }
24417
- }
24418
- const frontendPagePath = path17__default.default.join(
24419
- targetDir,
24420
- "src",
24421
- "app",
24422
- "(frontend)",
24423
- "page.tsx"
24424
- );
24425
- const basePagePath = path17__default.default.join(targetDir, "src", "app", "page.tsx");
24426
- if (await import_fs_extra11.default.pathExists(frontendPagePath) && await import_fs_extra11.default.pathExists(basePagePath)) {
24427
- await import_fs_extra11.default.remove(basePagePath);
24428
- }
24429
- const packageJsonContent = await generatePackageJson(
24430
- projectName,
24431
- database,
24432
- useYalc
24433
- );
24434
- await import_fs_extra11.default.writeFile(
24435
- path17__default.default.join(targetDir, "package.json"),
24436
- packageJsonContent,
24437
- "utf-8"
24438
- );
24439
- if (database.type === "sqlite") {
24440
- await import_fs_extra11.default.ensureDir(path17__default.default.join(targetDir, "data"));
24441
- }
24442
- const placeholders = buildPlaceholderMap({ database, databaseUrl });
24443
- if (approach) {
24444
- placeholders["{{approach}}"] = approach;
24445
- }
24446
- await replacePlaceholders(targetDir, placeholders);
24447
- }
24448
-
24449
24457
  // src/create-nextly.ts
24450
24458
  async function createNextly(options = {}) {
24451
24459
  const {
@@ -24474,7 +24482,7 @@ async function createNextly(options = {}) {
24474
24482
  }
24475
24483
  }
24476
24484
  } else if (installInCwd) {
24477
- projectName = path17__default.default.basename(cwd);
24485
+ projectName = path14__default.default.basename(cwd);
24478
24486
  isFreshProject = true;
24479
24487
  } else {
24480
24488
  if (options.projectNameFromArg) {
@@ -24606,7 +24614,7 @@ async function createNextly(options = {}) {
24606
24614
  } else {
24607
24615
  s3.start("Scaffolding project...");
24608
24616
  }
24609
- const targetDir = installInCwd ? cwd : path17__default.default.join(cwd, projectName);
24617
+ const targetDir = installInCwd ? cwd : path14__default.default.join(cwd, projectName);
24610
24618
  if (installInCwd) {
24611
24619
  const entries = await import_fs_extra12.default.readdir(cwd);
24612
24620
  const nonHidden = entries.filter((e) => !e.startsWith("."));
@@ -24644,7 +24652,7 @@ async function createNextly(options = {}) {
24644
24652
  } catch (error) {
24645
24653
  s3.stop("Scaffolding failed");
24646
24654
  if (!installInCwd) {
24647
- const targetDir = path17__default.default.join(cwd, projectName);
24655
+ const targetDir = path14__default.default.join(cwd, projectName);
24648
24656
  if (await import_fs_extra12.default.pathExists(targetDir)) {
24649
24657
  await import_fs_extra12.default.remove(targetDir);
24650
24658
  }
@@ -24686,7 +24694,8 @@ async function createNextly(options = {}) {
24686
24694
  projectInfo,
24687
24695
  database,
24688
24696
  useYalc,
24689
- isFreshProject
24697
+ isFreshProject,
24698
+ projectType
24690
24699
  );
24691
24700
  s3.stop("Dependencies installed");
24692
24701
  capture("install_completed", {