betterstart-cli 0.0.42 → 0.0.44
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/README.md +1 -1
- package/dist/assets/adapters/next/{plugins/blog/plugin.ts → presets/blog/preset.ts} +2 -2
- package/dist/assets/adapters/next/{plugins/portfolio/plugin.ts → presets/portfolio/preset.ts} +2 -2
- package/dist/cli.js +325 -260
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- /package/dist/assets/adapters/next/{plugins → presets}/blog/schemas/menus.json +0 -0
- /package/dist/assets/adapters/next/{plugins → presets}/blog/schemas/posts.json +0 -0
- /package/dist/assets/adapters/next/{plugins → presets}/portfolio/schemas/portfolio.json +0 -0
package/dist/cli.js
CHANGED
|
@@ -70,9 +70,9 @@ function requireInitializedProject(command) {
|
|
|
70
70
|
import { Argument, Command } from "commander";
|
|
71
71
|
var CREATE_SCHEMA_KINDS = ["entity", "single", "form"];
|
|
72
72
|
function createAddCommand(runtime) {
|
|
73
|
-
return new Command("add").description("Install BetterStart
|
|
73
|
+
return new Command("add").description("Install BetterStart presets or integrations into an existing Admin").argument("<items...>", "Preset or integration IDs to install (e.g. blog, r2)").option("-y, --yes", "Skip interactive configuration prompts", false).option("--integration", "Install integration IDs instead of content preset IDs", false).option(
|
|
74
74
|
"--skip-migration",
|
|
75
|
-
"Skip running db:push after installing schema-backed
|
|
75
|
+
"Skip running db:push after installing schema-backed presets",
|
|
76
76
|
false
|
|
77
77
|
).option("--cwd <path>", "Project root path").action((items, options) => runtime.runAdd(items, options));
|
|
78
78
|
}
|
|
@@ -109,21 +109,21 @@ function createGenerateCommand(runtime) {
|
|
|
109
109
|
);
|
|
110
110
|
}
|
|
111
111
|
function createInitCommand(runtime) {
|
|
112
|
-
return new Command("init").description("Scaffold Admin into a new or existing Next.js app").argument("[name]", "Project name (creates new directory if fresh project)").option("--
|
|
112
|
+
return new Command("init").description("Scaffold Admin into a new or existing Next.js app").argument("[name]", "Project name (creates new directory if fresh project)").option("--presets <presets>", "Comma-separated content preset IDs (e.g. blog)").option("--integrations <integrations>", "Comma-separated integration IDs (e.g. r2,resend)").option("--namespace <name>", "Generated admin namespace (e.g. admin, dashboard)").option("-y, --yes", "Skip all prompts (accept defaults)").option("--skip-migration", "Skip running drizzle-kit push after scaffolding").option("--skip-admin-creation", "Skip prompting to create the initial admin user").option("--skip-dev-server-start", "Skip prompting to start the development server").option(
|
|
113
113
|
"--database-url <url>",
|
|
114
114
|
"PostgreSQL database connection string (postgres:// or postgresql://)"
|
|
115
115
|
).option("--no-vercel", "Disable the Vercel (Neon) provisioning flow (manual connection only)").option("--vercel-plan <id>", "Neon plan id passed to `vercel integration add neon`").option("--skip-deploy", "Skip the post-scaffold deploy to the linked Vercel project").option("--force", "Overwrite all existing Admin files (nuclear option)").action(
|
|
116
116
|
(name, options) => runtime.runInit(name, options)
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
|
-
function
|
|
120
|
-
return new Command("list-
|
|
119
|
+
function createListPresetsCommand(runtime) {
|
|
120
|
+
return new Command("list-presets").description("List available BetterStart presets").option("--cwd <path>", "Project root path").action((options) => runtime.runListPresets(options));
|
|
121
121
|
}
|
|
122
122
|
function createListIntegrationsCommand(runtime) {
|
|
123
123
|
return new Command("list-integrations").description("List available BetterStart integrations").option("--cwd <path>", "Project root path").action((options) => runtime.runListIntegrations(options));
|
|
124
124
|
}
|
|
125
125
|
function createRemoveCommand(runtime) {
|
|
126
|
-
return new Command("remove").description("Remove installed BetterStart
|
|
126
|
+
return new Command("remove").description("Remove installed BetterStart presets or integrations").argument("<items...>", "Preset or integration IDs to remove (e.g. blog r2)").option("-f, --force", "Skip confirmation prompt", false).option("--integration", "Remove integration IDs instead of content preset IDs", false).option("--cwd <path>", "Project root path").action((items, options) => runtime.runRemove(items, options));
|
|
127
127
|
}
|
|
128
128
|
function createRemoveSchemaCommand(runtime) {
|
|
129
129
|
return new Command("remove-schema").description("Remove generated files for a user-authored schema").argument("<schema>", "Schema name to remove (e.g. posts, categories, contact)").option("-f, --force", "Skip confirmation prompt", false).option("--cwd <path>", "Project root path").action(
|
|
@@ -191,8 +191,8 @@ export default defineConfig({
|
|
|
191
191
|
migrationsDir: ${quote(config.database.migrationsDir)},
|
|
192
192
|
},
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
installed: ${formatArray(config.
|
|
194
|
+
presets: {
|
|
195
|
+
installed: ${formatArray(config.presets.installed)},
|
|
196
196
|
},
|
|
197
197
|
|
|
198
198
|
integrations: {
|
|
@@ -442,7 +442,7 @@ function getDefaultConfig(srcDir, nextMajorVersion = 16) {
|
|
|
442
442
|
provider: "postgres",
|
|
443
443
|
migrationsDir: deriveMigrationsDir(namespace)
|
|
444
444
|
},
|
|
445
|
-
|
|
445
|
+
presets: {
|
|
446
446
|
installed: []
|
|
447
447
|
},
|
|
448
448
|
integrations: {
|
|
@@ -507,7 +507,7 @@ async function resolveConfig(cwd) {
|
|
|
507
507
|
provider: "postgres",
|
|
508
508
|
migrationsDir: loadedDatabase.migrationsDir
|
|
509
509
|
},
|
|
510
|
-
|
|
510
|
+
presets: loadedConfig.presets ?? defaultConfig.presets,
|
|
511
511
|
integrations: loadedConfig.integrations ?? defaultConfig.integrations,
|
|
512
512
|
email: loadedConfig.email ?? defaultConfig.email,
|
|
513
513
|
storage: loadedConfig.storage ?? defaultConfig.storage,
|
|
@@ -899,8 +899,8 @@ function formatUnknownIntegrationMessage(integrationIds) {
|
|
|
899
899
|
return `Unknown integration(s): ${integrationIds.join(", ")}. Available for next: ${Object.keys(integrationRegistry).join(", ")}`;
|
|
900
900
|
}
|
|
901
901
|
|
|
902
|
-
// adapters/next/
|
|
903
|
-
var
|
|
902
|
+
// adapters/next/presets/blog/preset.ts
|
|
903
|
+
var blogPreset = {
|
|
904
904
|
id: "blog",
|
|
905
905
|
title: "Blog",
|
|
906
906
|
description: "Posts content module",
|
|
@@ -916,8 +916,8 @@ var blogPlugin = {
|
|
|
916
916
|
configure: "none"
|
|
917
917
|
};
|
|
918
918
|
|
|
919
|
-
// adapters/next/
|
|
920
|
-
var
|
|
919
|
+
// adapters/next/presets/portfolio/preset.ts
|
|
920
|
+
var portfolioPreset = {
|
|
921
921
|
id: "portfolio",
|
|
922
922
|
title: "Portfolio",
|
|
923
923
|
description: "Portfolio content module",
|
|
@@ -933,26 +933,26 @@ var portfolioPlugin = {
|
|
|
933
933
|
configure: "none"
|
|
934
934
|
};
|
|
935
935
|
|
|
936
|
-
// adapters/next/
|
|
937
|
-
var
|
|
938
|
-
blog:
|
|
939
|
-
portfolio:
|
|
936
|
+
// adapters/next/preset-registry.ts
|
|
937
|
+
var presetRegistry = {
|
|
938
|
+
blog: blogPreset,
|
|
939
|
+
portfolio: portfolioPreset
|
|
940
940
|
};
|
|
941
|
-
function
|
|
942
|
-
return Object.values(
|
|
941
|
+
function listPresetDefinitions() {
|
|
942
|
+
return Object.values(presetRegistry);
|
|
943
943
|
}
|
|
944
|
-
function
|
|
945
|
-
const definition =
|
|
944
|
+
function getPresetDefinition(presetId) {
|
|
945
|
+
const definition = presetRegistry[presetId];
|
|
946
946
|
if (!definition) {
|
|
947
|
-
throw new Error(
|
|
947
|
+
throw new Error(formatUnknownPresetMessage([presetId]));
|
|
948
948
|
}
|
|
949
949
|
return definition;
|
|
950
950
|
}
|
|
951
|
-
function
|
|
952
|
-
return value in
|
|
951
|
+
function isPresetId(value) {
|
|
952
|
+
return value in presetRegistry;
|
|
953
953
|
}
|
|
954
|
-
function
|
|
955
|
-
return `Unknown
|
|
954
|
+
function formatUnknownPresetMessage(presetIds) {
|
|
955
|
+
return `Unknown preset(s): ${presetIds.join(", ")}. Available for next: ${Object.keys(presetRegistry).join(", ")}`;
|
|
956
956
|
}
|
|
957
957
|
|
|
958
958
|
// shared-assets/react-admin/dependencies.ts
|
|
@@ -1313,12 +1313,12 @@ function spawnAsync(cmd, args, cwd) {
|
|
|
1313
1313
|
function unique(values) {
|
|
1314
1314
|
return Array.from(new Set(values));
|
|
1315
1315
|
}
|
|
1316
|
-
function getDependencyPlan(
|
|
1317
|
-
const
|
|
1318
|
-
(
|
|
1316
|
+
function getDependencyPlan(presetIds, integrationIds, includeBiome) {
|
|
1317
|
+
const presetDependencies = presetIds.flatMap(
|
|
1318
|
+
(presetId) => getPresetDefinition(presetId).packageDependencies
|
|
1319
1319
|
);
|
|
1320
|
-
const
|
|
1321
|
-
(
|
|
1320
|
+
const presetDevDependencies = presetIds.flatMap(
|
|
1321
|
+
(presetId) => getPresetDefinition(presetId).devDependencies
|
|
1322
1322
|
);
|
|
1323
1323
|
const integrationDependencies = integrationIds.flatMap(
|
|
1324
1324
|
(integrationId) => getIntegrationDefinition(integrationId).packageDependencies
|
|
@@ -1327,10 +1327,10 @@ function getDependencyPlan(pluginIds, integrationIds, includeBiome) {
|
|
|
1327
1327
|
(integrationId) => getIntegrationDefinition(integrationId).devDependencies
|
|
1328
1328
|
);
|
|
1329
1329
|
return {
|
|
1330
|
-
dependencies: unique([...CORE_DEPS, ...
|
|
1330
|
+
dependencies: unique([...CORE_DEPS, ...presetDependencies, ...integrationDependencies]),
|
|
1331
1331
|
devDependencies: unique([
|
|
1332
1332
|
...DEV_DEPS,
|
|
1333
|
-
...
|
|
1333
|
+
...presetDevDependencies,
|
|
1334
1334
|
...integrationDevDependencies,
|
|
1335
1335
|
...includeBiome ? BIOME_DEV_DEPS : []
|
|
1336
1336
|
])
|
|
@@ -2916,7 +2916,7 @@ function readIntegrationTemplate(integrationId, relativePath) {
|
|
|
2916
2916
|
return fs12.readFileSync(path15.join(integrationTemplateRoot(integrationId), relativePath), "utf-8");
|
|
2917
2917
|
}
|
|
2918
2918
|
|
|
2919
|
-
//
|
|
2919
|
+
// preset-engine/ownership.ts
|
|
2920
2920
|
import fs13 from "fs";
|
|
2921
2921
|
import path16 from "path";
|
|
2922
2922
|
function ownershipPath(cwd) {
|
|
@@ -3499,16 +3499,16 @@ function getUnusedIntegrationDependencies(config, remainingIntegrations, removed
|
|
|
3499
3499
|
const remainingIntegrationDefinitions = remainingIntegrations.map(
|
|
3500
3500
|
(integrationId) => getIntegrationDefinition(integrationId)
|
|
3501
3501
|
);
|
|
3502
|
-
const
|
|
3503
|
-
(
|
|
3502
|
+
const remainingPresetDefinitions = config.presets.installed.map(
|
|
3503
|
+
(presetId) => getPresetDefinition(presetId)
|
|
3504
3504
|
);
|
|
3505
3505
|
const remainingDependencies = /* @__PURE__ */ new Set([
|
|
3506
3506
|
...remainingIntegrationDefinitions.flatMap((definition) => definition.packageDependencies),
|
|
3507
|
-
...
|
|
3507
|
+
...remainingPresetDefinitions.flatMap((definition) => definition.packageDependencies)
|
|
3508
3508
|
]);
|
|
3509
3509
|
const remainingDevDependencies = /* @__PURE__ */ new Set([
|
|
3510
3510
|
...remainingIntegrationDefinitions.flatMap((definition) => definition.devDependencies),
|
|
3511
|
-
...
|
|
3511
|
+
...remainingPresetDefinitions.flatMap((definition) => definition.devDependencies)
|
|
3512
3512
|
]);
|
|
3513
3513
|
const corePlan = getDependencyPlan([], [], false);
|
|
3514
3514
|
const removedDefinition = getIntegrationDefinition(removedIntegrationId);
|
|
@@ -3666,12 +3666,12 @@ async function installIntegrations({
|
|
|
3666
3666
|
ensureIntegrationDirectFileTargetsAvailable(cwd, config, definition);
|
|
3667
3667
|
const configureResult = await configureIntegration(definition, cwd, interactive);
|
|
3668
3668
|
const dependencyPlan = getDependencyPlan(
|
|
3669
|
-
config.
|
|
3669
|
+
config.presets.installed,
|
|
3670
3670
|
[...installedIntegrationIds, integrationId],
|
|
3671
3671
|
includeBiome
|
|
3672
3672
|
);
|
|
3673
3673
|
const currentPlan = getDependencyPlan(
|
|
3674
|
-
config.
|
|
3674
|
+
config.presets.installed,
|
|
3675
3675
|
installedIntegrationIds,
|
|
3676
3676
|
includeBiome
|
|
3677
3677
|
);
|
|
@@ -3829,7 +3829,7 @@ function listAvailableIntegrations() {
|
|
|
3829
3829
|
return listIntegrationDefinitions();
|
|
3830
3830
|
}
|
|
3831
3831
|
|
|
3832
|
-
// adapters/next/
|
|
3832
|
+
// adapters/next/preset-runtime.ts
|
|
3833
3833
|
import fs22 from "fs";
|
|
3834
3834
|
import path26 from "path";
|
|
3835
3835
|
|
|
@@ -17347,14 +17347,14 @@ function runSinglePipeline(schema, cwd, config, options = {}) {
|
|
|
17347
17347
|
};
|
|
17348
17348
|
}
|
|
17349
17349
|
|
|
17350
|
-
// adapters/next/
|
|
17350
|
+
// adapters/next/preset-template-reader.ts
|
|
17351
17351
|
import fs16 from "fs";
|
|
17352
17352
|
import path20 from "path";
|
|
17353
|
-
function
|
|
17354
|
-
return resolveCliAssetPath("adapters", "next", "
|
|
17353
|
+
function presetTemplateRoot(presetId) {
|
|
17354
|
+
return resolveCliAssetPath("adapters", "next", "presets", presetId);
|
|
17355
17355
|
}
|
|
17356
|
-
function
|
|
17357
|
-
return fs16.readFileSync(path20.join(
|
|
17356
|
+
function readPresetTemplate(presetId, relativePath) {
|
|
17357
|
+
return fs16.readFileSync(path20.join(presetTemplateRoot(presetId), relativePath), "utf-8");
|
|
17358
17358
|
}
|
|
17359
17359
|
|
|
17360
17360
|
// adapters/next/snapshots/apply.ts
|
|
@@ -18267,62 +18267,62 @@ async function applyGeneratedFiles({
|
|
|
18267
18267
|
return summary;
|
|
18268
18268
|
}
|
|
18269
18269
|
|
|
18270
|
-
//
|
|
18270
|
+
// preset-engine/manifests.ts
|
|
18271
18271
|
import fs21 from "fs";
|
|
18272
18272
|
import path25 from "path";
|
|
18273
|
-
function
|
|
18274
|
-
return path25.join(cwd, ".betterstart", "
|
|
18273
|
+
function presetsDir(cwd) {
|
|
18274
|
+
return path25.join(cwd, ".betterstart", "presets");
|
|
18275
18275
|
}
|
|
18276
|
-
function
|
|
18277
|
-
return path25.join(
|
|
18276
|
+
function presetManifestPath(cwd, presetId) {
|
|
18277
|
+
return path25.join(presetsDir(cwd), presetId, "manifest.json");
|
|
18278
18278
|
}
|
|
18279
|
-
function
|
|
18280
|
-
const filePath =
|
|
18279
|
+
function loadInstalledPresetManifest(cwd, presetId) {
|
|
18280
|
+
const filePath = presetManifestPath(cwd, presetId);
|
|
18281
18281
|
if (!fs21.existsSync(filePath)) {
|
|
18282
18282
|
return null;
|
|
18283
18283
|
}
|
|
18284
18284
|
return JSON.parse(fs21.readFileSync(filePath, "utf-8"));
|
|
18285
18285
|
}
|
|
18286
|
-
function
|
|
18287
|
-
const filePath =
|
|
18286
|
+
function saveInstalledPresetManifest(cwd, manifest) {
|
|
18287
|
+
const filePath = presetManifestPath(cwd, manifest.id);
|
|
18288
18288
|
fs21.mkdirSync(path25.dirname(filePath), { recursive: true });
|
|
18289
18289
|
fs21.writeFileSync(filePath, stringifyProjectJson(manifest), "utf-8");
|
|
18290
18290
|
}
|
|
18291
|
-
function
|
|
18292
|
-
fs21.rmSync(path25.dirname(
|
|
18291
|
+
function deleteInstalledPresetManifest(cwd, presetId) {
|
|
18292
|
+
fs21.rmSync(path25.dirname(presetManifestPath(cwd, presetId)), {
|
|
18293
18293
|
recursive: true,
|
|
18294
18294
|
force: true
|
|
18295
18295
|
});
|
|
18296
18296
|
}
|
|
18297
18297
|
|
|
18298
|
-
// adapters/next/
|
|
18298
|
+
// adapters/next/preset-runtime.ts
|
|
18299
18299
|
function unique3(values) {
|
|
18300
18300
|
return Array.from(new Set(values));
|
|
18301
18301
|
}
|
|
18302
|
-
function
|
|
18303
|
-
return unique3((config.
|
|
18302
|
+
function normalizeInstalledPresets(config) {
|
|
18303
|
+
return unique3((config.presets.installed ?? []).filter(isPresetId)).sort();
|
|
18304
18304
|
}
|
|
18305
|
-
function
|
|
18305
|
+
function resolvePresetInstallOrder(presetIds) {
|
|
18306
18306
|
const ordered = [];
|
|
18307
18307
|
const visiting = /* @__PURE__ */ new Set();
|
|
18308
18308
|
const visited = /* @__PURE__ */ new Set();
|
|
18309
|
-
function visit(
|
|
18310
|
-
if (visited.has(
|
|
18309
|
+
function visit(presetId) {
|
|
18310
|
+
if (visited.has(presetId)) {
|
|
18311
18311
|
return;
|
|
18312
18312
|
}
|
|
18313
|
-
if (visiting.has(
|
|
18314
|
-
throw new Error(`Circular
|
|
18313
|
+
if (visiting.has(presetId)) {
|
|
18314
|
+
throw new Error(`Circular preset dependency detected at "${presetId}".`);
|
|
18315
18315
|
}
|
|
18316
|
-
visiting.add(
|
|
18317
|
-
for (const dependency of
|
|
18316
|
+
visiting.add(presetId);
|
|
18317
|
+
for (const dependency of getPresetDefinition(presetId).dependencies) {
|
|
18318
18318
|
visit(dependency);
|
|
18319
18319
|
}
|
|
18320
|
-
visiting.delete(
|
|
18321
|
-
visited.add(
|
|
18322
|
-
ordered.push(
|
|
18320
|
+
visiting.delete(presetId);
|
|
18321
|
+
visited.add(presetId);
|
|
18322
|
+
ordered.push(presetId);
|
|
18323
18323
|
}
|
|
18324
|
-
for (const
|
|
18325
|
-
visit(
|
|
18324
|
+
for (const presetId of presetIds) {
|
|
18325
|
+
visit(presetId);
|
|
18326
18326
|
}
|
|
18327
18327
|
return ordered;
|
|
18328
18328
|
}
|
|
@@ -18381,14 +18381,14 @@ async function regenerateBarrels(cwd, config) {
|
|
|
18381
18381
|
interactive: false
|
|
18382
18382
|
});
|
|
18383
18383
|
}
|
|
18384
|
-
function
|
|
18384
|
+
function resolvePresetProjectPath(config, outputPath) {
|
|
18385
18385
|
const namespacedOutputPath = applyAdminNamespaceToPath(
|
|
18386
18386
|
outputPath,
|
|
18387
18387
|
config.frameworkConfig.next.namespace
|
|
18388
18388
|
);
|
|
18389
18389
|
return path26.posix.join(config.paths.admin.replace(/^\.\//, ""), namespacedOutputPath);
|
|
18390
18390
|
}
|
|
18391
|
-
function
|
|
18391
|
+
function namespacePresetContent(config, content) {
|
|
18392
18392
|
return applyAdminNamespaceToContent(content, config.frameworkConfig.next.namespace);
|
|
18393
18393
|
}
|
|
18394
18394
|
function flattenEnvKeys2(definition) {
|
|
@@ -18404,7 +18404,7 @@ function tryReadCoreManagedTemplate2(relativeOutputPath) {
|
|
|
18404
18404
|
return null;
|
|
18405
18405
|
}
|
|
18406
18406
|
}
|
|
18407
|
-
function
|
|
18407
|
+
function configurePreset(definition, cwd) {
|
|
18408
18408
|
const envResult = appendEnvVars(cwd, definition.envSections);
|
|
18409
18409
|
return {
|
|
18410
18410
|
configured: true,
|
|
@@ -18412,7 +18412,7 @@ function configurePlugin(definition, cwd) {
|
|
|
18412
18412
|
updatedEnvKeys: envResult.updated
|
|
18413
18413
|
};
|
|
18414
18414
|
}
|
|
18415
|
-
function
|
|
18415
|
+
function ensurePresetSchemaTargetsAvailable(cwd, config, definition) {
|
|
18416
18416
|
const schemasDir = getSchemasDir(cwd, config);
|
|
18417
18417
|
for (const schemaFile of definition.schemaFiles) {
|
|
18418
18418
|
const schemaName = schemaFile.replace(/\.json$/, "");
|
|
@@ -18421,21 +18421,21 @@ function ensurePluginSchemaTargetsAvailable(cwd, config, definition) {
|
|
|
18421
18421
|
continue;
|
|
18422
18422
|
}
|
|
18423
18423
|
const owner = getSchemaOwner(cwd, schemaName);
|
|
18424
|
-
if (owner && owner !== `
|
|
18424
|
+
if (owner && owner !== `preset:${definition.id}`) {
|
|
18425
18425
|
throw new Error(
|
|
18426
18426
|
`Schema "${schemaName}" is already owned by "${owner}". Remove or rename it before installing ${definition.id}.`
|
|
18427
18427
|
);
|
|
18428
18428
|
}
|
|
18429
18429
|
if (!owner) {
|
|
18430
18430
|
throw new Error(
|
|
18431
|
-
`Schema "${schemaName}" already exists and is not
|
|
18431
|
+
`Schema "${schemaName}" already exists and is not preset-owned. Remove or rename it before installing ${definition.id}.`
|
|
18432
18432
|
);
|
|
18433
18433
|
}
|
|
18434
18434
|
}
|
|
18435
18435
|
}
|
|
18436
|
-
function
|
|
18436
|
+
function ensurePresetDirectFileTargetsAvailable(cwd, config, definition) {
|
|
18437
18437
|
for (const file of definition.files) {
|
|
18438
|
-
const projectRelativePath =
|
|
18438
|
+
const projectRelativePath = resolvePresetProjectPath(config, file.outputPath);
|
|
18439
18439
|
const fullPath = path26.join(cwd, ...projectRelativePath.split("/"));
|
|
18440
18440
|
if (!fs22.existsSync(fullPath)) {
|
|
18441
18441
|
continue;
|
|
@@ -18447,14 +18447,14 @@ function ensurePluginDirectFileTargetsAvailable(cwd, config, definition) {
|
|
|
18447
18447
|
);
|
|
18448
18448
|
}
|
|
18449
18449
|
const existingContent = normalizeManagedFileContent2(fs22.readFileSync(fullPath, "utf-8"));
|
|
18450
|
-
const
|
|
18451
|
-
|
|
18450
|
+
const presetTemplate = normalizeManagedFileContent2(
|
|
18451
|
+
namespacePresetContent(config, readPresetTemplate(definition.id, file.templatePath))
|
|
18452
18452
|
);
|
|
18453
|
-
if (existingContent ===
|
|
18453
|
+
if (existingContent === presetTemplate) {
|
|
18454
18454
|
continue;
|
|
18455
18455
|
}
|
|
18456
18456
|
const coreTemplate = tryReadCoreManagedTemplate2(file.outputPath);
|
|
18457
|
-
if (coreTemplate && existingContent === normalizeManagedFileContent2(
|
|
18457
|
+
if (coreTemplate && existingContent === normalizeManagedFileContent2(namespacePresetContent(config, coreTemplate))) {
|
|
18458
18458
|
continue;
|
|
18459
18459
|
}
|
|
18460
18460
|
throw new Error(
|
|
@@ -18462,15 +18462,15 @@ function ensurePluginDirectFileTargetsAvailable(cwd, config, definition) {
|
|
|
18462
18462
|
);
|
|
18463
18463
|
}
|
|
18464
18464
|
}
|
|
18465
|
-
function
|
|
18465
|
+
function writePresetDirectFiles(cwd, config, definition) {
|
|
18466
18466
|
const writtenFiles = [];
|
|
18467
18467
|
for (const file of definition.files) {
|
|
18468
|
-
const projectRelativePath =
|
|
18468
|
+
const projectRelativePath = resolvePresetProjectPath(config, file.outputPath);
|
|
18469
18469
|
const fullPath = path26.join(cwd, ...projectRelativePath.split("/"));
|
|
18470
18470
|
fs22.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
18471
18471
|
fs22.writeFileSync(
|
|
18472
18472
|
fullPath,
|
|
18473
|
-
|
|
18473
|
+
namespacePresetContent(config, readPresetTemplate(definition.id, file.templatePath)),
|
|
18474
18474
|
"utf-8"
|
|
18475
18475
|
);
|
|
18476
18476
|
writtenFiles.push(projectRelativePath);
|
|
@@ -18493,7 +18493,7 @@ function cleanupEmptyDirs2(cwd, deletedPaths, config) {
|
|
|
18493
18493
|
toProjectAbsolutePath2(cwd, paths.pagesDir),
|
|
18494
18494
|
toProjectAbsolutePath2(cwd, paths.schemasDir),
|
|
18495
18495
|
path26.join(projectRoot, ".betterstart"),
|
|
18496
|
-
path26.join(projectRoot, ".betterstart", "
|
|
18496
|
+
path26.join(projectRoot, ".betterstart", "presets"),
|
|
18497
18497
|
path26.join(projectRoot, ".betterstart", "snapshots")
|
|
18498
18498
|
]);
|
|
18499
18499
|
for (const deletedPath of deletedPaths) {
|
|
@@ -18511,13 +18511,13 @@ function cleanupEmptyDirs2(cwd, deletedPaths, config) {
|
|
|
18511
18511
|
}
|
|
18512
18512
|
}
|
|
18513
18513
|
}
|
|
18514
|
-
function
|
|
18515
|
-
const projectRelativePath =
|
|
18514
|
+
function restoreOrDeletePresetFile(cwd, config, relativeOutputPath) {
|
|
18515
|
+
const projectRelativePath = resolvePresetProjectPath(config, relativeOutputPath);
|
|
18516
18516
|
const fullPath = toProjectAbsolutePath2(cwd, projectRelativePath);
|
|
18517
18517
|
try {
|
|
18518
18518
|
const coreTemplate = readTemplate(relativeOutputPath);
|
|
18519
18519
|
fs22.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
18520
|
-
fs22.writeFileSync(fullPath,
|
|
18520
|
+
fs22.writeFileSync(fullPath, namespacePresetContent(config, coreTemplate), "utf-8");
|
|
18521
18521
|
return null;
|
|
18522
18522
|
} catch {
|
|
18523
18523
|
const existed = fs22.existsSync(fullPath);
|
|
@@ -18525,7 +18525,7 @@ function restoreOrDeletePluginFile(cwd, config, relativeOutputPath) {
|
|
|
18525
18525
|
return existed ? projectRelativePath : null;
|
|
18526
18526
|
}
|
|
18527
18527
|
}
|
|
18528
|
-
function
|
|
18528
|
+
function writePresetSchemas(cwd, config, definition) {
|
|
18529
18529
|
const schemasDir = getSchemasDir(cwd, config);
|
|
18530
18530
|
const writtenSchemaNames = [];
|
|
18531
18531
|
for (const schemaFile of definition.schemaFiles) {
|
|
@@ -18533,7 +18533,7 @@ function writePluginSchemas(cwd, config, definition) {
|
|
|
18533
18533
|
fs22.mkdirSync(path26.dirname(outputPath), { recursive: true });
|
|
18534
18534
|
fs22.writeFileSync(
|
|
18535
18535
|
outputPath,
|
|
18536
|
-
|
|
18536
|
+
readPresetTemplate(definition.id, `schemas/${schemaFile}`),
|
|
18537
18537
|
"utf-8"
|
|
18538
18538
|
);
|
|
18539
18539
|
writtenSchemaNames.push(schemaFile.replace(/\.json$/, ""));
|
|
@@ -18546,7 +18546,7 @@ function removePath(cwd, filePath) {
|
|
|
18546
18546
|
fs22.rmSync(fullPath, { recursive: true, force: true });
|
|
18547
18547
|
return existed;
|
|
18548
18548
|
}
|
|
18549
|
-
function
|
|
18549
|
+
function removePresetSchemas(cwd, config, manifest) {
|
|
18550
18550
|
const paths = resolveProjectPaths(config);
|
|
18551
18551
|
const deletedPaths = [];
|
|
18552
18552
|
const manifestsBySchema = /* @__PURE__ */ new Map();
|
|
@@ -18561,9 +18561,9 @@ function removePluginSchemas(cwd, config, manifest) {
|
|
|
18561
18561
|
}
|
|
18562
18562
|
if (missingManifests.length > 0) {
|
|
18563
18563
|
throw new Error(
|
|
18564
|
-
`Cannot remove ${manifest.id}. Missing snapshot manifest${missingManifests.length === 1 ? "" : "s"} for
|
|
18564
|
+
`Cannot remove ${manifest.id}. Missing snapshot manifest${missingManifests.length === 1 ? "" : "s"} for preset-owned schema${missingManifests.length === 1 ? "" : "s"}: ${missingManifests.join(
|
|
18565
18565
|
", "
|
|
18566
|
-
)}. Re-run \`pnpm betterstart init --force\` to restore snapshot state before removing the
|
|
18566
|
+
)}. Re-run \`pnpm betterstart init --force\` to restore snapshot state before removing the preset.`
|
|
18567
18567
|
);
|
|
18568
18568
|
}
|
|
18569
18569
|
for (const schemaName of manifest.ownedSchemas) {
|
|
@@ -18646,14 +18646,14 @@ function findBlockingSchemaDependencies(cwd, config, ownedSchemas) {
|
|
|
18646
18646
|
);
|
|
18647
18647
|
if (relationshipTargets.length > 0) {
|
|
18648
18648
|
blockers.push(
|
|
18649
|
-
`${schemaName} references
|
|
18649
|
+
`${schemaName} references preset-owned schema(s): ${relationshipTargets.join(", ")}`
|
|
18650
18650
|
);
|
|
18651
18651
|
}
|
|
18652
18652
|
}
|
|
18653
18653
|
return blockers;
|
|
18654
18654
|
}
|
|
18655
|
-
function
|
|
18656
|
-
const remainingDefinitions =
|
|
18655
|
+
function getUnusedPresetDependencies(remainingPresets, removedPresetId, installedIntegrations) {
|
|
18656
|
+
const remainingDefinitions = remainingPresets.map((presetId) => getPresetDefinition(presetId));
|
|
18657
18657
|
const integrationDefinitions = installedIntegrations.map(
|
|
18658
18658
|
(integrationId) => getIntegrationDefinition(integrationId)
|
|
18659
18659
|
);
|
|
@@ -18666,7 +18666,7 @@ function getUnusedPluginDependencies(remainingPlugins, removedPluginId, installe
|
|
|
18666
18666
|
...integrationDefinitions.flatMap((definition) => definition.devDependencies)
|
|
18667
18667
|
]);
|
|
18668
18668
|
const corePlan = getDependencyPlan([], [], false);
|
|
18669
|
-
const removedDefinition =
|
|
18669
|
+
const removedDefinition = getPresetDefinition(removedPresetId);
|
|
18670
18670
|
return {
|
|
18671
18671
|
dependencies: removedDefinition.packageDependencies.filter(
|
|
18672
18672
|
(dependency) => !remainingDependencies.has(dependency) && !corePlan.dependencies.includes(dependency)
|
|
@@ -18676,39 +18676,39 @@ function getUnusedPluginDependencies(remainingPlugins, removedPluginId, installe
|
|
|
18676
18676
|
)
|
|
18677
18677
|
};
|
|
18678
18678
|
}
|
|
18679
|
-
function
|
|
18679
|
+
function parsePresetList(value) {
|
|
18680
18680
|
if (!value) {
|
|
18681
18681
|
return [];
|
|
18682
18682
|
}
|
|
18683
|
-
const
|
|
18684
|
-
const invalid =
|
|
18683
|
+
const presetIds = value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
18684
|
+
const invalid = presetIds.filter((presetId) => !isPresetId(presetId));
|
|
18685
18685
|
if (invalid.length > 0) {
|
|
18686
|
-
throw new Error(
|
|
18686
|
+
throw new Error(formatUnknownPresetMessage(invalid));
|
|
18687
18687
|
}
|
|
18688
|
-
return unique3(
|
|
18688
|
+
return unique3(presetIds);
|
|
18689
18689
|
}
|
|
18690
|
-
function
|
|
18691
|
-
return
|
|
18690
|
+
function getInstalledPresets(config) {
|
|
18691
|
+
return normalizeInstalledPresets(config);
|
|
18692
18692
|
}
|
|
18693
|
-
function
|
|
18694
|
-
for (const
|
|
18695
|
-
const manifest =
|
|
18693
|
+
function syncInstalledPresetManifests(cwd, config) {
|
|
18694
|
+
for (const presetId of normalizeInstalledPresets(config)) {
|
|
18695
|
+
const manifest = loadInstalledPresetManifest(cwd, presetId);
|
|
18696
18696
|
if (!manifest) {
|
|
18697
18697
|
continue;
|
|
18698
18698
|
}
|
|
18699
|
-
const definition =
|
|
18699
|
+
const definition = getPresetDefinition(presetId);
|
|
18700
18700
|
const nextManifest = {
|
|
18701
18701
|
...manifest,
|
|
18702
18702
|
version: definition.version,
|
|
18703
18703
|
kind: definition.kind,
|
|
18704
|
-
ownedFiles: definition.files.map((file) =>
|
|
18704
|
+
ownedFiles: definition.files.map((file) => resolvePresetProjectPath(config, file.outputPath)),
|
|
18705
18705
|
packageDependencies: definition.packageDependencies,
|
|
18706
18706
|
devDependencies: definition.devDependencies,
|
|
18707
18707
|
dependencies: definition.dependencies,
|
|
18708
18708
|
conflicts: definition.conflicts
|
|
18709
18709
|
};
|
|
18710
18710
|
if (JSON.stringify(nextManifest) !== JSON.stringify(manifest)) {
|
|
18711
|
-
|
|
18711
|
+
saveInstalledPresetManifest(cwd, nextManifest);
|
|
18712
18712
|
}
|
|
18713
18713
|
}
|
|
18714
18714
|
}
|
|
@@ -18725,35 +18725,35 @@ function ensureUserSchemaOwnership(cwd, schemaName) {
|
|
|
18725
18725
|
setSchemaOwner(cwd, schemaName, "user");
|
|
18726
18726
|
}
|
|
18727
18727
|
}
|
|
18728
|
-
async function
|
|
18728
|
+
async function installPresets({
|
|
18729
18729
|
cwd,
|
|
18730
18730
|
config,
|
|
18731
18731
|
pm,
|
|
18732
|
-
|
|
18732
|
+
presetIds,
|
|
18733
18733
|
includeBiome
|
|
18734
18734
|
}) {
|
|
18735
|
-
const
|
|
18736
|
-
const
|
|
18735
|
+
const orderedPresetIds = resolvePresetInstallOrder(presetIds);
|
|
18736
|
+
const installedPresetIds = normalizeInstalledPresets(config);
|
|
18737
18737
|
const skipped = [];
|
|
18738
18738
|
const installed2 = [];
|
|
18739
18739
|
const warnings = [];
|
|
18740
18740
|
ensureSnapshotGitFiles(cwd);
|
|
18741
|
-
for (const
|
|
18742
|
-
if (
|
|
18743
|
-
skipped.push(
|
|
18741
|
+
for (const presetId of orderedPresetIds) {
|
|
18742
|
+
if (installedPresetIds.includes(presetId)) {
|
|
18743
|
+
skipped.push(presetId);
|
|
18744
18744
|
continue;
|
|
18745
18745
|
}
|
|
18746
|
-
const definition =
|
|
18747
|
-
|
|
18748
|
-
|
|
18749
|
-
const configureResult =
|
|
18746
|
+
const definition = getPresetDefinition(presetId);
|
|
18747
|
+
ensurePresetSchemaTargetsAvailable(cwd, config, definition);
|
|
18748
|
+
ensurePresetDirectFileTargetsAvailable(cwd, config, definition);
|
|
18749
|
+
const configureResult = configurePreset(definition, cwd);
|
|
18750
18750
|
const dependencyPlan = getDependencyPlan(
|
|
18751
|
-
[...
|
|
18751
|
+
[...installedPresetIds, presetId],
|
|
18752
18752
|
config.integrations.installed,
|
|
18753
18753
|
includeBiome
|
|
18754
18754
|
);
|
|
18755
18755
|
const currentPlan = getDependencyPlan(
|
|
18756
|
-
|
|
18756
|
+
installedPresetIds,
|
|
18757
18757
|
config.integrations.installed,
|
|
18758
18758
|
includeBiome
|
|
18759
18759
|
);
|
|
@@ -18773,23 +18773,23 @@ async function installPlugins({
|
|
|
18773
18773
|
devDependencies: dependencyDiff.devDependencies
|
|
18774
18774
|
});
|
|
18775
18775
|
if (!result.success) {
|
|
18776
|
-
throw new Error(result.error ?? `Failed to install dependencies for ${
|
|
18776
|
+
throw new Error(result.error ?? `Failed to install dependencies for ${presetId}.`);
|
|
18777
18777
|
}
|
|
18778
18778
|
}
|
|
18779
|
-
const writtenFiles =
|
|
18780
|
-
const writtenSchemas =
|
|
18779
|
+
const writtenFiles = writePresetDirectFiles(cwd, config, definition);
|
|
18780
|
+
const writtenSchemas = writePresetSchemas(cwd, config, definition);
|
|
18781
18781
|
for (const schemaName of writtenSchemas) {
|
|
18782
18782
|
const loaded = loadSchema(getSchemasDir(cwd, config), schemaName);
|
|
18783
|
-
await applyGeneratedSchema(cwd, config, loaded,
|
|
18784
|
-
setSchemaOwner(cwd, schemaName, `
|
|
18783
|
+
await applyGeneratedSchema(cwd, config, loaded, presetId);
|
|
18784
|
+
setSchemaOwner(cwd, schemaName, `preset:${presetId}`);
|
|
18785
18785
|
}
|
|
18786
18786
|
if (writtenSchemas.length > 0) {
|
|
18787
18787
|
await regenerateBarrels(cwd, config);
|
|
18788
18788
|
}
|
|
18789
|
-
|
|
18790
|
-
config.
|
|
18789
|
+
installedPresetIds.push(presetId);
|
|
18790
|
+
config.presets.installed = unique3(installedPresetIds).sort();
|
|
18791
18791
|
const manifest = {
|
|
18792
|
-
id:
|
|
18792
|
+
id: presetId,
|
|
18793
18793
|
version: definition.version,
|
|
18794
18794
|
kind: definition.kind,
|
|
18795
18795
|
ownedSchemas: writtenSchemas,
|
|
@@ -18802,9 +18802,9 @@ async function installPlugins({
|
|
|
18802
18802
|
conflicts: definition.conflicts,
|
|
18803
18803
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
18804
18804
|
};
|
|
18805
|
-
|
|
18805
|
+
saveInstalledPresetManifest(cwd, manifest);
|
|
18806
18806
|
writeConfigFile(cwd, config);
|
|
18807
|
-
installed2.push(
|
|
18807
|
+
installed2.push(presetId);
|
|
18808
18808
|
}
|
|
18809
18809
|
return {
|
|
18810
18810
|
installed: installed2,
|
|
@@ -18813,58 +18813,58 @@ async function installPlugins({
|
|
|
18813
18813
|
config
|
|
18814
18814
|
};
|
|
18815
18815
|
}
|
|
18816
|
-
async function
|
|
18816
|
+
async function removePresets({
|
|
18817
18817
|
cwd,
|
|
18818
18818
|
config,
|
|
18819
18819
|
pm,
|
|
18820
|
-
|
|
18820
|
+
presetIds
|
|
18821
18821
|
}) {
|
|
18822
|
-
const
|
|
18822
|
+
const installedPresets = normalizeInstalledPresets(config);
|
|
18823
18823
|
const removed = [];
|
|
18824
18824
|
const warnings = [];
|
|
18825
|
-
for (const
|
|
18826
|
-
if (!
|
|
18827
|
-
warnings.push(`${
|
|
18825
|
+
for (const presetId of presetIds) {
|
|
18826
|
+
if (!installedPresets.includes(presetId)) {
|
|
18827
|
+
warnings.push(`${presetId} is not installed.`);
|
|
18828
18828
|
continue;
|
|
18829
18829
|
}
|
|
18830
|
-
const manifest =
|
|
18830
|
+
const manifest = loadInstalledPresetManifest(cwd, presetId);
|
|
18831
18831
|
if (!manifest) {
|
|
18832
|
-
throw new Error(`Missing manifest for installed
|
|
18832
|
+
throw new Error(`Missing manifest for installed preset "${presetId}".`);
|
|
18833
18833
|
}
|
|
18834
|
-
const dependents =
|
|
18835
|
-
if (
|
|
18834
|
+
const dependents = installedPresets.filter((installedPresetId) => {
|
|
18835
|
+
if (installedPresetId === presetId) {
|
|
18836
18836
|
return false;
|
|
18837
18837
|
}
|
|
18838
|
-
return
|
|
18838
|
+
return getPresetDefinition(installedPresetId).dependencies.includes(presetId);
|
|
18839
18839
|
});
|
|
18840
18840
|
if (dependents.length > 0) {
|
|
18841
18841
|
throw new Error(
|
|
18842
|
-
`Cannot remove ${
|
|
18842
|
+
`Cannot remove ${presetId}. The following presets depend on it: ${dependents.join(", ")}`
|
|
18843
18843
|
);
|
|
18844
18844
|
}
|
|
18845
18845
|
const blockers = findBlockingSchemaDependencies(cwd, config, manifest.ownedSchemas);
|
|
18846
18846
|
if (blockers.length > 0) {
|
|
18847
|
-
throw new Error(`Cannot remove ${
|
|
18847
|
+
throw new Error(`Cannot remove ${presetId}:
|
|
18848
18848
|
- ${blockers.join("\n- ")}`);
|
|
18849
18849
|
}
|
|
18850
|
-
const deletedPaths =
|
|
18850
|
+
const deletedPaths = removePresetSchemas(cwd, config, manifest);
|
|
18851
18851
|
for (const filePath of manifest.ownedFiles) {
|
|
18852
18852
|
const relativeOutputPath = filePath.replace(`${config.paths.admin.replace(/^\.\//, "")}/`, "");
|
|
18853
|
-
const deletedPath =
|
|
18853
|
+
const deletedPath = restoreOrDeletePresetFile(cwd, config, relativeOutputPath);
|
|
18854
18854
|
if (deletedPath) {
|
|
18855
18855
|
deletedPaths.push(deletedPath);
|
|
18856
18856
|
}
|
|
18857
18857
|
}
|
|
18858
|
-
|
|
18859
|
-
const
|
|
18860
|
-
(
|
|
18858
|
+
deleteInstalledPresetManifest(cwd, presetId);
|
|
18859
|
+
const nextInstalledPresets = installedPresets.filter(
|
|
18860
|
+
(installedPresetId) => installedPresetId !== presetId
|
|
18861
18861
|
);
|
|
18862
|
-
|
|
18863
|
-
config.
|
|
18864
|
-
const
|
|
18865
|
-
const dependencyDiff =
|
|
18866
|
-
|
|
18867
|
-
|
|
18862
|
+
installedPresets.splice(0, installedPresets.length, ...nextInstalledPresets);
|
|
18863
|
+
config.presets.installed = [...nextInstalledPresets].sort();
|
|
18864
|
+
const remainingPresets = normalizeInstalledPresets(config);
|
|
18865
|
+
const dependencyDiff = getUnusedPresetDependencies(
|
|
18866
|
+
remainingPresets,
|
|
18867
|
+
presetId,
|
|
18868
18868
|
config.integrations.installed
|
|
18869
18869
|
);
|
|
18870
18870
|
if (dependencyDiff.dependencies.length > 0 || dependencyDiff.devDependencies.length > 0) {
|
|
@@ -18875,12 +18875,12 @@ async function removePlugins({
|
|
|
18875
18875
|
devDependencies: dependencyDiff.devDependencies
|
|
18876
18876
|
});
|
|
18877
18877
|
if (!result.success) {
|
|
18878
|
-
warnings.push(result.error ?? `Failed to remove dependencies for ${
|
|
18878
|
+
warnings.push(result.error ?? `Failed to remove dependencies for ${presetId}.`);
|
|
18879
18879
|
}
|
|
18880
18880
|
}
|
|
18881
18881
|
const usedEnvKeys = new Set(
|
|
18882
|
-
|
|
18883
|
-
(
|
|
18882
|
+
remainingPresets.flatMap(
|
|
18883
|
+
(installedPresetId) => flattenEnvKeys2(getPresetDefinition(installedPresetId))
|
|
18884
18884
|
)
|
|
18885
18885
|
);
|
|
18886
18886
|
const removableEnvKeys = manifest.envKeys.filter((envKey) => !usedEnvKeys.has(envKey));
|
|
@@ -18892,7 +18892,7 @@ async function removePlugins({
|
|
|
18892
18892
|
}
|
|
18893
18893
|
cleanupEmptyDirs2(cwd, deletedPaths, config);
|
|
18894
18894
|
writeConfigFile(cwd, config);
|
|
18895
|
-
removed.push(
|
|
18895
|
+
removed.push(presetId);
|
|
18896
18896
|
}
|
|
18897
18897
|
return {
|
|
18898
18898
|
removed,
|
|
@@ -18900,8 +18900,8 @@ async function removePlugins({
|
|
|
18900
18900
|
config
|
|
18901
18901
|
};
|
|
18902
18902
|
}
|
|
18903
|
-
function
|
|
18904
|
-
return
|
|
18903
|
+
function listAvailablePresets() {
|
|
18904
|
+
return listPresetDefinitions();
|
|
18905
18905
|
}
|
|
18906
18906
|
|
|
18907
18907
|
// adapters/next/commands/add.ts
|
|
@@ -18917,7 +18917,7 @@ function printAddNextSteps(installKind, hasSchemaChanges, result, adminRoutePath
|
|
|
18917
18917
|
}
|
|
18918
18918
|
async function runAddCommand(items, options) {
|
|
18919
18919
|
const installIntegrationsMode = Boolean(options.integration);
|
|
18920
|
-
const
|
|
18920
|
+
const presetIds = items.filter(isPresetId);
|
|
18921
18921
|
const integrationIds = items.filter(isIntegrationId);
|
|
18922
18922
|
if (!installIntegrationsMode && integrationIds.length > 0) {
|
|
18923
18923
|
p4.log.error(
|
|
@@ -18925,14 +18925,14 @@ async function runAddCommand(items, options) {
|
|
|
18925
18925
|
);
|
|
18926
18926
|
process.exit(1);
|
|
18927
18927
|
}
|
|
18928
|
-
if (installIntegrationsMode &&
|
|
18929
|
-
p4.log.error(`
|
|
18928
|
+
if (installIntegrationsMode && presetIds.length > 0) {
|
|
18929
|
+
p4.log.error(`Preset IDs cannot be installed with --integration: ${presetIds.join(", ")}`);
|
|
18930
18930
|
process.exit(1);
|
|
18931
18931
|
}
|
|
18932
|
-
const invalidItems = installIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((
|
|
18932
|
+
const invalidItems = installIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
18933
18933
|
if (invalidItems.length > 0) {
|
|
18934
18934
|
p4.log.error(
|
|
18935
|
-
installIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) :
|
|
18935
|
+
installIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
18936
18936
|
);
|
|
18937
18937
|
process.exit(1);
|
|
18938
18938
|
}
|
|
@@ -18984,16 +18984,16 @@ async function runAddCommand(items, options) {
|
|
|
18984
18984
|
p4.outro(messages.join("\n"));
|
|
18985
18985
|
return;
|
|
18986
18986
|
}
|
|
18987
|
-
const
|
|
18988
|
-
if (
|
|
18989
|
-
p4.log.error(
|
|
18987
|
+
const invalidPresets = items.filter((presetId) => !isPresetId(presetId));
|
|
18988
|
+
if (invalidPresets.length > 0) {
|
|
18989
|
+
p4.log.error(formatUnknownPresetMessage(invalidPresets));
|
|
18990
18990
|
process.exit(1);
|
|
18991
18991
|
}
|
|
18992
|
-
const result = await
|
|
18992
|
+
const result = await installPresets({
|
|
18993
18993
|
cwd,
|
|
18994
18994
|
config,
|
|
18995
18995
|
pm,
|
|
18996
|
-
|
|
18996
|
+
presetIds,
|
|
18997
18997
|
interactive: !options.yes,
|
|
18998
18998
|
includeBiome: false
|
|
18999
18999
|
});
|
|
@@ -19006,7 +19006,7 @@ async function runAddCommand(items, options) {
|
|
|
19006
19006
|
p4.note(result.warnings.join("\n"), "Warnings");
|
|
19007
19007
|
}
|
|
19008
19008
|
const installedSchemaNames = result.installed.flatMap(
|
|
19009
|
-
(
|
|
19009
|
+
(presetId) => getPresetDefinition(presetId).schemaFiles.map((schemaFile) => schemaFile.replace(/\.json$/, ""))
|
|
19010
19010
|
);
|
|
19011
19011
|
const hasSchemaChanges = installedSchemaNames.length > 0;
|
|
19012
19012
|
const conflictPaths = scanConflictPaths(cwd);
|
|
@@ -19018,10 +19018,10 @@ async function runAddCommand(items, options) {
|
|
|
19018
19018
|
showNextSteps: false
|
|
19019
19019
|
});
|
|
19020
19020
|
if (conflictPaths.length === 0) {
|
|
19021
|
-
printAddNextSteps("
|
|
19021
|
+
printAddNextSteps("preset", hasSchemaChanges, postGenerateResult, adminRoutePath);
|
|
19022
19022
|
}
|
|
19023
19023
|
p4.outro(
|
|
19024
|
-
`Installed
|
|
19024
|
+
`Installed preset${result.installed.length === 1 ? "" : "s"}: ${result.installed.join(", ")}`
|
|
19025
19025
|
);
|
|
19026
19026
|
}
|
|
19027
19027
|
|
|
@@ -20129,7 +20129,7 @@ function validateIntegrationRequirements(loaded, config) {
|
|
|
20129
20129
|
}
|
|
20130
20130
|
function runPipeline(loaded, cwd, config, options) {
|
|
20131
20131
|
const owner = getSchemaOwner(cwd, loaded.schema.name);
|
|
20132
|
-
const outputNamespace = owner === "core" ? "core" : owner?.startsWith("
|
|
20132
|
+
const outputNamespace = owner === "core" ? "core" : owner?.startsWith("preset:") ? owner.replace(/^preset:/, "") : void 0;
|
|
20133
20133
|
if (loaded.type === "form") {
|
|
20134
20134
|
return runFormPipeline(loaded.schema, cwd, config, {
|
|
20135
20135
|
force: options.force,
|
|
@@ -21098,8 +21098,8 @@ function schemaNameFromLoaded(loaded) {
|
|
|
21098
21098
|
function resolveSchemaOwner(cwd, schemaName) {
|
|
21099
21099
|
return getSchemaOwner(cwd, schemaName) ?? (schemaName === "settings" ? "core" : "user");
|
|
21100
21100
|
}
|
|
21101
|
-
function
|
|
21102
|
-
return owner.startsWith("
|
|
21101
|
+
function presetIdFromOwner(owner) {
|
|
21102
|
+
return owner.startsWith("preset:") ? owner.replace(/^preset:/, "") : null;
|
|
21103
21103
|
}
|
|
21104
21104
|
async function promptConfirm3(message, initialValue = true) {
|
|
21105
21105
|
return promptConfirm2(ADD_FIELD_PROMPT_CONTEXT, message, initialValue);
|
|
@@ -21170,7 +21170,7 @@ async function createInteractiveInsertion2(loaded, schemasDir) {
|
|
|
21170
21170
|
return createInteractiveInsertion(ADD_FIELD_PROMPT_CONTEXT, loaded, schemasDir);
|
|
21171
21171
|
}
|
|
21172
21172
|
function printPreview(loaded, owner, firstTimeGeneration, insertion, options) {
|
|
21173
|
-
const
|
|
21173
|
+
const presetId = presetIdFromOwner(owner);
|
|
21174
21174
|
const lines = [
|
|
21175
21175
|
`schema: ${loaded.name} (${formatKind(loaded.kind)})`,
|
|
21176
21176
|
`display: ${getSchemaDisplayName(loaded)}`,
|
|
@@ -21180,9 +21180,9 @@ function printPreview(loaded, owner, firstTimeGeneration, insertion, options) {
|
|
|
21180
21180
|
`migration: ${options.skipMigration ? "skip db:push" : "run post-generate default"}`,
|
|
21181
21181
|
`merge conflicts: ${options.acceptGenerated || options.yes ? "accept generated output" : "write conflict markers"}`
|
|
21182
21182
|
];
|
|
21183
|
-
if (
|
|
21183
|
+
if (presetId) {
|
|
21184
21184
|
lines.push(
|
|
21185
|
-
`warning:
|
|
21185
|
+
`warning: preset-owned schema; uninstalling "${presetId}" can remove this schema and generated output`
|
|
21186
21186
|
);
|
|
21187
21187
|
}
|
|
21188
21188
|
if (firstTimeGeneration) {
|
|
@@ -21202,10 +21202,10 @@ ${stringifyProjectJson(insertion.field).trim()}`,
|
|
|
21202
21202
|
}
|
|
21203
21203
|
async function confirmWarningCases(owner, firstTimeGeneration, requiredPersistedField, nonInteractive, yes, extraWarnings = []) {
|
|
21204
21204
|
const warnings = [...extraWarnings];
|
|
21205
|
-
const
|
|
21206
|
-
if (
|
|
21205
|
+
const presetId = presetIdFromOwner(owner);
|
|
21206
|
+
if (presetId) {
|
|
21207
21207
|
warnings.push(
|
|
21208
|
-
`Schema is
|
|
21208
|
+
`Schema is preset-owned by "${presetId}". Removing that preset can remove the customized schema JSON, generated files, snapshots, and ownership entry.`
|
|
21209
21209
|
);
|
|
21210
21210
|
}
|
|
21211
21211
|
if (firstTimeGeneration) {
|
|
@@ -21240,8 +21240,8 @@ function collectRelationshipTargetWarnings(cwd, owner, field) {
|
|
|
21240
21240
|
collectRelationshipTargets(field, targetNames);
|
|
21241
21241
|
return Array.from(targetNames).map((targetName) => {
|
|
21242
21242
|
const targetOwner = getSchemaOwner(cwd, targetName);
|
|
21243
|
-
const
|
|
21244
|
-
return
|
|
21243
|
+
const presetId = targetOwner ? presetIdFromOwner(targetOwner) : null;
|
|
21244
|
+
return presetId ? `This user-owned schema references preset-owned schema "${targetName}". Removing preset "${presetId}" may affect that relationship.` : null;
|
|
21245
21245
|
}).filter((warning) => Boolean(warning));
|
|
21246
21246
|
}
|
|
21247
21247
|
function collectRelationshipTargets(field, targets) {
|
|
@@ -22032,7 +22032,7 @@ function openBrowser(url) {
|
|
|
22032
22032
|
}
|
|
22033
22033
|
}
|
|
22034
22034
|
|
|
22035
|
-
// adapters/next/init/prompts/
|
|
22035
|
+
// adapters/next/init/prompts/presets.ts
|
|
22036
22036
|
import { styleText } from "util";
|
|
22037
22037
|
import * as p12 from "@clack/prompts";
|
|
22038
22038
|
|
|
@@ -22183,13 +22183,13 @@ function scaffoldEnv(cwd, options) {
|
|
|
22183
22183
|
return appendEnvVars(cwd, sections, overwrite);
|
|
22184
22184
|
}
|
|
22185
22185
|
|
|
22186
|
-
// adapters/next/init/prompts/
|
|
22186
|
+
// adapters/next/init/prompts/presets.ts
|
|
22187
22187
|
function maskBlobToken(token) {
|
|
22188
22188
|
const match = /^(vercel_blob_rw_[A-Za-z0-9]+)_/.exec(token);
|
|
22189
22189
|
if (match) return `${match[1]}_***`;
|
|
22190
22190
|
return `${token.slice(0, 8)}***`;
|
|
22191
22191
|
}
|
|
22192
|
-
async function
|
|
22192
|
+
async function promptPresets(cwd, options = {}) {
|
|
22193
22193
|
const sections = [];
|
|
22194
22194
|
const overwriteKeys = /* @__PURE__ */ new Set();
|
|
22195
22195
|
const mergeIntegrationConfig = (collected) => {
|
|
@@ -22261,7 +22261,7 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
22261
22261
|
} else {
|
|
22262
22262
|
storageStep.confirm();
|
|
22263
22263
|
}
|
|
22264
|
-
const
|
|
22264
|
+
const selectedPresets = await p12.multiselect({
|
|
22265
22265
|
message: "Select presets",
|
|
22266
22266
|
options: [
|
|
22267
22267
|
{
|
|
@@ -22273,7 +22273,7 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
22273
22273
|
required: false,
|
|
22274
22274
|
initialValues: ["blog"]
|
|
22275
22275
|
});
|
|
22276
|
-
if (p12.isCancel(
|
|
22276
|
+
if (p12.isCancel(selectedPresets)) {
|
|
22277
22277
|
p12.cancel("Setup cancelled.");
|
|
22278
22278
|
process.exit(0);
|
|
22279
22279
|
}
|
|
@@ -22291,7 +22291,7 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
22291
22291
|
integrations.push("vercel-blob");
|
|
22292
22292
|
}
|
|
22293
22293
|
return {
|
|
22294
|
-
|
|
22294
|
+
presets: selectedPresets,
|
|
22295
22295
|
integrations,
|
|
22296
22296
|
storage,
|
|
22297
22297
|
integrationConfig: { sections, overwriteKeys }
|
|
@@ -24889,6 +24889,8 @@ import * as p16 from "@clack/prompts";
|
|
|
24889
24889
|
import pc5 from "picocolors";
|
|
24890
24890
|
var PROVISION_TIMEOUT_MS2 = 18e4;
|
|
24891
24891
|
var INTERACTIVE_PROVISION_TIMEOUT_MS2 = 6e5;
|
|
24892
|
+
var RESOURCE_CONNECT_TIMEOUT_MS = 6e4;
|
|
24893
|
+
var NEON_FREE_PLAN_ID = "free_v3";
|
|
24892
24894
|
async function provisionNeonInteractive(runner, cwd, options) {
|
|
24893
24895
|
const quietSpinner = spinner2();
|
|
24894
24896
|
quietSpinner.start("Creating your Neon database");
|
|
@@ -24953,12 +24955,54 @@ function readNeonProvisionInfo(stdout) {
|
|
|
24953
24955
|
const info = {};
|
|
24954
24956
|
if (meta.dashboardUrl) info.dashboardUrl = meta.dashboardUrl;
|
|
24955
24957
|
if (meta.ssoUrl?.resource) info.resourceUrl = meta.ssoUrl.resource;
|
|
24958
|
+
if (meta.resource?.name) info.resourceName = meta.resource.name;
|
|
24959
|
+
const connectWarning = (meta.warnings ?? []).some((warning) => /failed to connect/i.test(warning));
|
|
24960
|
+
if (meta.envPulled === false || connectWarning) info.connectedToProject = false;
|
|
24961
|
+
else if (meta.envPulled === true) info.connectedToProject = true;
|
|
24956
24962
|
return info;
|
|
24957
24963
|
}
|
|
24964
|
+
async function replaceNeonProjectConnection(runner, cwd, resourceName, env) {
|
|
24965
|
+
const list = await runVercel(runner, ["integration", "list", "--format", "json"], {
|
|
24966
|
+
cwd,
|
|
24967
|
+
mode: "capture",
|
|
24968
|
+
timeoutMs: RESOURCE_CONNECT_TIMEOUT_MS,
|
|
24969
|
+
env
|
|
24970
|
+
});
|
|
24971
|
+
if (list.success) {
|
|
24972
|
+
const payload = parseVercelJson(list.stdout);
|
|
24973
|
+
for (const resource of payload?.resources ?? []) {
|
|
24974
|
+
if (!resource.name || resource.name === resourceName) continue;
|
|
24975
|
+
if (resource.product && !/neon/i.test(resource.product)) continue;
|
|
24976
|
+
await runVercel(runner, ["integration-resource", "disconnect", resource.name, "--yes"], {
|
|
24977
|
+
cwd,
|
|
24978
|
+
mode: "capture",
|
|
24979
|
+
timeoutMs: RESOURCE_CONNECT_TIMEOUT_MS,
|
|
24980
|
+
env
|
|
24981
|
+
});
|
|
24982
|
+
}
|
|
24983
|
+
}
|
|
24984
|
+
const connect = await runVercel(
|
|
24985
|
+
runner,
|
|
24986
|
+
["integration-resource", "connect", resourceName, "--yes"],
|
|
24987
|
+
{
|
|
24988
|
+
cwd,
|
|
24989
|
+
mode: "capture",
|
|
24990
|
+
timeoutMs: RESOURCE_CONNECT_TIMEOUT_MS,
|
|
24991
|
+
env
|
|
24992
|
+
}
|
|
24993
|
+
);
|
|
24994
|
+
return connect.success;
|
|
24995
|
+
}
|
|
24958
24996
|
function neonAddArgs(options) {
|
|
24959
|
-
|
|
24960
|
-
|
|
24961
|
-
|
|
24997
|
+
return [
|
|
24998
|
+
"integration",
|
|
24999
|
+
"add",
|
|
25000
|
+
"neon",
|
|
25001
|
+
"--format",
|
|
25002
|
+
"json",
|
|
25003
|
+
"--plan",
|
|
25004
|
+
options.plan ?? NEON_FREE_PLAN_ID
|
|
25005
|
+
];
|
|
24962
25006
|
}
|
|
24963
25007
|
function connectedNeonAddArgs(options) {
|
|
24964
25008
|
const addArgs = ["integration", "add", "neon"];
|
|
@@ -24980,14 +25024,28 @@ async function runVercelNeonFlow(options) {
|
|
|
24980
25024
|
p17.log.warn(authFailureMessage(auth.reason));
|
|
24981
25025
|
return { ok: false };
|
|
24982
25026
|
}
|
|
25027
|
+
const linkPreExisted = Boolean(readLinkedProjectId(options.cwd));
|
|
24983
25028
|
const linkLinePrinted = await ensureLinkedProject(runner, options.cwd, options.projectName, env);
|
|
25029
|
+
const preExistingDbUrl = linkPreExisted ? await pullPreExistingDbUrl(runner, options.cwd, env) : void 0;
|
|
24984
25030
|
const neon = await provisionNeonForMode(runner, options);
|
|
24985
25031
|
if (neon.failure) {
|
|
24986
25032
|
p17.log.warn(neonFailureMessage(neon.failure));
|
|
24987
25033
|
if (neon.detail) p17.log.message(pc6.dim(neon.detail));
|
|
24988
25034
|
return { ok: false };
|
|
24989
25035
|
}
|
|
24990
|
-
|
|
25036
|
+
if (neon.connectedToProject === false && neon.resourceName) {
|
|
25037
|
+
const connectSpinner = spinner2();
|
|
25038
|
+
connectSpinner.start("Connecting the database to your Vercel project");
|
|
25039
|
+
await replaceNeonProjectConnection(runner, options.cwd, neon.resourceName, env);
|
|
25040
|
+
connectSpinner.clear();
|
|
25041
|
+
}
|
|
25042
|
+
let databaseUrl = await pullNeonDatabaseUrl(runner, options.cwd, env);
|
|
25043
|
+
if (databaseUrl && databaseUrl === preExistingDbUrl) {
|
|
25044
|
+
databaseUrl = void 0;
|
|
25045
|
+
p17.log.warn(
|
|
25046
|
+
"The linked Vercel project still returns its previous DATABASE_URL \u2014 the new database could not be connected."
|
|
25047
|
+
);
|
|
25048
|
+
}
|
|
24991
25049
|
const dismissSignedInNote = databaseUrl && auth.dismissNote && !neon.usedTerminalFallback ? () => auth.dismissNote?.({ linesBelow: linkLinePrinted ? 1 : 0 }) : void 0;
|
|
24992
25050
|
return {
|
|
24993
25051
|
ok: true,
|
|
@@ -25083,7 +25141,7 @@ async function runVercelDeployFlow(options) {
|
|
|
25083
25141
|
);
|
|
25084
25142
|
}
|
|
25085
25143
|
const deploySpinner = spinner2();
|
|
25086
|
-
deploySpinner.start("Deploying to Vercel
|
|
25144
|
+
deploySpinner.start("Deploying to Vercel, This may take a moment");
|
|
25087
25145
|
let deploy;
|
|
25088
25146
|
try {
|
|
25089
25147
|
deploy = await deployVercelProject(runner, options.cwd, env);
|
|
@@ -25121,6 +25179,13 @@ async function ensureLinkedProject(runner, cwd, projectName, env) {
|
|
|
25121
25179
|
);
|
|
25122
25180
|
return true;
|
|
25123
25181
|
}
|
|
25182
|
+
async function pullPreExistingDbUrl(runner, cwd, env) {
|
|
25183
|
+
const snapshotSpinner = spinner2();
|
|
25184
|
+
snapshotSpinner.start("Checking the linked Vercel project");
|
|
25185
|
+
const url = await pullVercelEnvValue(runner, cwd, readDbUrlFromDotenv, env);
|
|
25186
|
+
snapshotSpinner.clear();
|
|
25187
|
+
return url;
|
|
25188
|
+
}
|
|
25124
25189
|
async function pullNeonDatabaseUrl(runner, cwd, env) {
|
|
25125
25190
|
const neonSpinner = spinner2();
|
|
25126
25191
|
neonSpinner.start("Retrieving DATABASE_URL from Vercel");
|
|
@@ -25822,9 +25887,9 @@ async function runInitCommand(name, options) {
|
|
|
25822
25887
|
databaseStep.confirm();
|
|
25823
25888
|
}
|
|
25824
25889
|
}
|
|
25825
|
-
const
|
|
25826
|
-
if (options.
|
|
25827
|
-
return
|
|
25890
|
+
const selectedPresets = (() => {
|
|
25891
|
+
if (options.presets) {
|
|
25892
|
+
return parsePresetList(options.presets);
|
|
25828
25893
|
}
|
|
25829
25894
|
return [];
|
|
25830
25895
|
})();
|
|
@@ -25838,15 +25903,15 @@ async function runInitCommand(name, options) {
|
|
|
25838
25903
|
sections: [],
|
|
25839
25904
|
overwriteKeys: /* @__PURE__ */ new Set()
|
|
25840
25905
|
};
|
|
25841
|
-
let
|
|
25906
|
+
let presetSelection;
|
|
25842
25907
|
const vercelBlobAllowed = options.vercel !== false;
|
|
25843
|
-
if (
|
|
25844
|
-
|
|
25845
|
-
|
|
25908
|
+
if (selectedPresets.length > 0 || selectedIntegrations.length > 0) {
|
|
25909
|
+
presetSelection = {
|
|
25910
|
+
presets: selectedPresets,
|
|
25846
25911
|
integrations: selectedIntegrations,
|
|
25847
25912
|
storage: selectedIntegrations.includes("vercel-blob") ? "vercel-blob" : selectedIntegrations.includes("r2") ? "r2" : "local"
|
|
25848
25913
|
};
|
|
25849
|
-
if (
|
|
25914
|
+
if (presetSelection.storage === "vercel-blob" && !readEnvVar(cwd, "BLOB_READ_WRITE_TOKEN")?.trim() && vercelBlobAllowed && (!options.yes || process.env.VERCEL_TOKEN)) {
|
|
25850
25915
|
const flow = await runVercelBlobFlow({
|
|
25851
25916
|
cwd,
|
|
25852
25917
|
projectName,
|
|
@@ -25871,15 +25936,15 @@ async function runInitCommand(name, options) {
|
|
|
25871
25936
|
}
|
|
25872
25937
|
}
|
|
25873
25938
|
} else if (options.yes) {
|
|
25874
|
-
|
|
25939
|
+
presetSelection = { presets: [], integrations: [], storage: "local" };
|
|
25875
25940
|
} else {
|
|
25876
25941
|
dismissVercelSignedInNote?.();
|
|
25877
|
-
const promptResult = await
|
|
25942
|
+
const promptResult = await promptPresets(cwd, {
|
|
25878
25943
|
provisionVercelBlob: vercelBlobAllowed ? () => runVercelBlobFlow({ cwd, projectName, interactive: true, env: process.env }) : void 0
|
|
25879
25944
|
});
|
|
25880
25945
|
collectedIntegrationConfig = promptResult.integrationConfig;
|
|
25881
|
-
|
|
25882
|
-
|
|
25946
|
+
presetSelection = {
|
|
25947
|
+
presets: promptResult.presets,
|
|
25883
25948
|
integrations: promptResult.integrations,
|
|
25884
25949
|
storage: promptResult.storage
|
|
25885
25950
|
};
|
|
@@ -25897,7 +25962,7 @@ async function runInitCommand(name, options) {
|
|
|
25897
25962
|
scaffoldBase({
|
|
25898
25963
|
cwd,
|
|
25899
25964
|
config,
|
|
25900
|
-
includeEmailTemplatesDir:
|
|
25965
|
+
includeEmailTemplatesDir: presetSelection.integrations.some(isEmailProviderIntegration)
|
|
25901
25966
|
});
|
|
25902
25967
|
s.message("TypeScript aliases");
|
|
25903
25968
|
scaffoldTsconfig(cwd, config);
|
|
@@ -25962,7 +26027,7 @@ async function runInitCommand(name, options) {
|
|
|
25962
26027
|
}
|
|
25963
26028
|
const coreDependencyPlan = getDependencyPlan([], [], project2.linter.type === "none");
|
|
25964
26029
|
const cliDependencyPlan = getCliDependencySyncPlan(cwd);
|
|
25965
|
-
s.start("Installing dependencies
|
|
26030
|
+
s.start("Installing dependencies, This may take a moment");
|
|
25966
26031
|
const depsResult = await installDependenciesAsync({
|
|
25967
26032
|
cwd,
|
|
25968
26033
|
pm,
|
|
@@ -25996,29 +26061,29 @@ async function runInitCommand(name, options) {
|
|
|
25996
26061
|
const coreSchemasResult = scaffoldCoreSchemas({ cwd, config });
|
|
25997
26062
|
s.stop("");
|
|
25998
26063
|
process.stdout.write("\x1B[2A\x1B[J");
|
|
25999
|
-
const
|
|
26000
|
-
s.start(`Installing
|
|
26001
|
-
return
|
|
26064
|
+
const presetInstallResult = presetSelection.presets.length > 0 ? (() => {
|
|
26065
|
+
s.start(`Installing presets: ${presetSelection.presets.join(", ")}`);
|
|
26066
|
+
return installPresets({
|
|
26002
26067
|
cwd,
|
|
26003
26068
|
config,
|
|
26004
26069
|
pm,
|
|
26005
|
-
|
|
26070
|
+
presetIds: presetSelection.presets,
|
|
26006
26071
|
interactive: !options.yes,
|
|
26007
26072
|
includeBiome: project2.linter.type === "none"
|
|
26008
26073
|
});
|
|
26009
26074
|
})() : Promise.resolve({ installed: [], skipped: [], warnings: [], config });
|
|
26010
|
-
const
|
|
26011
|
-
if (
|
|
26075
|
+
const resolvedPresetInstallResult = await presetInstallResult;
|
|
26076
|
+
if (presetSelection.presets.length > 0) {
|
|
26012
26077
|
s.stop("");
|
|
26013
26078
|
process.stdout.write("\x1B[2A\x1B[J");
|
|
26014
26079
|
}
|
|
26015
|
-
const integrationInstallResult =
|
|
26016
|
-
s.start(`Installing integrations: ${
|
|
26080
|
+
const integrationInstallResult = presetSelection.integrations.length > 0 ? (() => {
|
|
26081
|
+
s.start(`Installing integrations: ${presetSelection.integrations.join(", ")}`);
|
|
26017
26082
|
return installIntegrations({
|
|
26018
26083
|
cwd,
|
|
26019
|
-
config:
|
|
26084
|
+
config: resolvedPresetInstallResult.config,
|
|
26020
26085
|
pm,
|
|
26021
|
-
integrationIds:
|
|
26086
|
+
integrationIds: presetSelection.integrations,
|
|
26022
26087
|
// Secrets were already collected up front and persisted/written to
|
|
26023
26088
|
// .env.local, so the install runs without prompting (rule: no
|
|
26024
26089
|
// mid-scaffold input).
|
|
@@ -26029,10 +26094,10 @@ async function runInitCommand(name, options) {
|
|
|
26029
26094
|
installed: [],
|
|
26030
26095
|
skipped: [],
|
|
26031
26096
|
warnings: [],
|
|
26032
|
-
config:
|
|
26097
|
+
config: resolvedPresetInstallResult.config
|
|
26033
26098
|
});
|
|
26034
26099
|
const resolvedIntegrationInstallResult = await integrationInstallResult;
|
|
26035
|
-
if (
|
|
26100
|
+
if (presetSelection.integrations.length > 0) {
|
|
26036
26101
|
s.stop("");
|
|
26037
26102
|
process.stdout.write("\x1B[2A\x1B[J");
|
|
26038
26103
|
}
|
|
@@ -26041,7 +26106,7 @@ async function runInitCommand(name, options) {
|
|
|
26041
26106
|
for (const err of coreSchemasResult.errors) {
|
|
26042
26107
|
p18.log.warn(`Core schemas: ${err}`);
|
|
26043
26108
|
}
|
|
26044
|
-
for (const warning of
|
|
26109
|
+
for (const warning of resolvedPresetInstallResult.warnings) {
|
|
26045
26110
|
p18.log.warn(warning);
|
|
26046
26111
|
}
|
|
26047
26112
|
for (const warning of resolvedIntegrationInstallResult.warnings) {
|
|
@@ -26804,19 +26869,19 @@ async function runListIntegrationsCommand(options) {
|
|
|
26804
26869
|
);
|
|
26805
26870
|
}
|
|
26806
26871
|
|
|
26807
|
-
// adapters/next/commands/list-
|
|
26872
|
+
// adapters/next/commands/list-presets.ts
|
|
26808
26873
|
import path52 from "path";
|
|
26809
26874
|
import * as p20 from "@clack/prompts";
|
|
26810
|
-
async function
|
|
26875
|
+
async function runListPresetsCommand(options) {
|
|
26811
26876
|
const cwd = options.cwd ? path52.resolve(options.cwd) : process.cwd();
|
|
26812
26877
|
const config = await resolveConfig(cwd);
|
|
26813
|
-
const
|
|
26814
|
-
const lines =
|
|
26815
|
-
const status =
|
|
26816
|
-
return `${
|
|
26878
|
+
const installedPresets = new Set(config.presets.installed);
|
|
26879
|
+
const lines = listAvailablePresets().map((preset) => {
|
|
26880
|
+
const status = installedPresets.has(preset.id) ? "installed" : "available";
|
|
26881
|
+
return `${preset.id.padEnd(10)} ${status.padEnd(10)} ${preset.kind.padEnd(12)} ${preset.description}`;
|
|
26817
26882
|
});
|
|
26818
|
-
p20.note(lines.join("\n"), "BetterStart
|
|
26819
|
-
p20.outro(`${
|
|
26883
|
+
p20.note(lines.join("\n"), "BetterStart presets");
|
|
26884
|
+
p20.outro(`${installedPresets.size} installed, ${lines.length - installedPresets.size} available`);
|
|
26820
26885
|
}
|
|
26821
26886
|
|
|
26822
26887
|
// adapters/next/commands/remove.ts
|
|
@@ -26828,7 +26893,7 @@ async function runRemoveCommand(items, options) {
|
|
|
26828
26893
|
p21.log.error("The core Admin cannot be removed.");
|
|
26829
26894
|
process.exit(1);
|
|
26830
26895
|
}
|
|
26831
|
-
const
|
|
26896
|
+
const presetIds = items.filter(isPresetId);
|
|
26832
26897
|
const integrationIds = items.filter(isIntegrationId);
|
|
26833
26898
|
if (!removeIntegrationsMode && integrationIds.length > 0) {
|
|
26834
26899
|
p21.log.error(
|
|
@@ -26836,14 +26901,14 @@ async function runRemoveCommand(items, options) {
|
|
|
26836
26901
|
);
|
|
26837
26902
|
process.exit(1);
|
|
26838
26903
|
}
|
|
26839
|
-
if (removeIntegrationsMode &&
|
|
26840
|
-
p21.log.error(`
|
|
26904
|
+
if (removeIntegrationsMode && presetIds.length > 0) {
|
|
26905
|
+
p21.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
|
|
26841
26906
|
process.exit(1);
|
|
26842
26907
|
}
|
|
26843
|
-
const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((
|
|
26908
|
+
const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
26844
26909
|
if (invalidItems.length > 0) {
|
|
26845
26910
|
p21.log.error(
|
|
26846
|
-
removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) :
|
|
26911
|
+
removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
26847
26912
|
);
|
|
26848
26913
|
process.exit(1);
|
|
26849
26914
|
}
|
|
@@ -26852,11 +26917,11 @@ async function runRemoveCommand(items, options) {
|
|
|
26852
26917
|
const pm = detectPackageManager(cwd);
|
|
26853
26918
|
if (!options.force) {
|
|
26854
26919
|
const confirmed = await p21.confirm({
|
|
26855
|
-
message: `Remove ${removeIntegrationsMode ? "integration" : "
|
|
26920
|
+
message: `Remove ${removeIntegrationsMode ? "integration" : "preset"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
|
|
26856
26921
|
initialValue: false
|
|
26857
26922
|
});
|
|
26858
26923
|
if (p21.isCancel(confirmed) || !confirmed) {
|
|
26859
|
-
p21.cancel(`${removeIntegrationsMode ? "Integration" : "
|
|
26924
|
+
p21.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
|
|
26860
26925
|
process.exit(0);
|
|
26861
26926
|
}
|
|
26862
26927
|
}
|
|
@@ -26880,21 +26945,21 @@ async function runRemoveCommand(items, options) {
|
|
|
26880
26945
|
);
|
|
26881
26946
|
return;
|
|
26882
26947
|
}
|
|
26883
|
-
const result = await
|
|
26948
|
+
const result = await removePresets({
|
|
26884
26949
|
cwd,
|
|
26885
26950
|
config,
|
|
26886
26951
|
pm,
|
|
26887
|
-
|
|
26952
|
+
presetIds
|
|
26888
26953
|
});
|
|
26889
26954
|
writeConfigFile(cwd, result.config);
|
|
26890
26955
|
if (result.removed.length === 0) {
|
|
26891
|
-
p21.outro("No
|
|
26956
|
+
p21.outro("No presets were removed.");
|
|
26892
26957
|
return;
|
|
26893
26958
|
}
|
|
26894
26959
|
if (result.warnings.length > 0) {
|
|
26895
26960
|
p21.note(result.warnings.join("\n"), "Warnings");
|
|
26896
26961
|
}
|
|
26897
|
-
p21.outro(`Removed
|
|
26962
|
+
p21.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
|
|
26898
26963
|
}
|
|
26899
26964
|
|
|
26900
26965
|
// adapters/next/commands/remove-schema.ts
|
|
@@ -26963,8 +27028,8 @@ async function runRemoveSchemaCommand(schemaName, options) {
|
|
|
26963
27028
|
);
|
|
26964
27029
|
process.exit(1);
|
|
26965
27030
|
}
|
|
26966
|
-
if (owner.startsWith("
|
|
26967
|
-
console.error(` "${schemaName}" is owned by ${owner}. Remove the owning
|
|
27031
|
+
if (owner.startsWith("preset:")) {
|
|
27032
|
+
console.error(` "${schemaName}" is owned by ${owner}. Remove the owning preset instead.`);
|
|
26968
27033
|
process.exit(1);
|
|
26969
27034
|
}
|
|
26970
27035
|
const cwd = options.cwd ? path54.resolve(options.cwd) : process.cwd();
|
|
@@ -27646,8 +27711,8 @@ function copyNamespacedDirectory(srcDir, destDir, namespace) {
|
|
|
27646
27711
|
writeNamespacedFile(srcPath, destPath, namespace);
|
|
27647
27712
|
}
|
|
27648
27713
|
}
|
|
27649
|
-
function
|
|
27650
|
-
return config.
|
|
27714
|
+
function hasPreset(config, presetId) {
|
|
27715
|
+
return config.presets.installed.includes(presetId);
|
|
27651
27716
|
}
|
|
27652
27717
|
function hasIntegration(config, integrationId) {
|
|
27653
27718
|
return config.integrations.installed.includes(integrationId);
|
|
@@ -29224,7 +29289,7 @@ function getAllComponentNamesForConfig(config) {
|
|
|
29224
29289
|
const staticUi = getStaticUiComponents();
|
|
29225
29290
|
const staticCustom = getStaticCustomComponents();
|
|
29226
29291
|
const templateKeys = Object.entries(TEMPLATE_REGISTRY).filter(
|
|
29227
|
-
([, entry]) => (!entry.
|
|
29292
|
+
([, entry]) => (!entry.requiredPreset || hasPreset(config, entry.requiredPreset)) && (!entry.requiredIntegration || hasIntegration(config, entry.requiredIntegration))
|
|
29228
29293
|
).map(([name]) => name);
|
|
29229
29294
|
return [.../* @__PURE__ */ new Set([...staticUi, ...staticCustom, ...templateKeys, "tiptap"])].sort();
|
|
29230
29295
|
}
|
|
@@ -29313,8 +29378,8 @@ async function runUpdateCommand(components, options) {
|
|
|
29313
29378
|
if (updatedTemplateNames.has(name)) {
|
|
29314
29379
|
return false;
|
|
29315
29380
|
}
|
|
29316
|
-
if (entry.
|
|
29317
|
-
clack2.log.warning(`${name} requires the ${entry.
|
|
29381
|
+
if (entry.requiredPreset && !hasPreset(config, entry.requiredPreset)) {
|
|
29382
|
+
clack2.log.warning(`${name} requires the ${entry.requiredPreset} preset and was skipped.`);
|
|
29318
29383
|
skipped++;
|
|
29319
29384
|
return false;
|
|
29320
29385
|
}
|
|
@@ -29466,7 +29531,7 @@ async function runUpdateCommand(components, options) {
|
|
|
29466
29531
|
clack2.log.warning(`Unknown component: ${name}`);
|
|
29467
29532
|
skipped++;
|
|
29468
29533
|
}
|
|
29469
|
-
|
|
29534
|
+
syncInstalledPresetManifests(cwd, config);
|
|
29470
29535
|
syncInstalledIntegrationManifests(cwd, config);
|
|
29471
29536
|
const projectPackageJson = readProjectPackageJson2(cwd);
|
|
29472
29537
|
const missingPackageDependencies = Array.from(requiredPackageDependencies).filter(
|
|
@@ -29661,7 +29726,7 @@ async function runUpdateDepsCommand(options) {
|
|
|
29661
29726
|
clack3.log.info(`Package manager: ${pm}`);
|
|
29662
29727
|
const config = await resolveConfig(cwd);
|
|
29663
29728
|
const dependencyPlan = getDependencyPlan(
|
|
29664
|
-
|
|
29729
|
+
getInstalledPresets(config),
|
|
29665
29730
|
getInstalledIntegrations(config),
|
|
29666
29731
|
false
|
|
29667
29732
|
);
|
|
@@ -29720,7 +29785,7 @@ var nextCommandRuntime = {
|
|
|
29720
29785
|
runGenerate: runGenerateCommand,
|
|
29721
29786
|
runInit: runInitCommand,
|
|
29722
29787
|
runListIntegrations: runListIntegrationsCommand,
|
|
29723
|
-
|
|
29788
|
+
runListPresets: runListPresetsCommand,
|
|
29724
29789
|
runRemove: runRemoveCommand,
|
|
29725
29790
|
runRemoveSchema: runRemoveSchemaCommand,
|
|
29726
29791
|
runSeed: runSeedCommand,
|
|
@@ -29736,7 +29801,7 @@ var { version } = JSON.parse(
|
|
|
29736
29801
|
readFileSync(new URL("../package.json", import.meta.url), "utf-8")
|
|
29737
29802
|
);
|
|
29738
29803
|
var program = new Command2();
|
|
29739
|
-
program.name("betterstart").description("Scaffold a
|
|
29804
|
+
program.name("betterstart").description("Scaffold a preset and integration based Admin into any Next.js 16 application").version(version);
|
|
29740
29805
|
program.hook("preAction", (_command, actionCommand) => {
|
|
29741
29806
|
requireInitializedProject(actionCommand);
|
|
29742
29807
|
});
|
|
@@ -29745,7 +29810,7 @@ program.addCommand(createAddFieldCommand(nextCommandRuntime));
|
|
|
29745
29810
|
program.addCommand(createCreateCommand(nextCommandRuntime));
|
|
29746
29811
|
program.addCommand(createInitCommand(nextCommandRuntime));
|
|
29747
29812
|
program.addCommand(createListIntegrationsCommand(nextCommandRuntime));
|
|
29748
|
-
program.addCommand(
|
|
29813
|
+
program.addCommand(createListPresetsCommand(nextCommandRuntime));
|
|
29749
29814
|
program.addCommand(createGenerateCommand(nextCommandRuntime));
|
|
29750
29815
|
program.addCommand(createRemoveCommand(nextCommandRuntime));
|
|
29751
29816
|
program.addCommand(createRemoveSchemaCommand(nextCommandRuntime));
|