create-nextly-app 0.0.2-alpha.73 → 0.0.2-alpha.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/{create-nextly-Q62KZJib.cjs → create-nextly-DdIL2e9E.cjs} +170 -77
- package/dist/{create-nextly-Q62KZJib.cjs.map → create-nextly-DdIL2e9E.cjs.map} +1 -1
- package/dist/{create-nextly-CuWn_ITx.mjs → create-nextly-N_COehCu.mjs} +170 -77
- package/dist/{create-nextly-CuWn_ITx.mjs.map → create-nextly-N_COehCu.mjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +5 -5
- package/skills/nextly-authentication/SKILL.md +1 -1
- package/skills/nextly-collections/SKILL.md +1 -1
- package/skills/nextly-deploy/SKILL.md +1 -1
- package/skills/nextly-install/SKILL.md +1 -1
- package/templates/base/src/app/admin/[[...params]]/layout.tsx +60 -8
- package/templates/base/src/app/layout.tsx +5 -0
- package/templates/base/src/nextly/cached-read.ts +52 -0
- package/templates/base/src/types/generated/plugin-admin-imports.generated.ts +2 -0
- package/templates/blank/src/app/layout.tsx +5 -0
- package/templates/blank/src/instrumentation.ts +4 -1
- package/templates/plugin/AGENTS.md.template +2 -2
- package/templates/plugin/dev/src/app/layout.tsx +6 -0
- package/templates/plugin/dev/src/instrumentation.ts +4 -1
- package/templates/plugin/dev/src/nextly/cached-read.ts +52 -0
- package/templates/plugin/dev/src/types/generated/plugin-admin-imports.generated.ts +2 -2
- package/templates/plugin/src/admin/index.ts +4 -14
- package/templates/plugin/dev/src/app/admin/[[...params]]/layout.tsx +0 -24
package/dist/cli.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_create_nextly = require("./create-nextly-
|
|
3
|
+
const require_create_nextly = require("./create-nextly-DdIL2e9E.cjs");
|
|
4
4
|
// ../../node_modules/.pnpm/commander@14.0.2/node_modules/commander/lib/error.js
|
|
5
5
|
var require_error = /* @__PURE__ */ require_create_nextly.__commonJSMin(((exports) => {
|
|
6
6
|
/**
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as getAvailableTemplateNames, c as init, d as __require, f as __toESM, i as validateTemplateName, l as shutdown, n as resolveProjectArg, o as packageVersion, r as validateProjectName, s as capture, t as createNextly, u as __commonJSMin } from "./create-nextly-
|
|
2
|
+
import { a as getAvailableTemplateNames, c as init, d as __require, f as __toESM, i as validateTemplateName, l as shutdown, n as resolveProjectArg, o as packageVersion, r as validateProjectName, s as capture, t as createNextly, u as __commonJSMin } from "./create-nextly-N_COehCu.mjs";
|
|
3
3
|
// ../../node_modules/.pnpm/commander@14.0.2/node_modules/commander/lib/error.js
|
|
4
4
|
var require_error = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
5
5
|
/**
|
|
@@ -42579,15 +42579,27 @@ const REQUIRE_IMPORT = "import { createRequire } from \"node:module\";";
|
|
|
42579
42579
|
const requireDeclaration = (createRequireName) => `// Resolves Nextly's cache handlers from this app's node_modules.
|
|
42580
42580
|
const require = ${createRequireName}(import.meta.url);`;
|
|
42581
42581
|
const REQUIRE_DECLARATION = requireDeclaration("createRequire");
|
|
42582
|
+
/** Where a new app's config takes the crawlers that wait for the whole head. */
|
|
42583
|
+
const HTML_LIMITED_BOTS_IMPORT = "import { nextlyHtmlLimitedBots } from \"nextly/next\";";
|
|
42584
|
+
/**
|
|
42585
|
+
* The crawlers answered with each page's whole head in the first HTML rather
|
|
42586
|
+
* than streamed it: Next.js's own list, the main Googlebot and the AI
|
|
42587
|
+
* crawlers (`nextlyHtmlLimitedBots`).
|
|
42588
|
+
*/
|
|
42589
|
+
const HTML_LIMITED_BOTS_LINE = ` // Search engines and AI crawlers read each page's whole head in the first
|
|
42590
|
+
// HTML, rather than metadata streamed in after it.
|
|
42591
|
+
htmlLimitedBots: nextlyHtmlLimitedBots,`;
|
|
42582
42592
|
/**
|
|
42583
42593
|
* Render a complete next.config.ts file for the selected database.
|
|
42584
42594
|
*/
|
|
42585
42595
|
function buildNextConfigTemplate(database) {
|
|
42586
42596
|
return `import type { NextConfig } from "next";
|
|
42597
|
+
${HTML_LIMITED_BOTS_IMPORT}
|
|
42587
42598
|
|
|
42588
42599
|
const nextConfig: NextConfig = {
|
|
42589
42600
|
${CACHE_COMPONENTS_ON}
|
|
42590
42601
|
serverExternalPackages: ${packageListLiteral(database)},
|
|
42602
|
+
${HTML_LIMITED_BOTS_LINE}
|
|
42591
42603
|
};
|
|
42592
42604
|
|
|
42593
42605
|
export default nextConfig;
|
|
@@ -42596,6 +42608,7 @@ export default nextConfig;
|
|
|
42596
42608
|
/** The same config as a JavaScript module, for an app without TypeScript. */
|
|
42597
42609
|
function buildNextConfigModule(database) {
|
|
42598
42610
|
return `${REQUIRE_IMPORT}
|
|
42611
|
+
${HTML_LIMITED_BOTS_IMPORT}
|
|
42599
42612
|
|
|
42600
42613
|
${REQUIRE_DECLARATION}
|
|
42601
42614
|
|
|
@@ -42603,6 +42616,7 @@ ${REQUIRE_DECLARATION}
|
|
|
42603
42616
|
const nextConfig = {
|
|
42604
42617
|
${CACHE_COMPONENTS_ON}
|
|
42605
42618
|
serverExternalPackages: ${packageListLiteral(database)},
|
|
42619
|
+
${HTML_LIMITED_BOTS_LINE}
|
|
42606
42620
|
};
|
|
42607
42621
|
|
|
42608
42622
|
export default nextConfig;
|
|
@@ -45986,41 +46000,56 @@ const SEARCH_INDEX_SCRIPT = path.default.join("scripts", "build-search-index.mjs
|
|
|
45986
46000
|
async function projectHasSearchIndexScript(targetDir) {
|
|
45987
46001
|
return import_lib$1.default.pathExists(path.default.join(targetDir, SEARCH_INDEX_SCRIPT));
|
|
45988
46002
|
}
|
|
45989
|
-
/**
|
|
45990
|
-
|
|
45991
|
-
* imports from a `@nextlyhq/plugin-*` package (the SDK aside) that a
|
|
45992
|
-
* `plugins: [...]` list in it names, however deep in an element. Read with
|
|
45993
|
-
* the parser the Next config step uses, so nested brackets, either quote and
|
|
45994
|
-
* default or aliased imports are read as the compiler reads them. First-party
|
|
45995
|
-
* plugins register under their package name, which is what
|
|
45996
|
-
* `nextly plugins install` takes. Throws for a config that does not parse,
|
|
45997
|
-
* since every template's must.
|
|
45998
|
-
*
|
|
45999
|
-
* Exported for the test that holds every template's config to its build.
|
|
46000
|
-
*/
|
|
46001
|
-
function configuredPlugins(configText, file = "nextly.config.ts") {
|
|
46002
|
-
let program;
|
|
46003
|
+
/** Parses a config, naming the file when it does not parse. */
|
|
46004
|
+
function parseConfigProgram(configText, file) {
|
|
46003
46005
|
try {
|
|
46004
|
-
|
|
46006
|
+
return (0, import_lib.parse)(configText, {
|
|
46005
46007
|
sourceType: "module",
|
|
46006
46008
|
plugins: ["typescript", "jsx"]
|
|
46007
46009
|
}).program;
|
|
46008
46010
|
} catch (error) {
|
|
46009
46011
|
throw new Error(`${file} cannot be parsed (${error.message}), so the plugins its build must install cannot be read.`);
|
|
46010
46012
|
}
|
|
46011
|
-
|
|
46013
|
+
}
|
|
46014
|
+
/** Each binding imported from a module `matches` accepts, to that module's name. */
|
|
46015
|
+
function bindingsImportedFrom(program, matches) {
|
|
46016
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
46012
46017
|
for (const statement of program.body) {
|
|
46013
46018
|
if (statement.type !== "ImportDeclaration") continue;
|
|
46014
|
-
|
|
46015
|
-
|
|
46016
|
-
for (const specifier of statement.specifiers) fromPackage.set(specifier.local.name, pkg);
|
|
46019
|
+
if (!matches(statement.source.value)) continue;
|
|
46020
|
+
for (const specifier of statement.specifiers) bindings.set(specifier.local.name, statement.source.value);
|
|
46017
46021
|
}
|
|
46018
|
-
|
|
46022
|
+
return bindings;
|
|
46023
|
+
}
|
|
46024
|
+
const isPluginPackage = (source) => source.startsWith("@nextlyhq/plugin-") && source !== "@nextlyhq/plugin-sdk";
|
|
46025
|
+
/** What a config's `plugins` lists hold: the packages, and whether a binding from its own source is among them. */
|
|
46026
|
+
function readPluginLists(configText, file) {
|
|
46027
|
+
const program = parseConfigProgram(configText, file);
|
|
46028
|
+
const fromPackage = bindingsImportedFrom(program, isPluginPackage);
|
|
46029
|
+
const packages = /* @__PURE__ */ new Set();
|
|
46019
46030
|
for (const name of identifiersInPluginLists(program, file)) {
|
|
46020
46031
|
const pkg = fromPackage.get(name);
|
|
46021
|
-
if (pkg !== void 0
|
|
46032
|
+
if (pkg !== void 0) packages.add(pkg);
|
|
46022
46033
|
}
|
|
46023
|
-
|
|
46034
|
+
const local = bindingsImportedFrom(program, (source) => source.startsWith("."));
|
|
46035
|
+
const ownPlugin = namesInPluginEntries(program, file).some((name) => local.has(name) && !fromPackage.has(name));
|
|
46036
|
+
return {
|
|
46037
|
+
packages: [...packages],
|
|
46038
|
+
ownPlugin
|
|
46039
|
+
};
|
|
46040
|
+
}
|
|
46041
|
+
/**
|
|
46042
|
+
* The `nextly plugins install` steps a project's build runs, read from its
|
|
46043
|
+
* config. A plugin package is installed by name, and the build says which. A
|
|
46044
|
+
* plugin the site wrote itself has no package name to give, and a production
|
|
46045
|
+
* boot refuses it like any other when nothing has installed it, so a config
|
|
46046
|
+
* that lists one installs with `--all`, which reads the names from the config.
|
|
46047
|
+
* Exported for the test that holds every template's config to its build.
|
|
46048
|
+
*/
|
|
46049
|
+
function pluginInstallSteps(configText, file = "nextly.config.ts") {
|
|
46050
|
+
const { packages, ownPlugin } = readPluginLists(configText, file);
|
|
46051
|
+
if (ownPlugin) return ["nextly plugins install --all"];
|
|
46052
|
+
return packages.map((pkg) => `nextly plugins install ${pkg}`);
|
|
46024
46053
|
}
|
|
46025
46054
|
/** Every identifier inside the value of each `plugins: [...]` property, in source order. */
|
|
46026
46055
|
function identifiersInPluginLists(program, file) {
|
|
@@ -46034,6 +46063,20 @@ function identifiersInPluginLists(program, file) {
|
|
|
46034
46063
|
return names;
|
|
46035
46064
|
}
|
|
46036
46065
|
/**
|
|
46066
|
+
* The binding each entry of a `plugins: [...]` list is, as written: `seo` for
|
|
46067
|
+
* `seo` or `seo({ ... })`. Narrower than {@link identifiersInPluginLists},
|
|
46068
|
+
* which also sees the identifiers inside an entry's options.
|
|
46069
|
+
*/
|
|
46070
|
+
function namesInPluginEntries(program, file) {
|
|
46071
|
+
const names = [];
|
|
46072
|
+
walkNodes(program, (node) => {
|
|
46073
|
+
if (!isPluginList(node, file) || node.value.type !== "ArrayExpression") return;
|
|
46074
|
+
for (const element of node.value.elements) if (element?.type === "Identifier") names.push(element.name);
|
|
46075
|
+
else if (element?.type === "CallExpression" && element.callee.type === "Identifier") names.push(element.callee.name);
|
|
46076
|
+
});
|
|
46077
|
+
return names;
|
|
46078
|
+
}
|
|
46079
|
+
/**
|
|
46037
46080
|
* A `plugins: [...]` property, by an identifier or a string key. A `plugins`
|
|
46038
46081
|
* property written any other way, such as a variable holding the list, a call
|
|
46039
46082
|
* or a spread inside it, is
|
|
@@ -46065,16 +46108,15 @@ function isNode(value) {
|
|
|
46065
46108
|
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
46066
46109
|
}
|
|
46067
46110
|
/**
|
|
46068
|
-
* The
|
|
46069
|
-
* finished project as {@link projectHasSearchIndexScript} is: a template
|
|
46070
|
-
* offers more than one config
|
|
46071
|
-
*
|
|
46072
|
-
* no project on disk to ask.
|
|
46111
|
+
* The plugin install steps the scaffolded PROJECT's build needs, read from
|
|
46112
|
+
* the finished project as {@link projectHasSearchIndexScript} is: a template
|
|
46113
|
+
* offers more than one config, so only the file the copy wrote can say. None
|
|
46114
|
+
* when there is no config, or no project on disk to ask.
|
|
46073
46115
|
*/
|
|
46074
|
-
async function
|
|
46116
|
+
async function projectPluginInstalls(targetDir) {
|
|
46075
46117
|
if (targetDir === void 0) return [];
|
|
46076
46118
|
const config = path.default.join(targetDir, "nextly.config.ts");
|
|
46077
|
-
return await import_lib$1.default.pathExists(config) ?
|
|
46119
|
+
return await import_lib$1.default.pathExists(config) ? pluginInstallSteps(await import_lib$1.default.readFile(config, "utf-8"), config) : [];
|
|
46078
46120
|
}
|
|
46079
46121
|
/**
|
|
46080
46122
|
* Every file under `root` that could carry an import specifier.
|
|
@@ -46667,7 +46709,7 @@ async function generatePackageJson(projectName, database, source = nextlySource(
|
|
|
46667
46709
|
esbuild: PINNED_VERSIONS.esbuild
|
|
46668
46710
|
};
|
|
46669
46711
|
const shipsSearchIndex = targetDir ? await projectHasSearchIndexScript(targetDir) : false;
|
|
46670
|
-
const
|
|
46712
|
+
const pluginInstalls = await projectPluginInstalls(targetDir);
|
|
46671
46713
|
if (shipsSearchIndex) devDependencies.pagefind = "^1.1.0";
|
|
46672
46714
|
const pkg = {
|
|
46673
46715
|
name: projectName,
|
|
@@ -46677,7 +46719,7 @@ async function generatePackageJson(projectName, database, source = nextlySource(
|
|
|
46677
46719
|
dev: "next dev --turbopack",
|
|
46678
46720
|
build: [
|
|
46679
46721
|
"nextly migrate",
|
|
46680
|
-
...
|
|
46722
|
+
...pluginInstalls,
|
|
46681
46723
|
"next build",
|
|
46682
46724
|
...shipsSearchIndex ? ["node scripts/build-search-index.mjs"] : []
|
|
46683
46725
|
].join(" && "),
|
|
@@ -47333,6 +47375,15 @@ const ADMIN_LAYOUT = {
|
|
|
47333
47375
|
path: "admin/[[...params]]/layout.tsx",
|
|
47334
47376
|
importsConfig: true
|
|
47335
47377
|
};
|
|
47378
|
+
/**
|
|
47379
|
+
* The admin component map's two generated files, under the app's source root,
|
|
47380
|
+
* as the base template commits them: the admin layout imports the list, and
|
|
47381
|
+
* the admin page imports the map that registers the components. Read with the
|
|
47382
|
+
* routes, so an app Nextly is added to starts from the template's own empty
|
|
47383
|
+
* map rather than a second one written out here, and `next dev` rewrites them
|
|
47384
|
+
* as plugins are added.
|
|
47385
|
+
*/
|
|
47386
|
+
const ADMIN_COMPONENT_MAP_FILES = ["types/generated/plugin-admin-components.generated.ts", "types/generated/plugin-admin-imports.generated.ts"];
|
|
47336
47387
|
/** Every file the existing-app path writes from the templates, read together. */
|
|
47337
47388
|
const ALL_ROUTES = [
|
|
47338
47389
|
...ROUTES,
|
|
@@ -47438,6 +47489,15 @@ async function readMediaRouteTemplates(templatesDir = resolveTemplatePath()) {
|
|
|
47438
47489
|
if (route.importsConfig && !CONFIG_IMPORT.test(text)) throw new Error(`The template's ${route.path} does not import the Nextly config, so no route that finds it can be written. Nothing was installed or written.`);
|
|
47439
47490
|
texts.set(route.path, text);
|
|
47440
47491
|
}
|
|
47492
|
+
for (const file of ADMIN_COMPONENT_MAP_FILES) {
|
|
47493
|
+
const relative = `base/src/${file}`;
|
|
47494
|
+
try {
|
|
47495
|
+
texts.set(file, await import_lib$1.default.readFile(path.default.join(templatesDir, relative), "utf-8"));
|
|
47496
|
+
} catch (error) {
|
|
47497
|
+
const code = error.code ?? "unreadable";
|
|
47498
|
+
throw new Error(`The templates at ${templatesDir} have no readable ${relative} (${code}), so Nextly's admin component map cannot be added. Nothing was installed or written; check the --local-template path if one was given.`);
|
|
47499
|
+
}
|
|
47500
|
+
}
|
|
47441
47501
|
return texts;
|
|
47442
47502
|
}
|
|
47443
47503
|
/**
|
|
@@ -47888,10 +47948,71 @@ function skipped(cwd, left, target, text, role, reason) {
|
|
|
47888
47948
|
function toPosix(p) {
|
|
47889
47949
|
return p.split(path.default.sep).join("/");
|
|
47890
47950
|
}
|
|
47951
|
+
// src/generators/types.ts
|
|
47952
|
+
/**
|
|
47953
|
+
* Where the generated types file goes, relative to the project root: under
|
|
47954
|
+
* src/ when the app keeps its code there, at the root when it does not. The
|
|
47955
|
+
* config names this path and the types step creates it, so both read it here.
|
|
47956
|
+
*/
|
|
47957
|
+
function typesOutputFile(projectInfo) {
|
|
47958
|
+
return `${projectInfo.srcDir ? "./src" : "."}/types/generated/nextly-types.ts`;
|
|
47959
|
+
}
|
|
47960
|
+
/**
|
|
47961
|
+
* The folder the generated files go in, relative to the project root, as
|
|
47962
|
+
* {@link typesOutputFile} names it: the admin layout and page import the
|
|
47963
|
+
* component map from here.
|
|
47964
|
+
*/
|
|
47965
|
+
function typesOutputFolder(projectInfo) {
|
|
47966
|
+
return path.default.posix.dirname(path.default.posix.normalize(typesOutputFile(projectInfo)));
|
|
47967
|
+
}
|
|
47968
|
+
/**
|
|
47969
|
+
* Create the types directory structure for generated TypeScript types.
|
|
47970
|
+
* This mirrors what `nextly init` does - creates the directory and a placeholder file.
|
|
47971
|
+
* The actual types are generated when running `next dev` (which boots Nextly
|
|
47972
|
+
* and emits types lazily) or `npx nextly generate:types`.
|
|
47973
|
+
*/
|
|
47974
|
+
async function generateTypesDirectory(cwd, projectInfo, templates) {
|
|
47975
|
+
const files = nothingYet();
|
|
47976
|
+
const typesFile = path.default.posix.normalize(typesOutputFile(projectInfo));
|
|
47977
|
+
const typesDir = typesOutputFolder(projectInfo);
|
|
47978
|
+
await writeNew(cwd, `${typesDir}/.gitkeep`, "", files, { why: "it is already there" });
|
|
47979
|
+
await writeNew(cwd, typesFile, `/**
|
|
47980
|
+
* Nextly Generated Types
|
|
47981
|
+
*
|
|
47982
|
+
* This file will be auto-generated when you run:
|
|
47983
|
+
* next dev (Nextly emits types on first boot)
|
|
47984
|
+
* npx nextly generate:types
|
|
47985
|
+
*
|
|
47986
|
+
* Do not edit this file manually - it will be overwritten.
|
|
47987
|
+
*/
|
|
47988
|
+
|
|
47989
|
+
// Types will be generated here after running next dev
|
|
47990
|
+
export {};
|
|
47991
|
+
`, files, { why: "it is already there; Nextly writes the types into it when they are generated" });
|
|
47992
|
+
for (const file of ADMIN_COMPONENT_MAP_FILES) {
|
|
47993
|
+
const text = templates.get(file);
|
|
47994
|
+
if (text === void 0) throw new Error(`The templates read for this app hold no ${file}, so Nextly's admin component map cannot be written.`);
|
|
47995
|
+
await writeNew(cwd, `${typesDir}/${path.default.posix.basename(file)}`, text, files, { why: "it is already there; `next dev` and `nextly generate:types` keep it current" });
|
|
47996
|
+
}
|
|
47997
|
+
return files;
|
|
47998
|
+
}
|
|
47891
47999
|
// src/generators/admin.ts
|
|
47892
|
-
|
|
48000
|
+
/**
|
|
48001
|
+
* The generated component map's two files, by the name a module imports them
|
|
48002
|
+
* as: the list the layout reads, and the map the page loads to register the
|
|
48003
|
+
* components.
|
|
48004
|
+
*/
|
|
48005
|
+
const COMPONENT_LIST = "plugin-admin-components.generated";
|
|
48006
|
+
const COMPONENT_MAP = "plugin-admin-imports.generated";
|
|
48007
|
+
/** How the file at `target` imports `name` from the app's generated types folder. */
|
|
48008
|
+
function generatedImport(cwd, target, projectInfo, name) {
|
|
48009
|
+
const relative = path.default.relative(path.default.dirname(target), path.default.join(cwd, typesOutputFolder(projectInfo), name)).split(path.default.sep).join("/");
|
|
48010
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
48011
|
+
}
|
|
48012
|
+
const adminPageTemplate = (componentMap) => `"use client";
|
|
47893
48013
|
|
|
47894
48014
|
import "@nextlyhq/admin/style.css";
|
|
48015
|
+
import "${componentMap}";
|
|
47895
48016
|
import { RootLayout, QueryProvider, ErrorBoundary } from "@nextlyhq/admin";
|
|
47896
48017
|
|
|
47897
48018
|
export default function AdminPage() {
|
|
@@ -47910,14 +48031,16 @@ export default function AdminPage() {
|
|
|
47910
48031
|
`;
|
|
47911
48032
|
/**
|
|
47912
48033
|
* The admin layout, as the base template holds it, with its config import
|
|
47913
|
-
* pointing at the project's `nextly.config
|
|
47914
|
-
*
|
|
47915
|
-
*
|
|
48034
|
+
* pointing at the project's `nextly.config`, and its component-list import at
|
|
48035
|
+
* the app's generated types folder, from where the layout is written. One
|
|
48036
|
+
* source with a new project's layout, so an app Nextly is added to gets the
|
|
48037
|
+
* same per-request admin.
|
|
47916
48038
|
*/
|
|
47917
|
-
function adminLayout(cwd, adminDir, templates) {
|
|
48039
|
+
function adminLayout(cwd, adminDir, projectInfo, templates) {
|
|
47918
48040
|
const text = templates.get(ADMIN_LAYOUT.path);
|
|
47919
48041
|
if (text === void 0) throw new Error(`The templates read for this app hold no ${ADMIN_LAYOUT.path}, so Nextly's admin layout cannot be written.`);
|
|
47920
|
-
|
|
48042
|
+
const target = path.default.join(cwd, adminDir, "layout.tsx");
|
|
48043
|
+
return withRelativeConfigImport(text, cwd, target, ADMIN_LAYOUT.path).replace(new RegExp(`"[^"]*/${COMPONENT_LIST.replaceAll(".", "\\.")}"`), `"${generatedImport(cwd, target, projectInfo, COMPONENT_LIST)}"`);
|
|
47921
48044
|
}
|
|
47922
48045
|
/**
|
|
47923
48046
|
* Generate the admin panel page and layout.
|
|
@@ -47926,56 +48049,23 @@ function adminLayout(cwd, adminDir, templates) {
|
|
|
47926
48049
|
async function generateAdminPage(cwd, projectInfo, templates) {
|
|
47927
48050
|
const files = nothingYet();
|
|
47928
48051
|
const adminDir = `${projectInfo.appDir}/admin/[[...params]]`;
|
|
47929
|
-
const layout = adminLayout(cwd, adminDir, templates);
|
|
48052
|
+
const layout = adminLayout(cwd, adminDir, projectInfo, templates);
|
|
48053
|
+
const page = adminPageTemplate(generatedImport(cwd, path.default.join(cwd, adminDir, "page.tsx"), projectInfo, COMPONENT_MAP));
|
|
47930
48054
|
const pages = await appPageExtensions(cwd);
|
|
47931
48055
|
if (pages.extensions !== "absent") {
|
|
47932
48056
|
const { configName, extensions } = pages;
|
|
47933
|
-
for (const [name, text] of [["page",
|
|
48057
|
+
for (const [name, text] of [["page", page], ["layout", layout]]) files.skipped.push(pageExtensionsSkip(`${adminDir}/${name}`, text, {
|
|
47934
48058
|
configName,
|
|
47935
48059
|
extensions
|
|
47936
48060
|
}, TSX_FILE));
|
|
47937
48061
|
return files;
|
|
47938
48062
|
}
|
|
47939
|
-
for (const [name, text] of [["page.tsx",
|
|
48063
|
+
for (const [name, text] of [["page.tsx", page], ["layout.tsx", layout]]) await writeNew(cwd, `${adminDir}/${name}`, text, files, {
|
|
47940
48064
|
why: `the app already has one; Nextly's admin needs its own ${name}, which is`,
|
|
47941
48065
|
toAdd: text
|
|
47942
48066
|
});
|
|
47943
48067
|
return files;
|
|
47944
48068
|
}
|
|
47945
|
-
// src/generators/types.ts
|
|
47946
|
-
/**
|
|
47947
|
-
* Where the generated types file goes, relative to the project root: under
|
|
47948
|
-
* src/ when the app keeps its code there, at the root when it does not. The
|
|
47949
|
-
* config names this path and the types step creates it, so both read it here.
|
|
47950
|
-
*/
|
|
47951
|
-
function typesOutputFile(projectInfo) {
|
|
47952
|
-
return `${projectInfo.srcDir ? "./src" : "."}/types/generated/nextly-types.ts`;
|
|
47953
|
-
}
|
|
47954
|
-
/**
|
|
47955
|
-
* Create the types directory structure for generated TypeScript types.
|
|
47956
|
-
* This mirrors what `nextly init` does - creates the directory and a placeholder file.
|
|
47957
|
-
* The actual types are generated when running `next dev` (which boots Nextly
|
|
47958
|
-
* and emits types lazily) or `npx nextly generate:types`.
|
|
47959
|
-
*/
|
|
47960
|
-
async function generateTypesDirectory(cwd, projectInfo) {
|
|
47961
|
-
const files = nothingYet();
|
|
47962
|
-
const typesFile = path.default.posix.normalize(typesOutputFile(projectInfo));
|
|
47963
|
-
await writeNew(cwd, `${path.default.posix.dirname(typesFile)}/.gitkeep`, "", files, { why: "it is already there" });
|
|
47964
|
-
await writeNew(cwd, typesFile, `/**
|
|
47965
|
-
* Nextly Generated Types
|
|
47966
|
-
*
|
|
47967
|
-
* This file will be auto-generated when you run:
|
|
47968
|
-
* next dev (Nextly emits types on first boot)
|
|
47969
|
-
* npx nextly generate:types
|
|
47970
|
-
*
|
|
47971
|
-
* Do not edit this file manually - it will be overwritten.
|
|
47972
|
-
*/
|
|
47973
|
-
|
|
47974
|
-
// Types will be generated here after running next dev
|
|
47975
|
-
export {};
|
|
47976
|
-
`, files, { why: "it is already there; Nextly writes the types into it when they are generated" });
|
|
47977
|
-
return files;
|
|
47978
|
-
}
|
|
47979
48069
|
// src/generators/config.ts
|
|
47980
48070
|
/**
|
|
47981
48071
|
* Base templates for project types that use inline config generation.
|
|
@@ -48058,9 +48148,12 @@ function startNextly(configImport) {
|
|
|
48058
48148
|
// Next.js writes its Cache Components setting into this file as it builds
|
|
48059
48149
|
// it. Nextly, loaded from node_modules, cannot read that for itself. With
|
|
48060
48150
|
// it off, Nextly warns at start; with it on, a cached read that finds no
|
|
48061
|
-
// "use cache" read function says so.
|
|
48151
|
+
// "use cache" read function says so. The same holds for the build's newest
|
|
48152
|
+
// migration, which withNextly sets: a production start compares it with
|
|
48153
|
+
// the database's schema version and warns when the database is behind.
|
|
48062
48154
|
await createRegister(config, {
|
|
48063
48155
|
cacheComponents: process.env.__NEXT_CACHE_COMPONENTS,
|
|
48156
|
+
buildSchemaVersion: process.env.NEXTLY_BUILD_SCHEMA_VERSION,
|
|
48064
48157
|
})();`;
|
|
48065
48158
|
}
|
|
48066
48159
|
/** The whole hook, as the blank template ships it. */
|
|
@@ -48208,7 +48301,7 @@ async function generateIntoExistingApp(cwd, projectType, projectInfo, database,
|
|
|
48208
48301
|
await generateMediaRoutes(cwd, projectInfo, templates),
|
|
48209
48302
|
await generateUploadsRoute(cwd, projectInfo, templates),
|
|
48210
48303
|
await generateInstrumentation(cwd, projectInfo),
|
|
48211
|
-
await generateTypesDirectory(cwd, projectInfo),
|
|
48304
|
+
await generateTypesDirectory(cwd, projectInfo, templates),
|
|
48212
48305
|
nextConfigFiles(await patchNextConfig(cwd, database)),
|
|
48213
48306
|
cacheComponentsFiles(await turnOnCacheComponents(cwd))
|
|
48214
48307
|
];
|
|
@@ -53074,4 +53167,4 @@ Object.defineProperty(exports, "validateTemplateName", {
|
|
|
53074
53167
|
}
|
|
53075
53168
|
});
|
|
53076
53169
|
|
|
53077
|
-
//# sourceMappingURL=create-nextly-
|
|
53170
|
+
//# sourceMappingURL=create-nextly-DdIL2e9E.cjs.map
|