create-nextly-app 0.0.2-alpha.56 → 0.0.2-alpha.58
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-6434MGWG.mjs → chunk-E6IFBI6N.mjs} +141 -18
- package/dist/chunk-E6IFBI6N.mjs.map +1 -0
- package/dist/cli.cjs +141 -18
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +3 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +139 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
- package/templates/base/gitignore +42 -0
- package/templates/base/src/app/globals.css +15 -2
- package/templates/base/src/app/layout.tsx +30 -15
- package/templates/base/tsconfig.json +7 -1
- package/templates/blank/src/app/globals.css +37 -1
- package/templates/blank/src/app/layout.tsx +26 -15
- package/templates/plugin/gitignore +10 -0
- package/dist/chunk-6434MGWG.mjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -21125,6 +21125,47 @@ var import_fs_extra8 = __toESM(require_lib());
|
|
|
21125
21125
|
var PROJECT_TYPES_WITH_FORM_BUILDER = /* @__PURE__ */ new Set([
|
|
21126
21126
|
"blog"
|
|
21127
21127
|
]);
|
|
21128
|
+
var FONT_PACKAGE_RANGE = "^5.3.0";
|
|
21129
|
+
var FONT_PACKAGE_PATTERN = /@fontsource(?:-variable)?\/[a-z0-9-]+/g;
|
|
21130
|
+
async function collectFontDependencies(templateDirs) {
|
|
21131
|
+
const effective = await effectiveTemplateFiles(templateDirs);
|
|
21132
|
+
const found = /* @__PURE__ */ new Set();
|
|
21133
|
+
for (const file of effective.values()) {
|
|
21134
|
+
const contents = await import_fs_extra8.default.readFile(file, "utf8");
|
|
21135
|
+
for (const match of contents.matchAll(FONT_PACKAGE_PATTERN)) {
|
|
21136
|
+
found.add(match[0]);
|
|
21137
|
+
}
|
|
21138
|
+
}
|
|
21139
|
+
return [...found].sort();
|
|
21140
|
+
}
|
|
21141
|
+
async function effectiveTemplateFiles(templateDirs) {
|
|
21142
|
+
const effective = /* @__PURE__ */ new Map();
|
|
21143
|
+
for (const root of templateDirs) {
|
|
21144
|
+
if (!root || !await import_fs_extra8.default.pathExists(root)) continue;
|
|
21145
|
+
for (const file of await walkSourceFiles(root)) {
|
|
21146
|
+
effective.set(path14__default.default.relative(root, file), file);
|
|
21147
|
+
}
|
|
21148
|
+
}
|
|
21149
|
+
return effective;
|
|
21150
|
+
}
|
|
21151
|
+
var SEARCH_INDEX_SCRIPT = path14__default.default.join("scripts", "build-search-index.mjs");
|
|
21152
|
+
async function projectHasSearchIndexScript(targetDir) {
|
|
21153
|
+
return import_fs_extra8.default.pathExists(path14__default.default.join(targetDir, SEARCH_INDEX_SCRIPT));
|
|
21154
|
+
}
|
|
21155
|
+
async function walkSourceFiles(root) {
|
|
21156
|
+
const out = [];
|
|
21157
|
+
const entries = await import_fs_extra8.default.readdir(root, { withFileTypes: true });
|
|
21158
|
+
for (const entry of entries) {
|
|
21159
|
+
const full = path14__default.default.join(root, entry.name);
|
|
21160
|
+
if (entry.isDirectory()) {
|
|
21161
|
+
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
21162
|
+
out.push(...await walkSourceFiles(full));
|
|
21163
|
+
} else if (/\.(?:tsx?|jsx?|mjs|cjs|css)$/.test(entry.name)) {
|
|
21164
|
+
out.push(full);
|
|
21165
|
+
}
|
|
21166
|
+
}
|
|
21167
|
+
return out;
|
|
21168
|
+
}
|
|
21128
21169
|
function projectUsesFormBuilder(projectType) {
|
|
21129
21170
|
return PROJECT_TYPES_WITH_FORM_BUILDER.has(projectType);
|
|
21130
21171
|
}
|
|
@@ -21146,6 +21187,15 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
21146
21187
|
".cjs"
|
|
21147
21188
|
]);
|
|
21148
21189
|
var SKIP_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db", ".gitkeep"]);
|
|
21190
|
+
var IGNORE_FILE_IN_TEMPLATE = "gitignore";
|
|
21191
|
+
var IGNORE_FILE_IN_PROJECT = ".gitignore";
|
|
21192
|
+
async function restoreIgnoreFile(targetDir) {
|
|
21193
|
+
const shipped = path14__default.default.join(targetDir, IGNORE_FILE_IN_TEMPLATE);
|
|
21194
|
+
if (!await import_fs_extra8.default.pathExists(shipped)) return;
|
|
21195
|
+
await import_fs_extra8.default.move(shipped, path14__default.default.join(targetDir, IGNORE_FILE_IN_PROJECT), {
|
|
21196
|
+
overwrite: true
|
|
21197
|
+
});
|
|
21198
|
+
}
|
|
21149
21199
|
function resolveTemplatePath(localTemplatePath) {
|
|
21150
21200
|
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))));
|
|
21151
21201
|
const fromDist = path14__default.default.resolve(__dirname, "../templates");
|
|
@@ -21269,7 +21319,7 @@ async function resolveRuntimeVersions() {
|
|
|
21269
21319
|
resolvedRuntimeVersions = Object.fromEntries(entries);
|
|
21270
21320
|
return resolvedRuntimeVersions;
|
|
21271
21321
|
}
|
|
21272
|
-
async function generatePackageJson(projectName, database, useYalc = false, projectType = "blank") {
|
|
21322
|
+
async function generatePackageJson(projectName, database, useYalc = false, projectType = "blank", templateDirs = [], targetDir) {
|
|
21273
21323
|
if (projectType === "plugin") {
|
|
21274
21324
|
return generatePluginPackageJson(projectName, useYalc);
|
|
21275
21325
|
}
|
|
@@ -21281,6 +21331,9 @@ async function generatePackageJson(projectName, database, useYalc = false, proje
|
|
|
21281
21331
|
};
|
|
21282
21332
|
dependencies["@tanstack/react-query"] = "^5.62.0";
|
|
21283
21333
|
dependencies["lucide-react"] = "^0.544.0";
|
|
21334
|
+
for (const font of await collectFontDependencies(templateDirs)) {
|
|
21335
|
+
dependencies[font] = FONT_PACKAGE_RANGE;
|
|
21336
|
+
}
|
|
21284
21337
|
if (!useYalc) {
|
|
21285
21338
|
const versions = await resolveNextlyVersions(
|
|
21286
21339
|
templateNextlyChannel(projectType)
|
|
@@ -21303,12 +21356,10 @@ async function generatePackageJson(projectName, database, useYalc = false, proje
|
|
|
21303
21356
|
"@tailwindcss/postcss": PINNED_VERSIONS["@tailwindcss/postcss"],
|
|
21304
21357
|
tailwindcss: PINNED_VERSIONS.tailwindcss,
|
|
21305
21358
|
eslint: PINNED_VERSIONS.eslint,
|
|
21306
|
-
"eslint-config-next": runtimeVersions["eslint-config-next"]
|
|
21307
|
-
// Pagefind powers /search in the blog template. Zero-config
|
|
21308
|
-
// static index generated at `next build` time. Templates that
|
|
21309
|
-
// don't ship a /search page simply won't invoke it.
|
|
21310
|
-
pagefind: "^1.1.0"
|
|
21359
|
+
"eslint-config-next": runtimeVersions["eslint-config-next"]
|
|
21311
21360
|
};
|
|
21361
|
+
const shipsSearchIndex = targetDir ? await projectHasSearchIndexScript(targetDir) : false;
|
|
21362
|
+
if (shipsSearchIndex) devDependencies.pagefind = "^1.1.0";
|
|
21312
21363
|
const pkg = {
|
|
21313
21364
|
name: projectName,
|
|
21314
21365
|
version: "0.1.0",
|
|
@@ -21320,11 +21371,25 @@ async function generatePackageJson(projectName, database, useYalc = false, proje
|
|
|
21320
21371
|
// prompts, and child supervision. `nextly dev` is gone; the only
|
|
21321
21372
|
// supported dev command is the standard `next dev`.
|
|
21322
21373
|
dev: "next dev --turbopack",
|
|
21323
|
-
// Build: migrate
|
|
21324
|
-
//
|
|
21325
|
-
//
|
|
21326
|
-
|
|
21327
|
-
|
|
21374
|
+
// Build: migrate the database, compile Next.js, and generate the Pagefind
|
|
21375
|
+
// search index for the templates that ship its builder.
|
|
21376
|
+
//
|
|
21377
|
+
// Whether that last step appears is decided HERE, from the files the
|
|
21378
|
+
// scaffold actually received, rather than by a shell conditional in the
|
|
21379
|
+
// script. Two reasons, and both were live:
|
|
21380
|
+
//
|
|
21381
|
+
// `npm run` uses cmd.exe on Windows, which has no `test` and no `true` —
|
|
21382
|
+
// so the `(test -f … || true)` form this replaces failed for every Windows
|
|
21383
|
+
// user, after `next build` had already succeeded. `&&` is all that remains,
|
|
21384
|
+
// and cmd.exe understands it.
|
|
21385
|
+
//
|
|
21386
|
+
// And `|| true` turned a failed index build into a successful one. The
|
|
21387
|
+
// search page then ships pointing at an index that was never written,
|
|
21388
|
+
// which fails in the browser rather than in CI.
|
|
21389
|
+
build: shipsSearchIndex ? "nextly migrate && next build && node scripts/build-search-index.mjs" : "nextly migrate && next build",
|
|
21390
|
+
// Offered only where the file exists. A script that always fails is worse
|
|
21391
|
+
// than an absent one: it reads as a supported command.
|
|
21392
|
+
...shipsSearchIndex ? { "search:index": "node scripts/build-search-index.mjs" } : {},
|
|
21328
21393
|
start: "next start",
|
|
21329
21394
|
lint: "next lint",
|
|
21330
21395
|
nextly: "nextly",
|
|
@@ -21334,8 +21399,11 @@ async function generatePackageJson(projectName, database, useYalc = false, proje
|
|
|
21334
21399
|
"db:setup": "nextly db:sync",
|
|
21335
21400
|
"db:migrate": "nextly migrate",
|
|
21336
21401
|
"db:migrate:status": "nextly migrate:status",
|
|
21402
|
+
// No `db:migrate:reset`: `nextly migrate:reset` is not a command the CLI
|
|
21403
|
+
// registers, so the script it generated failed for every scaffolded
|
|
21404
|
+
// project. `migrate:fresh` is the one that drops all tables and re-runs
|
|
21405
|
+
// the migrations, and it is already exposed above.
|
|
21337
21406
|
"db:migrate:fresh": "nextly migrate:fresh",
|
|
21338
|
-
"db:migrate:reset": "nextly migrate:reset",
|
|
21339
21407
|
"types:generate": "nextly generate:types"
|
|
21340
21408
|
},
|
|
21341
21409
|
dependencies,
|
|
@@ -21437,13 +21505,46 @@ function generatePnpmWorkspaceYaml() {
|
|
|
21437
21505
|
# compiled binding (sqlite apps crash at boot) and sharp/esbuild degrade.
|
|
21438
21506
|
#
|
|
21439
21507
|
# pnpm 11+ reads \`allowBuilds\`; pnpm 10.6+ reads \`onlyBuiltDependencies\`.
|
|
21440
|
-
# npm
|
|
21508
|
+
# npm and yarn ignore this file; pnpm 9 needs neither key, because it runs
|
|
21509
|
+
# build scripts by default.
|
|
21510
|
+
#
|
|
21511
|
+
# It does still READ the file, which is what the empty \`packages\` list is
|
|
21512
|
+
# for: through pnpm 9.3 the presence of this file declares a workspace, and
|
|
21513
|
+
# a missing \`packages\` key fails the install outright. This app has no
|
|
21514
|
+
# workspace members.
|
|
21515
|
+
packages: []
|
|
21441
21516
|
allowBuilds:
|
|
21442
21517
|
${allowBuilds}
|
|
21443
21518
|
onlyBuiltDependencies:
|
|
21444
21519
|
${onlyBuilt}
|
|
21445
21520
|
`;
|
|
21446
21521
|
}
|
|
21522
|
+
function generateNpmrc(packageManager) {
|
|
21523
|
+
if (packageManager !== "pnpm") return null;
|
|
21524
|
+
return `# This project is a single package, not a monorepo. pnpm 9 treats the
|
|
21525
|
+
# pnpm-workspace.yaml shipped for its build allowlist as declaring a
|
|
21526
|
+
# workspace root, which makes \`pnpm add <pkg>\` demand a -w flag. There is no
|
|
21527
|
+
# other package here for that check to protect.
|
|
21528
|
+
${NPMRC_WORKSPACE_ROOT_KEY}=true
|
|
21529
|
+
`;
|
|
21530
|
+
}
|
|
21531
|
+
var NPMRC_WORKSPACE_ROOT_KEY = "ignore-workspace-root-check";
|
|
21532
|
+
async function writeScaffoldNpmrc(targetDir, packageManager) {
|
|
21533
|
+
const addition = generateNpmrc(packageManager);
|
|
21534
|
+
if (!addition) return;
|
|
21535
|
+
const npmrcPath = path14__default.default.join(targetDir, ".npmrc");
|
|
21536
|
+
const link = await import_fs_extra8.default.lstat(npmrcPath).catch(() => null);
|
|
21537
|
+
if (link?.isSymbolicLink()) return;
|
|
21538
|
+
if (link && link.nlink > 1) return;
|
|
21539
|
+
const existing = link ? await import_fs_extra8.default.readFile(npmrcPath, "utf-8") : "";
|
|
21540
|
+
const alreadyDeclared = new RegExp(
|
|
21541
|
+
`^\\s*${NPMRC_WORKSPACE_ROOT_KEY}\\s*=`,
|
|
21542
|
+
"m"
|
|
21543
|
+
).test(existing);
|
|
21544
|
+
if (alreadyDeclared) return;
|
|
21545
|
+
const separator = existing === "" || existing.endsWith("\n") ? "" : "\n";
|
|
21546
|
+
await import_fs_extra8.default.writeFile(npmrcPath, existing + separator + addition, "utf-8");
|
|
21547
|
+
}
|
|
21447
21548
|
async function copyTemplate(options) {
|
|
21448
21549
|
const {
|
|
21449
21550
|
projectName,
|
|
@@ -21454,6 +21555,7 @@ async function copyTemplate(options) {
|
|
|
21454
21555
|
useYalc = false,
|
|
21455
21556
|
approach,
|
|
21456
21557
|
templateSource,
|
|
21558
|
+
packageManager,
|
|
21457
21559
|
allowExistingTarget = false
|
|
21458
21560
|
} = options;
|
|
21459
21561
|
if (!allowExistingTarget && targetDir !== process.cwd() && await import_fs_extra8.default.pathExists(targetDir)) {
|
|
@@ -21472,7 +21574,13 @@ async function copyTemplate(options) {
|
|
|
21472
21574
|
typeDir = path14__default.default.join(templatesRoot, projectType);
|
|
21473
21575
|
}
|
|
21474
21576
|
if (projectType === "plugin") {
|
|
21475
|
-
await copyPluginTemplate({
|
|
21577
|
+
await copyPluginTemplate({
|
|
21578
|
+
projectName,
|
|
21579
|
+
typeDir,
|
|
21580
|
+
targetDir,
|
|
21581
|
+
useYalc,
|
|
21582
|
+
packageManager
|
|
21583
|
+
});
|
|
21476
21584
|
return;
|
|
21477
21585
|
}
|
|
21478
21586
|
if (!await import_fs_extra8.default.pathExists(baseDir)) {
|
|
@@ -21531,6 +21639,13 @@ async function copyTemplate(options) {
|
|
|
21531
21639
|
overwrite: false
|
|
21532
21640
|
});
|
|
21533
21641
|
}
|
|
21642
|
+
const templateScriptsDir = path14__default.default.join(typeDir, "scripts");
|
|
21643
|
+
if (await import_fs_extra8.default.pathExists(templateScriptsDir)) {
|
|
21644
|
+
await import_fs_extra8.default.copy(templateScriptsDir, path14__default.default.join(targetDir, "scripts"), {
|
|
21645
|
+
overwrite: false,
|
|
21646
|
+
filter: (src) => !SKIP_FILES.has(path14__default.default.basename(src))
|
|
21647
|
+
});
|
|
21648
|
+
}
|
|
21534
21649
|
const frontendPagePath = path14__default.default.join(
|
|
21535
21650
|
targetDir,
|
|
21536
21651
|
"src",
|
|
@@ -21546,7 +21661,9 @@ async function copyTemplate(options) {
|
|
|
21546
21661
|
projectName,
|
|
21547
21662
|
database,
|
|
21548
21663
|
useYalc,
|
|
21549
|
-
projectType
|
|
21664
|
+
projectType,
|
|
21665
|
+
[baseDir, typeDir],
|
|
21666
|
+
targetDir
|
|
21550
21667
|
);
|
|
21551
21668
|
await import_fs_extra8.default.writeFile(
|
|
21552
21669
|
path14__default.default.join(targetDir, "package.json"),
|
|
@@ -21558,6 +21675,8 @@ async function copyTemplate(options) {
|
|
|
21558
21675
|
generatePnpmWorkspaceYaml(),
|
|
21559
21676
|
"utf-8"
|
|
21560
21677
|
);
|
|
21678
|
+
await restoreIgnoreFile(targetDir);
|
|
21679
|
+
await writeScaffoldNpmrc(targetDir, packageManager);
|
|
21561
21680
|
if (database.type === "sqlite") {
|
|
21562
21681
|
await import_fs_extra8.default.ensureDir(path14__default.default.join(targetDir, "data"));
|
|
21563
21682
|
}
|
|
@@ -21573,7 +21692,7 @@ async function copyTemplate(options) {
|
|
|
21573
21692
|
await replacePlaceholders(targetDir, placeholders);
|
|
21574
21693
|
}
|
|
21575
21694
|
async function copyPluginTemplate(opts) {
|
|
21576
|
-
const { projectName, typeDir, targetDir, useYalc } = opts;
|
|
21695
|
+
const { projectName, typeDir, targetDir, useYalc, packageManager } = opts;
|
|
21577
21696
|
if (!await import_fs_extra8.default.pathExists(typeDir)) {
|
|
21578
21697
|
throw new Error(
|
|
21579
21698
|
`Plugin template not found at ${typeDir}. The package may be corrupted or the download failed.`
|
|
@@ -21602,6 +21721,8 @@ async function copyPluginTemplate(opts) {
|
|
|
21602
21721
|
generatePnpmWorkspaceYaml(),
|
|
21603
21722
|
"utf-8"
|
|
21604
21723
|
);
|
|
21724
|
+
await restoreIgnoreFile(targetDir);
|
|
21725
|
+
await writeScaffoldNpmrc(targetDir, packageManager);
|
|
21605
21726
|
const nextlyRange = await resolvePluginNextlyRange(useYalc);
|
|
21606
21727
|
await replacePlaceholders(
|
|
21607
21728
|
targetDir,
|
|
@@ -25201,6 +25322,7 @@ async function createNextly(options = {}) {
|
|
|
25201
25322
|
} else {
|
|
25202
25323
|
s3.start("Scaffolding project...");
|
|
25203
25324
|
}
|
|
25325
|
+
const scaffoldPackageManager = await detectPackageManager(targetDir);
|
|
25204
25326
|
await copyTemplate({
|
|
25205
25327
|
projectName,
|
|
25206
25328
|
projectType,
|
|
@@ -25210,6 +25332,7 @@ async function createNextly(options = {}) {
|
|
|
25210
25332
|
useYalc,
|
|
25211
25333
|
approach,
|
|
25212
25334
|
templateSource,
|
|
25335
|
+
packageManager: scaffoldPackageManager,
|
|
25213
25336
|
// Suppress copyTemplate's "directory already exists" guard when the
|
|
25214
25337
|
// installer has already negotiated the conflict with the user
|
|
25215
25338
|
// (either by emptying the dir or accepting an overlay). Without
|