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/{chunk-AYJ2RKVJ.mjs → chunk-6NVRVAZA.mjs} +431 -422
- package/dist/chunk-6NVRVAZA.mjs.map +1 -0
- package/dist/cli.cjs +430 -421
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +429 -420
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +4 -4
- package/templates/base/src/app/admin/[[...params]]/page.tsx +0 -9
- package/dist/chunk-AYJ2RKVJ.mjs.map +0 -1
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.
|
|
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
|
-
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
|
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
|
|
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),
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
31424
|
-
await
|
|
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
|
|
31431
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
31570
|
-
async function isExistingNextProject(cwd) {
|
|
31571
|
-
const packageJsonPath = path__default.default.join(cwd, "package.json");
|
|
31572
|
-
if (!await
|
|
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
|
|
31772
|
-
|
|
31773
|
-
|
|
31774
|
-
|
|
31775
|
-
|
|
31776
|
-
|
|
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
|
|
31890
|
+
return false;
|
|
31780
31891
|
}
|
|
31781
31892
|
}
|
|
31782
|
-
|
|
31783
|
-
|
|
31784
|
-
|
|
31785
|
-
|
|
31786
|
-
|
|
31787
|
-
|
|
31788
|
-
|
|
31789
|
-
|
|
31790
|
-
|
|
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
|
-
|
|
31793
|
-
|
|
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
|
-
|
|
31809
|
-
|
|
31810
|
-
|
|
31811
|
-
|
|
31812
|
-
|
|
31813
|
-
|
|
31814
|
-
|
|
31815
|
-
|
|
31816
|
-
if (
|
|
31817
|
-
|
|
31818
|
-
|
|
31819
|
-
|
|
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
|
-
|
|
31874
|
-
|
|
31875
|
-
|
|
31876
|
-
|
|
31877
|
-
|
|
31878
|
-
|
|
31879
|
-
|
|
31880
|
-
|
|
31881
|
-
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
|
|
31885
|
-
|
|
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
|
-
|
|
31945
|
+
"No package.json found. Please run this command in a Next.js project."
|
|
31902
31946
|
);
|
|
31903
31947
|
}
|
|
31904
|
-
|
|
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
|
-
|
|
31956
|
+
"Next.js not found in dependencies. Please run this in a Next.js project."
|
|
31907
31957
|
);
|
|
31908
31958
|
}
|
|
31909
|
-
|
|
31910
|
-
|
|
31911
|
-
|
|
31912
|
-
|
|
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
|
-
|
|
31926
|
-
|
|
31927
|
-
|
|
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
|
|
31934
|
-
|
|
31935
|
-
|
|
31936
|
-
|
|
31937
|
-
|
|
31938
|
-
|
|
31939
|
-
|
|
31940
|
-
|
|
31941
|
-
|
|
31942
|
-
|
|
31943
|
-
|
|
31944
|
-
|
|
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", {
|