betterstart-cli 0.0.92 → 0.0.93
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/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx +146 -0
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-columns.tsx +31 -0
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-page-content.tsx +39 -90
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-table.tsx +87 -0
- package/dist/cli.js +1165 -1076
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/edit-form-notifications-dialog.tsx +0 -128
package/dist/cli.js
CHANGED
|
@@ -52,6 +52,9 @@ async function loadConfigFile(configPath) {
|
|
|
52
52
|
function isInteractiveSession() {
|
|
53
53
|
return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
|
|
54
54
|
}
|
|
55
|
+
function isInteractiveTerminalSession() {
|
|
56
|
+
return isInteractiveSession() && Boolean(process.stdout.isTTY);
|
|
57
|
+
}
|
|
55
58
|
|
|
56
59
|
// core-engine/commands/runtime.ts
|
|
57
60
|
import { Argument, Command } from "commander";
|
|
@@ -185,15 +188,18 @@ function createUpdateStylesCommand(runtime) {
|
|
|
185
188
|
// core-engine/commands/default-action.ts
|
|
186
189
|
var ADD_COMMAND = "add";
|
|
187
190
|
var CREATE_COMMAND = "create";
|
|
191
|
+
var GENERATE_COMMAND = "generate";
|
|
188
192
|
var INIT_COMMAND = "init";
|
|
189
193
|
var REMOVE_COMMAND = "remove";
|
|
190
194
|
var REMOVE_SCHEMA_COMMAND = "remove-schema";
|
|
195
|
+
var UPDATE_COMMAND = "update";
|
|
196
|
+
var ALL_FLAG = "--all";
|
|
191
197
|
var CANCELLED = /* @__PURE__ */ Symbol("cancelled");
|
|
192
198
|
function cancelled(value) {
|
|
193
199
|
return value === CANCELLED;
|
|
194
200
|
}
|
|
195
201
|
async function runDefaultAction(program2, runtime) {
|
|
196
|
-
if (!
|
|
202
|
+
if (!isInteractiveTerminalSession()) {
|
|
197
203
|
program2.outputHelp();
|
|
198
204
|
return;
|
|
199
205
|
}
|
|
@@ -238,6 +244,24 @@ async function promptRequiredArguments(name, runtime, cwd) {
|
|
|
238
244
|
if (name === ADD_COMMAND || name === REMOVE_COMMAND) {
|
|
239
245
|
return promptInstallables(name, runtime, cwd);
|
|
240
246
|
}
|
|
247
|
+
if (name === GENERATE_COMMAND) {
|
|
248
|
+
const schemas = await runtime.listSchemaChoices(cwd);
|
|
249
|
+
if (schemas.length === 0) {
|
|
250
|
+
p.log.warn("No schemas to generate.");
|
|
251
|
+
return CANCELLED;
|
|
252
|
+
}
|
|
253
|
+
const target = await p.select({
|
|
254
|
+
message: "What do you want to generate?",
|
|
255
|
+
options: [
|
|
256
|
+
...schemas.map((value) => ({ value, label: value })),
|
|
257
|
+
{ value: ALL_FLAG, label: "All schemas", hint: "regenerate everything" }
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
return p.isCancel(target) ? CANCELLED : [target];
|
|
261
|
+
}
|
|
262
|
+
if (name === UPDATE_COMMAND) {
|
|
263
|
+
return promptComponents(runtime, cwd);
|
|
264
|
+
}
|
|
241
265
|
if (name === REMOVE_SCHEMA_COMMAND) {
|
|
242
266
|
const schemas = await runtime.listSchemaChoices(cwd);
|
|
243
267
|
if (schemas.length === 0) {
|
|
@@ -252,6 +276,31 @@ async function promptRequiredArguments(name, runtime, cwd) {
|
|
|
252
276
|
}
|
|
253
277
|
return [];
|
|
254
278
|
}
|
|
279
|
+
async function promptComponents(runtime, cwd) {
|
|
280
|
+
const scope = await p.select({
|
|
281
|
+
message: "What do you want to update?",
|
|
282
|
+
options: [
|
|
283
|
+
{ value: ALL_FLAG, label: "All components", hint: "every installed component" },
|
|
284
|
+
{ value: "pick", label: "Choose components" }
|
|
285
|
+
]
|
|
286
|
+
});
|
|
287
|
+
if (p.isCancel(scope)) {
|
|
288
|
+
return CANCELLED;
|
|
289
|
+
}
|
|
290
|
+
if (scope === ALL_FLAG) {
|
|
291
|
+
return [ALL_FLAG];
|
|
292
|
+
}
|
|
293
|
+
const components = await runtime.listComponentChoices(cwd);
|
|
294
|
+
if (components.length === 0) {
|
|
295
|
+
p.log.warn("No components available to update.");
|
|
296
|
+
return CANCELLED;
|
|
297
|
+
}
|
|
298
|
+
const selected = await p.multiselect({
|
|
299
|
+
message: "Components to update",
|
|
300
|
+
options: components.map((value) => ({ value, label: value }))
|
|
301
|
+
});
|
|
302
|
+
return p.isCancel(selected) ? CANCELLED : selected;
|
|
303
|
+
}
|
|
255
304
|
async function promptInstallables(name, runtime, cwd) {
|
|
256
305
|
const removing = name === REMOVE_COMMAND;
|
|
257
306
|
const choices = await runtime.listInstallableChoices(cwd);
|
|
@@ -25055,8 +25104,16 @@ function scaffoldLayout({ cwd, config }) {
|
|
|
25055
25104
|
readTemplate("pages/settings/forms/forms-settings-page-content.tsx")
|
|
25056
25105
|
);
|
|
25057
25106
|
write(
|
|
25058
|
-
path43.join(settingsFormsDir, "
|
|
25059
|
-
readTemplate("pages/settings/forms/
|
|
25107
|
+
path43.join(settingsFormsDir, "forms-settings-columns.tsx"),
|
|
25108
|
+
readTemplate("pages/settings/forms/forms-settings-columns.tsx")
|
|
25109
|
+
);
|
|
25110
|
+
write(
|
|
25111
|
+
path43.join(settingsFormsDir, "forms-settings-table.tsx"),
|
|
25112
|
+
readTemplate("pages/settings/forms/forms-settings-table.tsx")
|
|
25113
|
+
);
|
|
25114
|
+
write(
|
|
25115
|
+
path43.join(settingsFormsDir, "form-notifications-drawer.tsx"),
|
|
25116
|
+
readTemplate("pages/settings/forms/form-notifications-drawer.tsx")
|
|
25060
25117
|
);
|
|
25061
25118
|
const settingsWebhooksDir = path43.join(settingsDir, "webhooks");
|
|
25062
25119
|
write(
|
|
@@ -28914,581 +28971,13 @@ async function runListPresetsCommand(options) {
|
|
|
28914
28971
|
}
|
|
28915
28972
|
|
|
28916
28973
|
// adapters/next/commands/menu-choices.ts
|
|
28917
|
-
import path55 from "path";
|
|
28918
|
-
async function listInstallableChoices(cwd) {
|
|
28919
|
-
const config = await resolveConfigOrExit(cwd);
|
|
28920
|
-
const installedPresets = new Set(config.presets.installed);
|
|
28921
|
-
const installedIntegrations = new Set(config.integrations.installed);
|
|
28922
|
-
return {
|
|
28923
|
-
presets: listAvailablePresets().map((preset) => ({
|
|
28924
|
-
id: preset.id,
|
|
28925
|
-
description: preset.description,
|
|
28926
|
-
installed: installedPresets.has(preset.id)
|
|
28927
|
-
})),
|
|
28928
|
-
integrations: listAvailableIntegrations().map((integration) => ({
|
|
28929
|
-
id: integration.id,
|
|
28930
|
-
description: integration.description,
|
|
28931
|
-
installed: installedIntegrations.has(integration.id)
|
|
28932
|
-
}))
|
|
28933
|
-
};
|
|
28934
|
-
}
|
|
28935
|
-
async function listSchemaChoices(cwd) {
|
|
28936
|
-
const config = await resolveConfigOrExit(cwd);
|
|
28937
|
-
const paths = resolveProjectPaths(config);
|
|
28938
|
-
return listSchemaNames(path55.join(cwd, ...paths.schemasDir.split("/")));
|
|
28939
|
-
}
|
|
28940
|
-
|
|
28941
|
-
// adapters/next/commands/remove.ts
|
|
28942
28974
|
import path56 from "path";
|
|
28943
|
-
import * as p29 from "@clack/prompts";
|
|
28944
|
-
async function runRemoveCommand(items, options) {
|
|
28945
|
-
const removeIntegrationsMode = Boolean(options.integration);
|
|
28946
|
-
if (!removeIntegrationsMode && items.includes("core")) {
|
|
28947
|
-
p29.log.error("The core Admin cannot be removed.");
|
|
28948
|
-
process.exit(1);
|
|
28949
|
-
}
|
|
28950
|
-
const presetIds = items.filter(isPresetId);
|
|
28951
|
-
const integrationIds = items.filter(isIntegrationId);
|
|
28952
|
-
if (!removeIntegrationsMode && integrationIds.length > 0) {
|
|
28953
|
-
p29.log.error(
|
|
28954
|
-
`Integration IDs require --integration. Run \`betterstart remove --integration ${integrationIds.join(" ")}\`.`
|
|
28955
|
-
);
|
|
28956
|
-
process.exit(1);
|
|
28957
|
-
}
|
|
28958
|
-
if (removeIntegrationsMode && presetIds.length > 0) {
|
|
28959
|
-
p29.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
|
|
28960
|
-
process.exit(1);
|
|
28961
|
-
}
|
|
28962
|
-
const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
28963
|
-
if (invalidItems.length > 0) {
|
|
28964
|
-
p29.log.error(
|
|
28965
|
-
removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
28966
|
-
);
|
|
28967
|
-
process.exit(1);
|
|
28968
|
-
}
|
|
28969
|
-
const cwd = options.cwd ? path56.resolve(options.cwd) : process.cwd();
|
|
28970
|
-
const config = await resolveConfigOrExit(cwd);
|
|
28971
|
-
const pm = detectPackageManager(cwd);
|
|
28972
|
-
if (!options.force) {
|
|
28973
|
-
const confirmed = await p29.confirm({
|
|
28974
|
-
message: `Remove ${removeIntegrationsMode ? "integration" : "preset"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
|
|
28975
|
-
initialValue: false
|
|
28976
|
-
});
|
|
28977
|
-
if (p29.isCancel(confirmed) || !confirmed) {
|
|
28978
|
-
p29.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
|
|
28979
|
-
process.exit(0);
|
|
28980
|
-
}
|
|
28981
|
-
}
|
|
28982
|
-
if (removeIntegrationsMode) {
|
|
28983
|
-
const result2 = await removeIntegrations({
|
|
28984
|
-
cwd,
|
|
28985
|
-
config,
|
|
28986
|
-
pm,
|
|
28987
|
-
integrationIds
|
|
28988
|
-
});
|
|
28989
|
-
writeConfigFile(cwd, result2.config);
|
|
28990
|
-
if (result2.removed.length === 0) {
|
|
28991
|
-
p29.outro("No integrations were removed.");
|
|
28992
|
-
return;
|
|
28993
|
-
}
|
|
28994
|
-
if (result2.warnings.length > 0) {
|
|
28995
|
-
p29.note(result2.warnings.join("\n"), "Warnings");
|
|
28996
|
-
}
|
|
28997
|
-
p29.outro(
|
|
28998
|
-
`Removed integration${result2.removed.length === 1 ? "" : "s"}: ${result2.removed.join(", ")}`
|
|
28999
|
-
);
|
|
29000
|
-
return;
|
|
29001
|
-
}
|
|
29002
|
-
const result = await removePresets({
|
|
29003
|
-
cwd,
|
|
29004
|
-
config,
|
|
29005
|
-
pm,
|
|
29006
|
-
presetIds
|
|
29007
|
-
});
|
|
29008
|
-
writeConfigFile(cwd, result.config);
|
|
29009
|
-
if (result.removed.length === 0) {
|
|
29010
|
-
p29.outro("No presets were removed.");
|
|
29011
|
-
return;
|
|
29012
|
-
}
|
|
29013
|
-
if (result.warnings.length > 0) {
|
|
29014
|
-
p29.note(result.warnings.join("\n"), "Warnings");
|
|
29015
|
-
}
|
|
29016
|
-
p29.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
|
|
29017
|
-
}
|
|
29018
28975
|
|
|
29019
|
-
// adapters/next/commands/
|
|
28976
|
+
// adapters/next/commands/update-component.ts
|
|
28977
|
+
import { execFileSync as execFileSync5 } from "child_process";
|
|
29020
28978
|
import fs42 from "fs";
|
|
29021
|
-
import
|
|
28979
|
+
import path55 from "path";
|
|
29022
28980
|
import * as clack3 from "@clack/prompts";
|
|
29023
|
-
function removePath2(cwd, filePath) {
|
|
29024
|
-
const fullPath = path57.join(cwd, ...filePath.split("/"));
|
|
29025
|
-
const existed = fs42.existsSync(fullPath);
|
|
29026
|
-
fs42.rmSync(fullPath, { recursive: true, force: true });
|
|
29027
|
-
return existed;
|
|
29028
|
-
}
|
|
29029
|
-
function cleanupEmptyDirs3(cwd, deletedPaths, configPaths) {
|
|
29030
|
-
const stopRoots = /* @__PURE__ */ new Set([
|
|
29031
|
-
path57.join(cwd, ...configPaths.adminDir.split("/")),
|
|
29032
|
-
path57.join(cwd, ...configPaths.adminNavigationDir.split("/")),
|
|
29033
|
-
path57.join(cwd, ...configPaths.adminWebhookEventsDir.split("/")),
|
|
29034
|
-
path57.join(cwd, ...configPaths.pagesDir.split("/"))
|
|
29035
|
-
]);
|
|
29036
|
-
for (const deletedPath of deletedPaths) {
|
|
29037
|
-
let current = path57.dirname(path57.join(cwd, ...deletedPath.split("/")));
|
|
29038
|
-
while (!stopRoots.has(current)) {
|
|
29039
|
-
if (!fs42.existsSync(current)) {
|
|
29040
|
-
current = path57.dirname(current);
|
|
29041
|
-
continue;
|
|
29042
|
-
}
|
|
29043
|
-
const entries = fs42.readdirSync(current);
|
|
29044
|
-
if (entries.length > 0) {
|
|
29045
|
-
break;
|
|
29046
|
-
}
|
|
29047
|
-
fs42.rmdirSync(current);
|
|
29048
|
-
current = path57.dirname(current);
|
|
29049
|
-
}
|
|
29050
|
-
}
|
|
29051
|
-
}
|
|
29052
|
-
function resolveSchemaOwnerForRemoval(cwd, schemaName) {
|
|
29053
|
-
const explicitOwner = getSchemaOwner(cwd, schemaName);
|
|
29054
|
-
if (explicitOwner) {
|
|
29055
|
-
return explicitOwner;
|
|
29056
|
-
}
|
|
29057
|
-
if (schemaName === "settings") {
|
|
29058
|
-
return "core";
|
|
29059
|
-
}
|
|
29060
|
-
return "user";
|
|
29061
|
-
}
|
|
29062
|
-
async function runRemoveSchemaCommand(schemaName, options) {
|
|
29063
|
-
const owner = resolveSchemaOwnerForRemoval(
|
|
29064
|
-
options.cwd ? path57.resolve(options.cwd) : process.cwd(),
|
|
29065
|
-
schemaName
|
|
29066
|
-
);
|
|
29067
|
-
if (owner === "core") {
|
|
29068
|
-
clack3.log.error(
|
|
29069
|
-
`"${schemaName}" is a core Admin module and cannot be removed with remove-schema.`
|
|
29070
|
-
);
|
|
29071
|
-
process.exit(1);
|
|
29072
|
-
}
|
|
29073
|
-
if (owner.startsWith("preset:")) {
|
|
29074
|
-
clack3.log.error(`"${schemaName}" is owned by ${owner}. Remove the owning preset instead.`);
|
|
29075
|
-
process.exit(1);
|
|
29076
|
-
}
|
|
29077
|
-
const cwd = options.cwd ? path57.resolve(options.cwd) : process.cwd();
|
|
29078
|
-
const config = await resolveConfigOrExit(cwd);
|
|
29079
|
-
const paths = resolveProjectPaths(config);
|
|
29080
|
-
const manifest = loadManifest(cwd, schemaName);
|
|
29081
|
-
if (!snapshotRootExists(cwd)) {
|
|
29082
|
-
clack3.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
|
|
29083
|
-
process.exit(1);
|
|
29084
|
-
}
|
|
29085
|
-
if (!manifest) {
|
|
29086
|
-
clack3.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
|
|
29087
|
-
process.exit(1);
|
|
29088
|
-
}
|
|
29089
|
-
if (!options.force) {
|
|
29090
|
-
if (!isInteractiveSession()) {
|
|
29091
|
-
clack3.log.error(
|
|
29092
|
-
`Removing generated files for ${schemaName} needs confirmation. Re-run with --force.`
|
|
29093
|
-
);
|
|
29094
|
-
process.exit(1);
|
|
29095
|
-
}
|
|
29096
|
-
const confirmed = await clack3.confirm({
|
|
29097
|
-
message: `Remove generated files for ${schemaName}?`,
|
|
29098
|
-
initialValue: false
|
|
29099
|
-
});
|
|
29100
|
-
if (clack3.isCancel(confirmed) || !confirmed) {
|
|
29101
|
-
clack3.cancel("Cancelled.");
|
|
29102
|
-
return;
|
|
29103
|
-
}
|
|
29104
|
-
}
|
|
29105
|
-
const deletedPaths = [];
|
|
29106
|
-
for (const file of [...manifest.files.map((entry) => entry.path), ...manifest.skipped]) {
|
|
29107
|
-
if (removePath2(cwd, file)) {
|
|
29108
|
-
deletedPaths.push(file);
|
|
29109
|
-
}
|
|
29110
|
-
}
|
|
29111
|
-
const loaded = (() => {
|
|
29112
|
-
try {
|
|
29113
|
-
return loadSchema(path57.join(cwd, ...paths.schemasDir.split("/")), schemaName);
|
|
29114
|
-
} catch {
|
|
29115
|
-
return null;
|
|
29116
|
-
}
|
|
29117
|
-
})();
|
|
29118
|
-
const kebabName = toKebabCase(schemaName);
|
|
29119
|
-
if (loaded?.type === "form") {
|
|
29120
|
-
if (removePath2(cwd, `${paths.adminActionsDir}/${schemaName}`)) {
|
|
29121
|
-
deletedPaths.push(`${paths.adminActionsDir}/${schemaName}`);
|
|
29122
|
-
}
|
|
29123
|
-
if (removePath2(cwd, `${paths.pagesDir}/forms/${kebabName}`)) {
|
|
29124
|
-
deletedPaths.push(`${paths.pagesDir}/forms/${kebabName}`);
|
|
29125
|
-
}
|
|
29126
|
-
} else {
|
|
29127
|
-
if (removePath2(cwd, `${paths.adminActionsDir}/${schemaName}`)) {
|
|
29128
|
-
deletedPaths.push(`${paths.adminActionsDir}/${schemaName}`);
|
|
29129
|
-
}
|
|
29130
|
-
if (removePath2(cwd, `${paths.pagesDir}/${schemaName}`)) {
|
|
29131
|
-
deletedPaths.push(`${paths.pagesDir}/${schemaName}`);
|
|
29132
|
-
}
|
|
29133
|
-
}
|
|
29134
|
-
cleanupEmptyDirs3(cwd, deletedPaths, paths);
|
|
29135
|
-
deleteSnapshot(cwd, schemaName);
|
|
29136
|
-
if (hasTombstone(cwd, schemaName)) {
|
|
29137
|
-
clearTombstone(cwd, schemaName);
|
|
29138
|
-
}
|
|
29139
|
-
writeTombstone(cwd, schemaName);
|
|
29140
|
-
await applyGeneratedFiles({
|
|
29141
|
-
cwd,
|
|
29142
|
-
config,
|
|
29143
|
-
scope: BARREL_SCOPE,
|
|
29144
|
-
schemaJson: { name: BARREL_SCOPE },
|
|
29145
|
-
generatedFiles: renderBarrelFiles(cwd, config),
|
|
29146
|
-
force: false,
|
|
29147
|
-
interactive: false
|
|
29148
|
-
});
|
|
29149
|
-
clack3.log.info(
|
|
29150
|
-
`Tombstone written: .betterstart/snapshots/_removed/${schemaName}
|
|
29151
|
-
Schema JSON preserved.`
|
|
29152
|
-
);
|
|
29153
|
-
clack3.outro(`Removed generated files for ${schemaName}`);
|
|
29154
|
-
}
|
|
29155
|
-
|
|
29156
|
-
// adapters/next/commands/uninstall.ts
|
|
29157
|
-
import fs44 from "fs";
|
|
29158
|
-
import path58 from "path";
|
|
29159
|
-
import * as p30 from "@clack/prompts";
|
|
29160
|
-
import pc11 from "picocolors";
|
|
29161
|
-
|
|
29162
|
-
// adapters/next/commands/uninstall-cleaners.ts
|
|
29163
|
-
import fs43 from "fs";
|
|
29164
|
-
function stripJsonComments2(input) {
|
|
29165
|
-
let result = "";
|
|
29166
|
-
let i = 0;
|
|
29167
|
-
while (i < input.length) {
|
|
29168
|
-
if (input[i] === '"') {
|
|
29169
|
-
let j = i + 1;
|
|
29170
|
-
while (j < input.length) {
|
|
29171
|
-
if (input[j] === "\\") {
|
|
29172
|
-
j += 2;
|
|
29173
|
-
continue;
|
|
29174
|
-
}
|
|
29175
|
-
if (input[j] === '"') {
|
|
29176
|
-
j++;
|
|
29177
|
-
break;
|
|
29178
|
-
}
|
|
29179
|
-
j++;
|
|
29180
|
-
}
|
|
29181
|
-
result += input.slice(i, j);
|
|
29182
|
-
i = j;
|
|
29183
|
-
} else if (input[i] === "/" && input[i + 1] === "/") {
|
|
29184
|
-
const nl = input.indexOf("\n", i);
|
|
29185
|
-
i = nl === -1 ? input.length : nl;
|
|
29186
|
-
} else if (input[i] === "/" && input[i + 1] === "*") {
|
|
29187
|
-
const end = input.indexOf("*/", i + 2);
|
|
29188
|
-
i = end === -1 ? input.length : end + 2;
|
|
29189
|
-
} else {
|
|
29190
|
-
result += input[i];
|
|
29191
|
-
i++;
|
|
29192
|
-
}
|
|
29193
|
-
}
|
|
29194
|
-
return result;
|
|
29195
|
-
}
|
|
29196
|
-
function cleanTsconfig(tsconfigPath, aliasRoot = "@admin") {
|
|
29197
|
-
if (!fs43.existsSync(tsconfigPath)) return [];
|
|
29198
|
-
const raw = fs43.readFileSync(tsconfigPath, "utf-8");
|
|
29199
|
-
const stripped = stripJsonComments2(raw).replace(/,\s*([\]}])/g, "$1");
|
|
29200
|
-
let tsconfig;
|
|
29201
|
-
try {
|
|
29202
|
-
tsconfig = JSON.parse(stripped);
|
|
29203
|
-
} catch {
|
|
29204
|
-
return [];
|
|
29205
|
-
}
|
|
29206
|
-
const compilerOptions = tsconfig.compilerOptions ?? {};
|
|
29207
|
-
const paths = compilerOptions.paths ?? {};
|
|
29208
|
-
const removed = [];
|
|
29209
|
-
for (const key of Object.keys(paths)) {
|
|
29210
|
-
if (key.startsWith("@admin/") || key === "@admin/*" || key.startsWith(`${aliasRoot}/`) || key === `${aliasRoot}/*`) {
|
|
29211
|
-
removed.push(key);
|
|
29212
|
-
delete paths[key];
|
|
29213
|
-
}
|
|
29214
|
-
}
|
|
29215
|
-
if (removed.length === 0) return [];
|
|
29216
|
-
if (Object.keys(paths).length === 0) {
|
|
29217
|
-
compilerOptions.paths = void 0;
|
|
29218
|
-
} else {
|
|
29219
|
-
compilerOptions.paths = paths;
|
|
29220
|
-
}
|
|
29221
|
-
tsconfig.compilerOptions = compilerOptions;
|
|
29222
|
-
fs43.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
29223
|
-
`, "utf-8");
|
|
29224
|
-
return removed;
|
|
29225
|
-
}
|
|
29226
|
-
function cleanCss(cssPath, namespace = "admin") {
|
|
29227
|
-
if (!fs43.existsSync(cssPath)) return [];
|
|
29228
|
-
const content = fs43.readFileSync(cssPath, "utf-8");
|
|
29229
|
-
const lines = content.split("\n");
|
|
29230
|
-
const sourcePattern = new RegExp(`^@source\\s+"[^"]*(?:admin|${namespace})[^"]*";\\s*$`);
|
|
29231
|
-
const removed = [];
|
|
29232
|
-
const kept = [];
|
|
29233
|
-
for (const line of lines) {
|
|
29234
|
-
if (sourcePattern.test(line)) {
|
|
29235
|
-
removed.push(line.trim());
|
|
29236
|
-
} else {
|
|
29237
|
-
kept.push(line);
|
|
29238
|
-
}
|
|
29239
|
-
}
|
|
29240
|
-
if (removed.length === 0) return [];
|
|
29241
|
-
const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
29242
|
-
fs43.writeFileSync(cssPath, cleaned, "utf-8");
|
|
29243
|
-
return removed;
|
|
29244
|
-
}
|
|
29245
|
-
function cleanEnvFile(envPath) {
|
|
29246
|
-
if (!fs43.existsSync(envPath)) return [];
|
|
29247
|
-
const content = fs43.readFileSync(envPath, "utf-8");
|
|
29248
|
-
const lines = content.split("\n");
|
|
29249
|
-
const removed = [];
|
|
29250
|
-
const kept = [];
|
|
29251
|
-
const headerPattern = /^# =+$/;
|
|
29252
|
-
const headerTextPattern = /^# BetterStart Admin$/;
|
|
29253
|
-
for (let i = 0; i < lines.length; i++) {
|
|
29254
|
-
const line = lines[i];
|
|
29255
|
-
const trimmed = line.trim();
|
|
29256
|
-
if (trimmed.match(/^BETTERSTART_\w+=/)) {
|
|
29257
|
-
const key = trimmed.split("=")[0];
|
|
29258
|
-
removed.push(key);
|
|
29259
|
-
continue;
|
|
29260
|
-
}
|
|
29261
|
-
if (headerPattern.test(trimmed)) {
|
|
29262
|
-
const next = lines[i + 1]?.trim();
|
|
29263
|
-
const afterNext = lines[i + 2]?.trim();
|
|
29264
|
-
if (next && headerTextPattern.test(next) && afterNext && headerPattern.test(afterNext)) {
|
|
29265
|
-
i += 2;
|
|
29266
|
-
continue;
|
|
29267
|
-
}
|
|
29268
|
-
}
|
|
29269
|
-
if (trimmed.startsWith("#") && !headerPattern.test(trimmed)) {
|
|
29270
|
-
const nextNonEmpty = findNextNonEmptyLine(lines, i + 1);
|
|
29271
|
-
if (nextNonEmpty?.match(/^BETTERSTART_\w+=/)) {
|
|
29272
|
-
continue;
|
|
29273
|
-
}
|
|
29274
|
-
}
|
|
29275
|
-
kept.push(line);
|
|
29276
|
-
}
|
|
29277
|
-
if (removed.length === 0) return [];
|
|
29278
|
-
const result = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
29279
|
-
if (result === "") {
|
|
29280
|
-
fs43.unlinkSync(envPath);
|
|
29281
|
-
} else {
|
|
29282
|
-
fs43.writeFileSync(envPath, `${result}
|
|
29283
|
-
`, "utf-8");
|
|
29284
|
-
}
|
|
29285
|
-
return removed;
|
|
29286
|
-
}
|
|
29287
|
-
function findNextNonEmptyLine(lines, startIndex) {
|
|
29288
|
-
for (let i = startIndex; i < lines.length; i++) {
|
|
29289
|
-
const trimmed = lines[i].trim();
|
|
29290
|
-
if (trimmed !== "") return trimmed;
|
|
29291
|
-
}
|
|
29292
|
-
return null;
|
|
29293
|
-
}
|
|
29294
|
-
|
|
29295
|
-
// adapters/next/commands/uninstall.ts
|
|
29296
|
-
function findMainCss2(cwd) {
|
|
29297
|
-
const candidates = [
|
|
29298
|
-
"src/app/globals.css",
|
|
29299
|
-
"app/globals.css",
|
|
29300
|
-
"src/app/global.css",
|
|
29301
|
-
"app/global.css",
|
|
29302
|
-
"src/app/app.css",
|
|
29303
|
-
"app/app.css",
|
|
29304
|
-
"src/globals.css",
|
|
29305
|
-
"globals.css"
|
|
29306
|
-
];
|
|
29307
|
-
for (const candidate of candidates) {
|
|
29308
|
-
const filePath = path58.join(cwd, candidate);
|
|
29309
|
-
if (fs44.existsSync(filePath)) return filePath;
|
|
29310
|
-
}
|
|
29311
|
-
return void 0;
|
|
29312
|
-
}
|
|
29313
|
-
function isCLICreatedBiome(biomePath) {
|
|
29314
|
-
if (!fs44.existsSync(biomePath)) return false;
|
|
29315
|
-
try {
|
|
29316
|
-
const content = JSON.parse(fs44.readFileSync(biomePath, "utf-8"));
|
|
29317
|
-
return content.$schema?.includes("biomejs.dev") && content.formatter?.indentStyle === "space" && content.javascript?.formatter?.quoteStyle === "single" && Array.isArray(content.files?.ignore) && content.files.ignore.includes(".next");
|
|
29318
|
-
} catch {
|
|
29319
|
-
return false;
|
|
29320
|
-
}
|
|
29321
|
-
}
|
|
29322
|
-
function buildUninstallPlan(cwd, namespaceValue) {
|
|
29323
|
-
const steps = [];
|
|
29324
|
-
const namespace = resolveAdminNamespace(namespaceValue);
|
|
29325
|
-
const hasSrc = fs44.existsSync(path58.join(cwd, "src"));
|
|
29326
|
-
const appBase = hasSrc ? "src/app" : "app";
|
|
29327
|
-
const dirs = [];
|
|
29328
|
-
const adminDir = path58.join(cwd, namespace.segment);
|
|
29329
|
-
const legacyAdminDir = path58.join(cwd, "admin");
|
|
29330
|
-
const adminRouteGroup = path58.join(cwd, appBase, namespace.routeGroup);
|
|
29331
|
-
const legacyAdminRouteGroup = path58.join(cwd, appBase, "(admin)");
|
|
29332
|
-
if (fs44.existsSync(adminDir)) dirs.push(`${namespace.segment}/`);
|
|
29333
|
-
if (namespace.segment !== "admin" && fs44.existsSync(legacyAdminDir)) dirs.push("admin/");
|
|
29334
|
-
if (fs44.existsSync(adminRouteGroup)) dirs.push(`${appBase}/${namespace.routeGroup}/`);
|
|
29335
|
-
if (namespace.segment !== "admin" && fs44.existsSync(legacyAdminRouteGroup))
|
|
29336
|
-
dirs.push(`${appBase}/(admin)/`);
|
|
29337
|
-
if (dirs.length > 0) {
|
|
29338
|
-
steps.push({
|
|
29339
|
-
label: "Admin directories",
|
|
29340
|
-
items: dirs,
|
|
29341
|
-
count: dirs.length,
|
|
29342
|
-
unit: dirs.length === 1 ? "directory" : "directories",
|
|
29343
|
-
execute() {
|
|
29344
|
-
if (fs44.existsSync(adminDir)) fs44.rmSync(adminDir, { recursive: true, force: true });
|
|
29345
|
-
if (fs44.existsSync(legacyAdminDir))
|
|
29346
|
-
fs44.rmSync(legacyAdminDir, { recursive: true, force: true });
|
|
29347
|
-
if (fs44.existsSync(adminRouteGroup)) {
|
|
29348
|
-
fs44.rmSync(adminRouteGroup, { recursive: true, force: true });
|
|
29349
|
-
}
|
|
29350
|
-
if (fs44.existsSync(legacyAdminRouteGroup)) {
|
|
29351
|
-
fs44.rmSync(legacyAdminRouteGroup, { recursive: true, force: true });
|
|
29352
|
-
}
|
|
29353
|
-
}
|
|
29354
|
-
});
|
|
29355
|
-
}
|
|
29356
|
-
const configFiles = [];
|
|
29357
|
-
const configPaths = [];
|
|
29358
|
-
const candidates = [
|
|
29359
|
-
[CONFIG_FILE_NAME, path58.join(cwd, CONFIG_FILE_NAME)],
|
|
29360
|
-
["drizzle.config.ts", path58.join(cwd, "drizzle.config.ts")],
|
|
29361
|
-
["ADMIN.md", path58.join(cwd, "ADMIN.md")]
|
|
29362
|
-
];
|
|
29363
|
-
for (const [label, fullPath] of candidates) {
|
|
29364
|
-
if (fs44.existsSync(fullPath)) {
|
|
29365
|
-
configFiles.push(label);
|
|
29366
|
-
configPaths.push(fullPath);
|
|
29367
|
-
}
|
|
29368
|
-
}
|
|
29369
|
-
const biomePath = path58.join(cwd, "biome.json");
|
|
29370
|
-
if (isCLICreatedBiome(biomePath)) {
|
|
29371
|
-
configFiles.push("biome.json (CLI-created)");
|
|
29372
|
-
configPaths.push(biomePath);
|
|
29373
|
-
}
|
|
29374
|
-
if (configFiles.length > 0) {
|
|
29375
|
-
steps.push({
|
|
29376
|
-
label: "Config files",
|
|
29377
|
-
items: configFiles,
|
|
29378
|
-
count: configFiles.length,
|
|
29379
|
-
unit: configFiles.length === 1 ? "file" : "files",
|
|
29380
|
-
execute() {
|
|
29381
|
-
for (const p32 of configPaths) {
|
|
29382
|
-
if (fs44.existsSync(p32)) fs44.unlinkSync(p32);
|
|
29383
|
-
}
|
|
29384
|
-
}
|
|
29385
|
-
});
|
|
29386
|
-
}
|
|
29387
|
-
const tsconfigPath = path58.join(cwd, "tsconfig.json");
|
|
29388
|
-
if (fs44.existsSync(tsconfigPath)) {
|
|
29389
|
-
const content = fs44.readFileSync(tsconfigPath, "utf-8");
|
|
29390
|
-
const aliasMatches = [
|
|
29391
|
-
...content.match(/"@admin\//g) ?? [],
|
|
29392
|
-
...content.match(new RegExp(`"${namespace.alias}/`, "g")) ?? []
|
|
29393
|
-
];
|
|
29394
|
-
if (aliasMatches && aliasMatches.length > 0) {
|
|
29395
|
-
const aliasCount = aliasMatches.length;
|
|
29396
|
-
steps.push({
|
|
29397
|
-
label: "tsconfig.json path aliases",
|
|
29398
|
-
items: [`${namespace.alias}/* aliases in tsconfig.json`],
|
|
29399
|
-
count: aliasCount,
|
|
29400
|
-
unit: aliasCount === 1 ? "alias" : "aliases",
|
|
29401
|
-
execute() {
|
|
29402
|
-
cleanTsconfig(tsconfigPath, namespace.alias);
|
|
29403
|
-
}
|
|
29404
|
-
});
|
|
29405
|
-
}
|
|
29406
|
-
}
|
|
29407
|
-
const cssFile = findMainCss2(cwd);
|
|
29408
|
-
if (cssFile) {
|
|
29409
|
-
const cssContent = fs44.readFileSync(cssFile, "utf-8");
|
|
29410
|
-
const sourceLines = cssContent.split("\n").filter(
|
|
29411
|
-
(l) => new RegExp(`^@source\\s+"[^"]*(?:admin|${namespace.segment})[^"]*";\\s*$`).test(l)
|
|
29412
|
-
);
|
|
29413
|
-
if (sourceLines.length > 0) {
|
|
29414
|
-
const relCss = path58.relative(cwd, cssFile);
|
|
29415
|
-
steps.push({
|
|
29416
|
-
label: `CSS @source lines (${relCss})`,
|
|
29417
|
-
items: [`@source lines in ${relCss}`],
|
|
29418
|
-
count: sourceLines.length,
|
|
29419
|
-
unit: sourceLines.length === 1 ? "line" : "lines",
|
|
29420
|
-
execute() {
|
|
29421
|
-
cleanCss(cssFile, namespace.segment);
|
|
29422
|
-
}
|
|
29423
|
-
});
|
|
29424
|
-
}
|
|
29425
|
-
}
|
|
29426
|
-
const envPath = path58.join(cwd, ".env.local");
|
|
29427
|
-
if (fs44.existsSync(envPath)) {
|
|
29428
|
-
const envContent = fs44.readFileSync(envPath, "utf-8");
|
|
29429
|
-
const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
|
|
29430
|
-
if (bsVars.length > 0) {
|
|
29431
|
-
steps.push({
|
|
29432
|
-
label: ".env.local variables",
|
|
29433
|
-
items: ["BETTERSTART_* vars in .env.local"],
|
|
29434
|
-
count: bsVars.length,
|
|
29435
|
-
unit: bsVars.length === 1 ? "variable" : "variables",
|
|
29436
|
-
execute() {
|
|
29437
|
-
cleanEnvFile(envPath);
|
|
29438
|
-
}
|
|
29439
|
-
});
|
|
29440
|
-
}
|
|
29441
|
-
}
|
|
29442
|
-
return steps;
|
|
29443
|
-
}
|
|
29444
|
-
async function runUninstallCommand(options) {
|
|
29445
|
-
const cwd = options.cwd ? path58.resolve(options.cwd) : process.cwd();
|
|
29446
|
-
p30.intro(pc11.bgRed(pc11.white(" BetterStart Uninstall ")));
|
|
29447
|
-
let namespace = DEFAULT_ADMIN_NAMESPACE;
|
|
29448
|
-
try {
|
|
29449
|
-
const config = await resolveConfig(cwd);
|
|
29450
|
-
namespace = config.frameworkConfig.next.namespace;
|
|
29451
|
-
} catch {
|
|
29452
|
-
}
|
|
29453
|
-
const steps = buildUninstallPlan(cwd, namespace);
|
|
29454
|
-
if (steps.length === 0) {
|
|
29455
|
-
p30.log.success(`${pc11.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
|
|
29456
|
-
p30.outro("Project already clean");
|
|
29457
|
-
return;
|
|
29458
|
-
}
|
|
29459
|
-
const planLines = steps.map((step) => {
|
|
29460
|
-
const names = step.items.join(" ");
|
|
29461
|
-
const countLabel = pc11.dim(`${step.count} ${step.unit}`);
|
|
29462
|
-
return `${pc11.red("\u2717")} ${names} ${countLabel}`;
|
|
29463
|
-
});
|
|
29464
|
-
p30.note(planLines.join("\n"), "Uninstall plan");
|
|
29465
|
-
if (!options.force) {
|
|
29466
|
-
const confirmed = await p30.confirm({
|
|
29467
|
-
message: "Proceed with uninstall?",
|
|
29468
|
-
initialValue: false
|
|
29469
|
-
});
|
|
29470
|
-
if (p30.isCancel(confirmed) || !confirmed) {
|
|
29471
|
-
p30.cancel("Uninstall cancelled.");
|
|
29472
|
-
process.exit(0);
|
|
29473
|
-
}
|
|
29474
|
-
}
|
|
29475
|
-
const s = spinner2();
|
|
29476
|
-
s.start(steps[0].label);
|
|
29477
|
-
for (const step of steps) {
|
|
29478
|
-
s.message(step.label);
|
|
29479
|
-
step.execute();
|
|
29480
|
-
}
|
|
29481
|
-
const parts = steps.map((step) => `${step.count} ${step.unit}`);
|
|
29482
|
-
s.stop(`Removed ${parts.join(", ")}`);
|
|
29483
|
-
p30.note(pc11.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
|
|
29484
|
-
p30.outro("Uninstall complete");
|
|
29485
|
-
}
|
|
29486
|
-
|
|
29487
|
-
// adapters/next/commands/update-component.ts
|
|
29488
|
-
import { execFileSync as execFileSync5 } from "child_process";
|
|
29489
|
-
import fs45 from "fs";
|
|
29490
|
-
import path59 from "path";
|
|
29491
|
-
import * as clack4 from "@clack/prompts";
|
|
29492
28981
|
import fsExtra from "fs-extra";
|
|
29493
28982
|
var STATIC_CUSTOM_DEPENDENCIES = {
|
|
29494
28983
|
"content-editor": [
|
|
@@ -29738,24 +29227,24 @@ function applyNamespaceToTemplateEntry(entry, config, cwd) {
|
|
|
29738
29227
|
};
|
|
29739
29228
|
}
|
|
29740
29229
|
function writeNamespacedFile(srcPath, destPath, namespace) {
|
|
29741
|
-
|
|
29230
|
+
fs42.writeFileSync(
|
|
29742
29231
|
destPath,
|
|
29743
|
-
applyAdminNamespaceToContent(
|
|
29232
|
+
applyAdminNamespaceToContent(fs42.readFileSync(srcPath, "utf-8"), namespace),
|
|
29744
29233
|
"utf-8"
|
|
29745
29234
|
);
|
|
29746
29235
|
}
|
|
29747
29236
|
function copyNamespacedDirectory(srcDir, destDir, namespace) {
|
|
29748
|
-
const entries =
|
|
29237
|
+
const entries = fs42.readdirSync(srcDir, { withFileTypes: true });
|
|
29749
29238
|
for (const entry of entries) {
|
|
29750
29239
|
const namespacedName = applyAdminNamespaceToPath(entry.name, namespace);
|
|
29751
|
-
const srcPath =
|
|
29752
|
-
const destPath =
|
|
29240
|
+
const srcPath = path55.join(srcDir, entry.name);
|
|
29241
|
+
const destPath = path55.join(destDir, namespacedName);
|
|
29753
29242
|
if (entry.isDirectory()) {
|
|
29754
29243
|
fsExtra.ensureDirSync(destPath);
|
|
29755
29244
|
copyNamespacedDirectory(srcPath, destPath, namespace);
|
|
29756
29245
|
continue;
|
|
29757
29246
|
}
|
|
29758
|
-
fsExtra.ensureDirSync(
|
|
29247
|
+
fsExtra.ensureDirSync(path55.dirname(destPath));
|
|
29759
29248
|
writeNamespacedFile(srcPath, destPath, namespace);
|
|
29760
29249
|
}
|
|
29761
29250
|
}
|
|
@@ -29766,10 +29255,10 @@ function hasIntegration(config, integrationId) {
|
|
|
29766
29255
|
return config.integrations.installed.includes(integrationId);
|
|
29767
29256
|
}
|
|
29768
29257
|
function readProjectPackageJson2(cwd) {
|
|
29769
|
-
const pkgPath =
|
|
29770
|
-
if (!
|
|
29258
|
+
const pkgPath = path55.join(cwd, "package.json");
|
|
29259
|
+
if (!fs42.existsSync(pkgPath)) return null;
|
|
29771
29260
|
try {
|
|
29772
|
-
return JSON.parse(
|
|
29261
|
+
return JSON.parse(fs42.readFileSync(pkgPath, "utf-8"));
|
|
29773
29262
|
} catch {
|
|
29774
29263
|
return null;
|
|
29775
29264
|
}
|
|
@@ -30653,13 +30142,38 @@ var TEMPLATE_REGISTRY = {
|
|
|
30653
30142
|
relPath: "app/(admin)/admin/(authenticated)/settings/forms/forms-settings-page-content.tsx",
|
|
30654
30143
|
content: () => readTemplate("pages/settings/forms/forms-settings-page-content.tsx"),
|
|
30655
30144
|
base: "cwd",
|
|
30656
|
-
dependencies: [
|
|
30145
|
+
dependencies: [
|
|
30146
|
+
"form-notifications-drawer",
|
|
30147
|
+
"forms-settings-columns",
|
|
30148
|
+
"forms-settings-table",
|
|
30149
|
+
"page-header",
|
|
30150
|
+
"use-webhooks"
|
|
30151
|
+
]
|
|
30152
|
+
},
|
|
30153
|
+
"forms-settings-columns": {
|
|
30154
|
+
relPath: "app/(admin)/admin/(authenticated)/settings/forms/forms-settings-columns.tsx",
|
|
30155
|
+
content: () => readTemplate("pages/settings/forms/forms-settings-columns.tsx"),
|
|
30156
|
+
base: "cwd"
|
|
30157
|
+
},
|
|
30158
|
+
"forms-settings-table": {
|
|
30159
|
+
relPath: "app/(admin)/admin/(authenticated)/settings/forms/forms-settings-table.tsx",
|
|
30160
|
+
content: () => readTemplate("pages/settings/forms/forms-settings-table.tsx"),
|
|
30161
|
+
base: "cwd",
|
|
30162
|
+
dependencies: ["data-grid"]
|
|
30657
30163
|
},
|
|
30658
|
-
"
|
|
30659
|
-
relPath: "app/(admin)/admin/(authenticated)/settings/forms/
|
|
30660
|
-
content: () => readTemplate("pages/settings/forms/
|
|
30164
|
+
"form-notifications-drawer": {
|
|
30165
|
+
relPath: "app/(admin)/admin/(authenticated)/settings/forms/form-notifications-drawer.tsx",
|
|
30166
|
+
content: () => readTemplate("pages/settings/forms/form-notifications-drawer.tsx"),
|
|
30661
30167
|
base: "cwd",
|
|
30662
|
-
dependencies: [
|
|
30168
|
+
dependencies: [
|
|
30169
|
+
"button",
|
|
30170
|
+
"card",
|
|
30171
|
+
"drawer",
|
|
30172
|
+
"form",
|
|
30173
|
+
"form-settings-action",
|
|
30174
|
+
"scroll-area",
|
|
30175
|
+
"textarea"
|
|
30176
|
+
]
|
|
30663
30177
|
},
|
|
30664
30178
|
"webhooks-page": {
|
|
30665
30179
|
relPath: "app/(admin)/admin/(authenticated)/settings/webhooks/page.tsx",
|
|
@@ -31277,577 +30791,1151 @@ function getStaticUiComponents() {
|
|
|
31277
30791
|
function getStaticUiComponentEntries() {
|
|
31278
30792
|
return getStaticAssetComponentEntries("ui");
|
|
31279
30793
|
}
|
|
31280
|
-
function getStaticCustomComponents() {
|
|
31281
|
-
return getStaticAssetComponents("custom");
|
|
30794
|
+
function getStaticCustomComponents() {
|
|
30795
|
+
return getStaticAssetComponents("custom");
|
|
30796
|
+
}
|
|
30797
|
+
function getStaticCustomComponentEntries() {
|
|
30798
|
+
return getStaticAssetComponentEntries("custom");
|
|
30799
|
+
}
|
|
30800
|
+
function getStaticAssetComponents(assetDirectory) {
|
|
30801
|
+
return getStaticAssetComponentEntries(assetDirectory).map((entry) => entry.name);
|
|
30802
|
+
}
|
|
30803
|
+
function getStaticAssetComponentEntries(assetDirectory) {
|
|
30804
|
+
const assetDir = resolveCliAssetPath("shared-assets", "react-admin", assetDirectory);
|
|
30805
|
+
if (!fs42.existsSync(assetDir)) return [];
|
|
30806
|
+
const components = [];
|
|
30807
|
+
for (const entry of fs42.readdirSync(assetDir, { withFileTypes: true })) {
|
|
30808
|
+
if (entry.isFile() && (entry.name.endsWith(".tsx") || entry.name.endsWith(".ts"))) {
|
|
30809
|
+
components.push({
|
|
30810
|
+
name: entry.name.replace(/\.(tsx|ts)$/, ""),
|
|
30811
|
+
file: entry.name
|
|
30812
|
+
});
|
|
30813
|
+
continue;
|
|
30814
|
+
}
|
|
30815
|
+
if (!entry.isDirectory()) {
|
|
30816
|
+
continue;
|
|
30817
|
+
}
|
|
30818
|
+
const indexFile = ["index.tsx", "index.ts"].find(
|
|
30819
|
+
(file) => fs42.existsSync(path55.join(assetDir, entry.name, file))
|
|
30820
|
+
);
|
|
30821
|
+
if (indexFile) {
|
|
30822
|
+
components.push({
|
|
30823
|
+
name: entry.name,
|
|
30824
|
+
file: path55.join(entry.name, indexFile)
|
|
30825
|
+
});
|
|
30826
|
+
}
|
|
30827
|
+
}
|
|
30828
|
+
return components.sort((a, b) => a.name.localeCompare(b.name));
|
|
30829
|
+
}
|
|
30830
|
+
function findStaticAssetFile(assetDir, componentName) {
|
|
30831
|
+
if (!fs42.existsSync(assetDir)) return void 0;
|
|
30832
|
+
const isNestedComponentName = /[\\/]/.test(componentName);
|
|
30833
|
+
const nestedComponentName = componentName.split(/[\\/]/).filter(Boolean).join(path55.sep);
|
|
30834
|
+
if (isNestedComponentName && nestedComponentName && !path55.isAbsolute(componentName) && !nestedComponentName.split(path55.sep).includes("..")) {
|
|
30835
|
+
for (const extension of [".tsx", ".ts"]) {
|
|
30836
|
+
const relPath = `${nestedComponentName}${extension}`;
|
|
30837
|
+
const filePath = path55.join(assetDir, relPath);
|
|
30838
|
+
if (fs42.existsSync(filePath) && fs42.statSync(filePath).isFile()) {
|
|
30839
|
+
return relPath;
|
|
30840
|
+
}
|
|
30841
|
+
}
|
|
30842
|
+
}
|
|
30843
|
+
if (!isNestedComponentName && !componentName.includes("..") && !path55.isAbsolute(componentName)) {
|
|
30844
|
+
for (const extension of [".tsx", ".ts"]) {
|
|
30845
|
+
const relPath = path55.join(componentName, `index${extension}`);
|
|
30846
|
+
const filePath = path55.join(assetDir, relPath);
|
|
30847
|
+
if (fs42.existsSync(filePath) && fs42.statSync(filePath).isFile()) {
|
|
30848
|
+
return relPath;
|
|
30849
|
+
}
|
|
30850
|
+
}
|
|
30851
|
+
}
|
|
30852
|
+
return fs42.readdirSync(assetDir, { withFileTypes: true }).find(
|
|
30853
|
+
(entry) => entry.isFile() && (entry.name.endsWith(".tsx") || entry.name.endsWith(".ts")) && entry.name.replace(/\.(tsx|ts)$/, "") === componentName
|
|
30854
|
+
)?.name;
|
|
31282
30855
|
}
|
|
31283
|
-
function
|
|
31284
|
-
|
|
30856
|
+
function getAllComponentNames() {
|
|
30857
|
+
const staticUi = getStaticUiComponents();
|
|
30858
|
+
const staticCustom = getStaticCustomComponents();
|
|
30859
|
+
const templateKeys = Object.keys(TEMPLATE_REGISTRY);
|
|
30860
|
+
return [.../* @__PURE__ */ new Set([...staticUi, ...staticCustom, ...templateKeys, "tiptap"])].sort();
|
|
31285
30861
|
}
|
|
31286
|
-
function
|
|
31287
|
-
|
|
30862
|
+
function getAllComponentNamesForConfig(config) {
|
|
30863
|
+
const staticUi = getStaticUiComponents();
|
|
30864
|
+
const staticCustom = getStaticCustomComponents();
|
|
30865
|
+
const templateKeys = Object.entries(TEMPLATE_REGISTRY).filter(
|
|
30866
|
+
([, entry]) => (!entry.requiredPreset || hasPreset(config, entry.requiredPreset)) && (!entry.requiredIntegration || hasIntegration(config, entry.requiredIntegration))
|
|
30867
|
+
).map(([name]) => name);
|
|
30868
|
+
return [.../* @__PURE__ */ new Set([...staticUi, ...staticCustom, ...templateKeys, "tiptap"])].sort();
|
|
31288
30869
|
}
|
|
31289
|
-
function
|
|
31290
|
-
const
|
|
31291
|
-
|
|
31292
|
-
|
|
31293
|
-
|
|
31294
|
-
|
|
31295
|
-
|
|
31296
|
-
|
|
31297
|
-
|
|
30870
|
+
async function runUpdateCommand(components, options) {
|
|
30871
|
+
const cwd = options.cwd ? path55.resolve(options.cwd) : process.cwd();
|
|
30872
|
+
const normalizedOnly = normalizeShadcnPresetOnly(options.only);
|
|
30873
|
+
validateShadcnPresetOptions(components, options);
|
|
30874
|
+
if (options.json && !options.list) {
|
|
30875
|
+
clack3.cancel("--json can only be used with --list.");
|
|
30876
|
+
process.exit(1);
|
|
30877
|
+
}
|
|
30878
|
+
if (options.list) {
|
|
30879
|
+
const uiComponents = getStaticUiComponentEntries();
|
|
30880
|
+
const customComponents = getStaticCustomComponentEntries();
|
|
30881
|
+
const templateKeys = Object.keys(TEMPLATE_REGISTRY).sort();
|
|
30882
|
+
const templatePath = (name) => {
|
|
30883
|
+
const entry = TEMPLATE_REGISTRY[name];
|
|
30884
|
+
return entry.displayPath ?? (typeof entry.relPath === "string" ? entry.relPath : "");
|
|
30885
|
+
};
|
|
30886
|
+
if (options.json) {
|
|
30887
|
+
const items = [
|
|
30888
|
+
...uiComponents.map((component) => ({
|
|
30889
|
+
name: component.name,
|
|
30890
|
+
path: `components/ui/${component.file}`,
|
|
30891
|
+
kind: "ui"
|
|
30892
|
+
})),
|
|
30893
|
+
...customComponents.map((component) => ({
|
|
30894
|
+
name: component.name,
|
|
30895
|
+
path: `components/custom/${component.file}`,
|
|
30896
|
+
kind: "custom"
|
|
30897
|
+
})),
|
|
30898
|
+
...templateKeys.map((name) => ({ name, path: templatePath(name), kind: "template" })),
|
|
30899
|
+
{ name: "tiptap", path: "components/custom/content-editor/tiptap-*/", kind: "special" }
|
|
30900
|
+
];
|
|
30901
|
+
console.log(JSON.stringify(items, null, 2));
|
|
30902
|
+
return;
|
|
30903
|
+
}
|
|
30904
|
+
const all = getAllComponentNames();
|
|
30905
|
+
clack3.intro("Available components");
|
|
30906
|
+
clack3.note(
|
|
30907
|
+
renderTableRows(
|
|
30908
|
+
uiComponents.map((component) => [component.name, `components/ui/${component.file}`])
|
|
30909
|
+
).join("\n"),
|
|
30910
|
+
`Shadcn UI Components (${uiComponents.length})`
|
|
30911
|
+
);
|
|
30912
|
+
clack3.note(
|
|
30913
|
+
renderTableRows(
|
|
30914
|
+
customComponents.map((component) => [component.name, `components/custom/${component.file}`])
|
|
30915
|
+
).join("\n"),
|
|
30916
|
+
`Custom Components (${customComponents.length})`
|
|
30917
|
+
);
|
|
30918
|
+
clack3.note(
|
|
30919
|
+
renderTableRows(templateKeys.map((name) => [name, templatePath(name)])).join("\n"),
|
|
30920
|
+
`Template Components (${templateKeys.length})`
|
|
30921
|
+
);
|
|
30922
|
+
clack3.note(
|
|
30923
|
+
renderTableRows([["tiptap", "components/custom/content-editor/tiptap-*/ (all files)"]]).join(
|
|
30924
|
+
"\n"
|
|
30925
|
+
),
|
|
30926
|
+
"Special"
|
|
30927
|
+
);
|
|
30928
|
+
clack3.outro(`${all.length} components available`);
|
|
30929
|
+
return;
|
|
30930
|
+
}
|
|
30931
|
+
const config = await resolveConfigOrExit(cwd);
|
|
30932
|
+
const admin = path55.resolve(cwd, config.paths.admin);
|
|
30933
|
+
if (!fs42.existsSync(admin)) {
|
|
30934
|
+
clack3.cancel(
|
|
30935
|
+
`Admin directory not found at ${config.paths.admin}. Run 'betterstart init' first.`
|
|
30936
|
+
);
|
|
30937
|
+
process.exit(1);
|
|
30938
|
+
}
|
|
30939
|
+
if (options.shadcnPreset) {
|
|
30940
|
+
runShadcnPresetUpdate({
|
|
30941
|
+
cwd,
|
|
30942
|
+
config,
|
|
30943
|
+
preset: options.shadcnPreset.trim(),
|
|
30944
|
+
only: normalizedOnly
|
|
30945
|
+
});
|
|
30946
|
+
return;
|
|
30947
|
+
}
|
|
30948
|
+
if (!options.all && components.length === 0) {
|
|
30949
|
+
clack3.log.error(
|
|
30950
|
+
"Provide component names or use --all. Run with --list to see available components."
|
|
30951
|
+
);
|
|
30952
|
+
process.exit(1);
|
|
30953
|
+
}
|
|
30954
|
+
clack3.intro("BetterStart Update Components");
|
|
30955
|
+
const toUpdate = options.all ? getAllComponentNamesForConfig(config) : components;
|
|
30956
|
+
const uiDir = resolveCliAssetPath("shared-assets", "react-admin", "ui");
|
|
30957
|
+
const customDir = resolveCliAssetPath("shared-assets", "react-admin", "custom");
|
|
30958
|
+
let updated = 0;
|
|
30959
|
+
let skipped = 0;
|
|
30960
|
+
const updatedTemplateNames = /* @__PURE__ */ new Set();
|
|
30961
|
+
const updatedStaticNames = /* @__PURE__ */ new Set();
|
|
30962
|
+
const requiredPackageDependencies = /* @__PURE__ */ new Set();
|
|
30963
|
+
const pendingWrites = [];
|
|
30964
|
+
function trackPackageDependencies(name) {
|
|
30965
|
+
for (const dependency of COMPONENT_PACKAGE_DEPENDENCIES[name] ?? []) {
|
|
30966
|
+
requiredPackageDependencies.add(dependency);
|
|
30967
|
+
}
|
|
30968
|
+
}
|
|
30969
|
+
function writeTemplateEntry(name, entry) {
|
|
30970
|
+
if (updatedTemplateNames.has(name)) {
|
|
30971
|
+
return false;
|
|
30972
|
+
}
|
|
30973
|
+
if (entry.requiredPreset && !hasPreset(config, entry.requiredPreset)) {
|
|
30974
|
+
clack3.log.warn(`${name} requires the ${entry.requiredPreset} preset and was skipped.`);
|
|
30975
|
+
skipped++;
|
|
30976
|
+
return false;
|
|
30977
|
+
}
|
|
30978
|
+
if (entry.requiredIntegration && !hasIntegration(config, entry.requiredIntegration)) {
|
|
30979
|
+
clack3.log.warn(
|
|
30980
|
+
`${name} requires the ${entry.requiredIntegration} integration and was skipped.`
|
|
30981
|
+
);
|
|
30982
|
+
skipped++;
|
|
30983
|
+
return false;
|
|
30984
|
+
}
|
|
30985
|
+
const { relPath, content } = applyNamespaceToTemplateEntry(entry, config, cwd);
|
|
30986
|
+
const baseDir = entry.base === "cwd" ? cwd : admin;
|
|
30987
|
+
const destPath = path55.join(baseDir, relPath);
|
|
30988
|
+
if (entry.preserveExisting && fs42.existsSync(destPath)) {
|
|
30989
|
+
clack3.log.info(`Preserved ${relPath}`);
|
|
30990
|
+
updatedTemplateNames.add(name);
|
|
30991
|
+
skipped++;
|
|
30992
|
+
return false;
|
|
30993
|
+
}
|
|
30994
|
+
pendingWrites.push({
|
|
30995
|
+
displayPath: relPath,
|
|
30996
|
+
write: () => {
|
|
30997
|
+
fsExtra.ensureDirSync(path55.dirname(destPath));
|
|
30998
|
+
fs42.writeFileSync(destPath, content, "utf-8");
|
|
30999
|
+
clack3.log.success(`Updated ${relPath}`);
|
|
31000
|
+
}
|
|
31001
|
+
});
|
|
31002
|
+
updatedTemplateNames.add(name);
|
|
31003
|
+
trackPackageDependencies(name);
|
|
31004
|
+
updated++;
|
|
31005
|
+
return true;
|
|
31006
|
+
}
|
|
31007
|
+
function writeTemplateEntryWithDependencies(name, entry) {
|
|
31008
|
+
const wroteEntry = writeTemplateEntry(name, entry);
|
|
31009
|
+
if (!wroteEntry) {
|
|
31010
|
+
return false;
|
|
31011
|
+
}
|
|
31012
|
+
for (const dependencyName of entry.dependencies ?? []) {
|
|
31013
|
+
writeNamedDependency(dependencyName);
|
|
31014
|
+
}
|
|
31015
|
+
return true;
|
|
31016
|
+
}
|
|
31017
|
+
function writeStaticAssetEntry(assetDirectory, name) {
|
|
31018
|
+
const key = `${assetDirectory}:${name}`;
|
|
31019
|
+
if (updatedStaticNames.has(key)) {
|
|
31020
|
+
return false;
|
|
31021
|
+
}
|
|
31022
|
+
const assetDir = assetDirectory === "ui" ? uiDir : customDir;
|
|
31023
|
+
const assetFile = findStaticAssetFile(assetDir, name);
|
|
31024
|
+
if (!assetFile) {
|
|
31025
|
+
return false;
|
|
31026
|
+
}
|
|
31027
|
+
const namespace = config.frameworkConfig.next.namespace;
|
|
31028
|
+
const namespacedAssetFile = applyAdminNamespaceToPath(assetFile, namespace);
|
|
31029
|
+
const destPath = path55.join(admin, "components", assetDirectory, namespacedAssetFile);
|
|
31030
|
+
pendingWrites.push({
|
|
31031
|
+
displayPath: `components/${assetDirectory}/${namespacedAssetFile}`,
|
|
31032
|
+
write: () => {
|
|
31033
|
+
fsExtra.ensureDirSync(path55.dirname(destPath));
|
|
31034
|
+
writeNamespacedFile(path55.join(assetDir, assetFile), destPath, namespace);
|
|
31035
|
+
clack3.log.success(`Updated components/${assetDirectory}/${namespacedAssetFile}`);
|
|
31036
|
+
}
|
|
31037
|
+
});
|
|
31038
|
+
if (assetDirectory === "custom") {
|
|
31039
|
+
const assetSubdir = path55.join(assetDir, name);
|
|
31040
|
+
if (fs42.existsSync(assetSubdir) && fs42.statSync(assetSubdir).isDirectory()) {
|
|
31041
|
+
const namespacedName = applyAdminNamespaceToPath(name, namespace);
|
|
31042
|
+
const destSubdir = path55.join(admin, "components", assetDirectory, namespacedName);
|
|
31043
|
+
pendingWrites.push({
|
|
31044
|
+
displayPath: `components/${assetDirectory}/${namespacedName}/ (template files)`,
|
|
31045
|
+
write: () => {
|
|
31046
|
+
fsExtra.ensureDirSync(destSubdir);
|
|
31047
|
+
copyNamespacedDirectory(assetSubdir, destSubdir, namespace);
|
|
31048
|
+
clack3.log.success(
|
|
31049
|
+
`Updated components/${assetDirectory}/${namespacedName}/ (template files)`
|
|
31050
|
+
);
|
|
31051
|
+
}
|
|
31052
|
+
});
|
|
31053
|
+
}
|
|
31054
|
+
}
|
|
31055
|
+
updatedStaticNames.add(key);
|
|
31056
|
+
trackPackageDependencies(name);
|
|
31057
|
+
updated++;
|
|
31058
|
+
if (assetDirectory === "custom") {
|
|
31059
|
+
for (const dependencyName of STATIC_CUSTOM_DEPENDENCIES[name] ?? []) {
|
|
31060
|
+
writeNamedDependency(dependencyName);
|
|
31061
|
+
}
|
|
31062
|
+
}
|
|
31063
|
+
return true;
|
|
31064
|
+
}
|
|
31065
|
+
function writeTiptapTemplates() {
|
|
31066
|
+
const key = "custom:tiptap";
|
|
31067
|
+
if (updatedStaticNames.has(key)) {
|
|
31068
|
+
return true;
|
|
31069
|
+
}
|
|
31070
|
+
const srcBaseDir = resolveCliAssetPath(
|
|
31071
|
+
"shared-assets",
|
|
31072
|
+
"react-admin",
|
|
31073
|
+
"custom",
|
|
31074
|
+
"content-editor"
|
|
31075
|
+
);
|
|
31076
|
+
const namespace = config.frameworkConfig.next.namespace;
|
|
31077
|
+
const destBaseDir = path55.join(admin, "components", "custom", "content-editor");
|
|
31078
|
+
if (!fs42.existsSync(srcBaseDir)) {
|
|
31079
|
+
return false;
|
|
31080
|
+
}
|
|
31081
|
+
const dirsToCopy = [];
|
|
31082
|
+
for (const directory of TIPTAP_CONTENT_EDITOR_DIRECTORIES) {
|
|
31083
|
+
const srcDir = path55.join(srcBaseDir, directory);
|
|
31084
|
+
if (!fs42.existsSync(srcDir)) {
|
|
31085
|
+
continue;
|
|
31086
|
+
}
|
|
31087
|
+
dirsToCopy.push({
|
|
31088
|
+
srcDir,
|
|
31089
|
+
destDir: path55.join(destBaseDir, applyAdminNamespaceToPath(directory, namespace))
|
|
31298
31090
|
});
|
|
31091
|
+
}
|
|
31092
|
+
if (dirsToCopy.length === 0) {
|
|
31093
|
+
return false;
|
|
31094
|
+
}
|
|
31095
|
+
pendingWrites.push({
|
|
31096
|
+
displayPath: "components/custom/content-editor/tiptap-*/ (template files)",
|
|
31097
|
+
write: () => {
|
|
31098
|
+
for (const { srcDir, destDir } of dirsToCopy) {
|
|
31099
|
+
fsExtra.ensureDirSync(destDir);
|
|
31100
|
+
copyNamespacedDirectory(srcDir, destDir, namespace);
|
|
31101
|
+
}
|
|
31102
|
+
clack3.log.success("Updated components/custom/content-editor/tiptap-*/ (template files)");
|
|
31103
|
+
removeLegacyDirectory(path55.join(admin, "components", "custom", "tiptap"));
|
|
31104
|
+
}
|
|
31105
|
+
});
|
|
31106
|
+
updatedStaticNames.add(key);
|
|
31107
|
+
trackPackageDependencies("tiptap");
|
|
31108
|
+
updated++;
|
|
31109
|
+
for (const dependencyName of TIPTAP_TEMPLATE_DEPENDENCIES) {
|
|
31110
|
+
writeNamedDependency(dependencyName);
|
|
31111
|
+
}
|
|
31112
|
+
return true;
|
|
31113
|
+
}
|
|
31114
|
+
function writeNamedDependency(name) {
|
|
31115
|
+
const entry = TEMPLATE_REGISTRY[name];
|
|
31116
|
+
if (entry) {
|
|
31117
|
+
writeTemplateEntryWithDependencies(name, entry);
|
|
31118
|
+
return;
|
|
31119
|
+
}
|
|
31120
|
+
if (writeStaticAssetEntry("ui", name)) {
|
|
31121
|
+
return;
|
|
31122
|
+
}
|
|
31123
|
+
if (writeStaticAssetEntry("custom", name)) {
|
|
31124
|
+
return;
|
|
31125
|
+
}
|
|
31126
|
+
if (name === "tiptap") {
|
|
31127
|
+
writeTiptapTemplates();
|
|
31128
|
+
}
|
|
31129
|
+
}
|
|
31130
|
+
for (const name of toUpdate) {
|
|
31131
|
+
if (TEMPLATE_REGISTRY[name]) {
|
|
31132
|
+
const entry = TEMPLATE_REGISTRY[name];
|
|
31133
|
+
writeTemplateEntryWithDependencies(name, entry);
|
|
31299
31134
|
continue;
|
|
31300
31135
|
}
|
|
31301
|
-
if (
|
|
31136
|
+
if (writeStaticAssetEntry("ui", name)) {
|
|
31302
31137
|
continue;
|
|
31303
31138
|
}
|
|
31304
|
-
|
|
31305
|
-
|
|
31306
|
-
);
|
|
31307
|
-
if (indexFile) {
|
|
31308
|
-
components.push({
|
|
31309
|
-
name: entry.name,
|
|
31310
|
-
file: path59.join(entry.name, indexFile)
|
|
31311
|
-
});
|
|
31139
|
+
if (writeStaticAssetEntry("custom", name)) {
|
|
31140
|
+
continue;
|
|
31312
31141
|
}
|
|
31313
|
-
|
|
31314
|
-
|
|
31315
|
-
|
|
31316
|
-
|
|
31317
|
-
if (!fs45.existsSync(assetDir)) return void 0;
|
|
31318
|
-
const isNestedComponentName = /[\\/]/.test(componentName);
|
|
31319
|
-
const nestedComponentName = componentName.split(/[\\/]/).filter(Boolean).join(path59.sep);
|
|
31320
|
-
if (isNestedComponentName && nestedComponentName && !path59.isAbsolute(componentName) && !nestedComponentName.split(path59.sep).includes("..")) {
|
|
31321
|
-
for (const extension of [".tsx", ".ts"]) {
|
|
31322
|
-
const relPath = `${nestedComponentName}${extension}`;
|
|
31323
|
-
const filePath = path59.join(assetDir, relPath);
|
|
31324
|
-
if (fs45.existsSync(filePath) && fs45.statSync(filePath).isFile()) {
|
|
31325
|
-
return relPath;
|
|
31142
|
+
if (name === "tiptap") {
|
|
31143
|
+
if (!writeTiptapTemplates()) {
|
|
31144
|
+
clack3.log.warn("tiptap templates not found");
|
|
31145
|
+
skipped++;
|
|
31326
31146
|
}
|
|
31147
|
+
continue;
|
|
31327
31148
|
}
|
|
31149
|
+
clack3.log.warn(`Unknown component: ${name}`);
|
|
31150
|
+
skipped++;
|
|
31328
31151
|
}
|
|
31329
|
-
if (
|
|
31330
|
-
|
|
31331
|
-
|
|
31332
|
-
|
|
31333
|
-
|
|
31334
|
-
|
|
31152
|
+
if (pendingWrites.length > 0) {
|
|
31153
|
+
const displayPaths = pendingWrites.map((entry) => entry.displayPath);
|
|
31154
|
+
const preview = displayPaths.slice(0, MAX_OVERWRITE_PREVIEW_ROWS);
|
|
31155
|
+
if (displayPaths.length > preview.length) {
|
|
31156
|
+
preview.push(`\u2026 and ${displayPaths.length - preview.length} more`);
|
|
31157
|
+
}
|
|
31158
|
+
clack3.note(
|
|
31159
|
+
preview.join("\n"),
|
|
31160
|
+
`Overwriting ${displayPaths.length} file${displayPaths.length === 1 ? "" : "s"}`
|
|
31161
|
+
);
|
|
31162
|
+
if (!options.yes) {
|
|
31163
|
+
if (!isInteractiveSession()) {
|
|
31164
|
+
clack3.log.error(
|
|
31165
|
+
`Overwriting ${displayPaths.length} file${displayPaths.length === 1 ? "" : "s"} needs confirmation. Re-run with --yes.`
|
|
31166
|
+
);
|
|
31167
|
+
process.exit(1);
|
|
31168
|
+
}
|
|
31169
|
+
const proceed = await clack3.confirm({
|
|
31170
|
+
message: "Overwrite these files with the latest templates?",
|
|
31171
|
+
initialValue: true
|
|
31172
|
+
});
|
|
31173
|
+
if (clack3.isCancel(proceed) || !proceed) {
|
|
31174
|
+
clack3.cancel("Update cancelled.");
|
|
31175
|
+
process.exit(0);
|
|
31335
31176
|
}
|
|
31336
31177
|
}
|
|
31178
|
+
for (const entry of pendingWrites) {
|
|
31179
|
+
entry.write();
|
|
31180
|
+
}
|
|
31337
31181
|
}
|
|
31338
|
-
|
|
31339
|
-
|
|
31340
|
-
)
|
|
31341
|
-
|
|
31342
|
-
|
|
31343
|
-
|
|
31344
|
-
|
|
31345
|
-
|
|
31346
|
-
|
|
31182
|
+
syncInstalledPresetManifests(cwd, config);
|
|
31183
|
+
syncInstalledIntegrationManifests(cwd, config);
|
|
31184
|
+
const projectPackageJson = readProjectPackageJson2(cwd);
|
|
31185
|
+
const missingPackageDependencies = Array.from(requiredPackageDependencies).filter(
|
|
31186
|
+
(dependency) => !hasDeclaredPackage2(projectPackageJson, dependency)
|
|
31187
|
+
);
|
|
31188
|
+
if (missingPackageDependencies.length > 0) {
|
|
31189
|
+
clack3.log.warn(
|
|
31190
|
+
`Updated components require package dependencies that are not declared: ${missingPackageDependencies.join(", ")}. Run 'pnpm betterstart update-deps' before building.`
|
|
31191
|
+
);
|
|
31192
|
+
}
|
|
31193
|
+
clack3.outro(
|
|
31194
|
+
`Updated ${updated} component${updated !== 1 ? "s" : ""}${skipped > 0 ? `, ${skipped} skipped` : ""}`
|
|
31195
|
+
);
|
|
31347
31196
|
}
|
|
31348
|
-
function
|
|
31349
|
-
|
|
31350
|
-
|
|
31351
|
-
|
|
31352
|
-
([, entry]) => (!entry.requiredPreset || hasPreset(config, entry.requiredPreset)) && (!entry.requiredIntegration || hasIntegration(config, entry.requiredIntegration))
|
|
31353
|
-
).map(([name]) => name);
|
|
31354
|
-
return [.../* @__PURE__ */ new Set([...staticUi, ...staticCustom, ...templateKeys, "tiptap"])].sort();
|
|
31197
|
+
function removeLegacyDirectory(dirPath) {
|
|
31198
|
+
if (fs42.existsSync(dirPath)) {
|
|
31199
|
+
fs42.rmSync(dirPath, { recursive: true, force: true });
|
|
31200
|
+
}
|
|
31355
31201
|
}
|
|
31356
|
-
|
|
31357
|
-
|
|
31358
|
-
|
|
31359
|
-
validateShadcnPresetOptions(components, options);
|
|
31360
|
-
if (options.json && !options.list) {
|
|
31361
|
-
clack4.cancel("--json can only be used with --list.");
|
|
31202
|
+
function validateShadcnPresetOptions(components, options) {
|
|
31203
|
+
if (options.only && !options.shadcnPreset) {
|
|
31204
|
+
clack3.cancel("--only can only be used with --shadcn-preset.");
|
|
31362
31205
|
process.exit(1);
|
|
31363
31206
|
}
|
|
31207
|
+
if (!options.shadcnPreset) {
|
|
31208
|
+
return;
|
|
31209
|
+
}
|
|
31364
31210
|
if (options.list) {
|
|
31365
|
-
|
|
31366
|
-
|
|
31367
|
-
|
|
31368
|
-
|
|
31369
|
-
|
|
31370
|
-
|
|
31371
|
-
|
|
31372
|
-
|
|
31373
|
-
|
|
31374
|
-
|
|
31375
|
-
|
|
31376
|
-
|
|
31377
|
-
|
|
31378
|
-
|
|
31379
|
-
|
|
31380
|
-
|
|
31381
|
-
|
|
31382
|
-
|
|
31383
|
-
|
|
31384
|
-
|
|
31385
|
-
{ name: "tiptap", path: "components/custom/content-editor/tiptap-*/", kind: "special" }
|
|
31386
|
-
];
|
|
31387
|
-
console.log(JSON.stringify(items, null, 2));
|
|
31388
|
-
return;
|
|
31389
|
-
}
|
|
31390
|
-
const all = getAllComponentNames();
|
|
31391
|
-
clack4.intro("Available components");
|
|
31392
|
-
clack4.note(
|
|
31393
|
-
renderTableRows(
|
|
31394
|
-
uiComponents.map((component) => [component.name, `components/ui/${component.file}`])
|
|
31395
|
-
).join("\n"),
|
|
31396
|
-
`Shadcn UI Components (${uiComponents.length})`
|
|
31211
|
+
clack3.cancel("--list cannot be combined with --shadcn-preset.");
|
|
31212
|
+
process.exit(1);
|
|
31213
|
+
}
|
|
31214
|
+
if (options.all) {
|
|
31215
|
+
clack3.cancel("--all cannot be combined with --shadcn-preset.");
|
|
31216
|
+
process.exit(1);
|
|
31217
|
+
}
|
|
31218
|
+
if (components.length > 0) {
|
|
31219
|
+
clack3.cancel("Component names cannot be combined with --shadcn-preset.");
|
|
31220
|
+
process.exit(1);
|
|
31221
|
+
}
|
|
31222
|
+
}
|
|
31223
|
+
function normalizeShadcnPresetOnly(value) {
|
|
31224
|
+
if (!value) {
|
|
31225
|
+
return void 0;
|
|
31226
|
+
}
|
|
31227
|
+
const parts = value.split(",").map((part) => part.trim().toLowerCase()).filter(Boolean);
|
|
31228
|
+
if (parts.length !== 1 || parts[0] !== "theme") {
|
|
31229
|
+
clack3.cancel(
|
|
31230
|
+
"Admin-only shadcn preset updates currently support --only theme. Omit --only to apply the full preset."
|
|
31397
31231
|
);
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
|
|
31402
|
-
|
|
31232
|
+
process.exit(1);
|
|
31233
|
+
}
|
|
31234
|
+
return "theme";
|
|
31235
|
+
}
|
|
31236
|
+
function runShadcnPresetUpdate({
|
|
31237
|
+
cwd,
|
|
31238
|
+
config,
|
|
31239
|
+
preset,
|
|
31240
|
+
only
|
|
31241
|
+
}) {
|
|
31242
|
+
const namespace = resolveAdminNamespace(config.frameworkConfig.next.namespace);
|
|
31243
|
+
const adminGlobalsPath = path55.join(cwd, config.paths.admin, namespace.globalsFile);
|
|
31244
|
+
const componentsJsonPath = path55.join(cwd, "components.json");
|
|
31245
|
+
const shadcnBackupPath = `${componentsJsonPath}.bak`;
|
|
31246
|
+
const restoreAfterApplyPaths = [
|
|
31247
|
+
componentsJsonPath,
|
|
31248
|
+
shadcnBackupPath,
|
|
31249
|
+
path55.join(cwd, config.paths.admin, "lib", "utils.ts"),
|
|
31250
|
+
...getHostProjectFilesToRestore(cwd)
|
|
31251
|
+
];
|
|
31252
|
+
if (!preset) {
|
|
31253
|
+
clack3.cancel("--shadcn-preset requires a preset code, preset name, or preset URL.");
|
|
31254
|
+
process.exit(1);
|
|
31255
|
+
}
|
|
31256
|
+
if (!fs42.existsSync(adminGlobalsPath)) {
|
|
31257
|
+
clack3.cancel(
|
|
31258
|
+
`Admin globals file not found at ${path55.relative(cwd, adminGlobalsPath)}. Run 'betterstart update admin-globals' first.`
|
|
31403
31259
|
);
|
|
31404
|
-
|
|
31405
|
-
|
|
31406
|
-
|
|
31260
|
+
process.exit(1);
|
|
31261
|
+
}
|
|
31262
|
+
const shadcnBin = resolveLocalShadcnBin(cwd);
|
|
31263
|
+
const restoreSnapshots = restoreAfterApplyPaths.map((filePath) => ({
|
|
31264
|
+
filePath,
|
|
31265
|
+
snapshot: snapshotFile(filePath)
|
|
31266
|
+
}));
|
|
31267
|
+
clack3.intro("BetterStart Shadcn Preset");
|
|
31268
|
+
clack3.log.info(`Applying preset to ${path55.join(config.paths.admin, "components/ui")}`);
|
|
31269
|
+
let failed = false;
|
|
31270
|
+
try {
|
|
31271
|
+
fs42.writeFileSync(
|
|
31272
|
+
componentsJsonPath,
|
|
31273
|
+
`${JSON.stringify(createAdminShadcnComponentsJson(config), null, 2)}
|
|
31274
|
+
`,
|
|
31275
|
+
"utf-8"
|
|
31407
31276
|
);
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31411
|
-
|
|
31412
|
-
|
|
31277
|
+
const args = ["apply", "--preset", preset, "--cwd", cwd, "--yes"];
|
|
31278
|
+
if (only) {
|
|
31279
|
+
args.push("--only", only);
|
|
31280
|
+
}
|
|
31281
|
+
execFileSync5(shadcnBin, args, { cwd, stdio: "inherit" });
|
|
31282
|
+
} catch {
|
|
31283
|
+
failed = true;
|
|
31284
|
+
} finally {
|
|
31285
|
+
for (const { filePath, snapshot } of restoreSnapshots.reverse()) {
|
|
31286
|
+
restoreFile(filePath, snapshot);
|
|
31287
|
+
}
|
|
31288
|
+
}
|
|
31289
|
+
if (failed) {
|
|
31290
|
+
clack3.cancel("shadcn preset application failed.");
|
|
31291
|
+
process.exit(1);
|
|
31292
|
+
}
|
|
31293
|
+
clack3.outro(
|
|
31294
|
+
only ? `Applied shadcn preset parts (${only}) to the Admin.` : "Applied shadcn preset to Admin UI components and styles."
|
|
31295
|
+
);
|
|
31296
|
+
}
|
|
31297
|
+
function createAdminShadcnComponentsJson(config) {
|
|
31298
|
+
const adminPath = toPosixPath(config.paths.admin);
|
|
31299
|
+
const namespace = resolveAdminNamespace(config.frameworkConfig.next.namespace);
|
|
31300
|
+
return {
|
|
31301
|
+
$schema: "https://ui.shadcn.com/schema.json",
|
|
31302
|
+
style: "new-york",
|
|
31303
|
+
rsc: true,
|
|
31304
|
+
tsx: true,
|
|
31305
|
+
tailwind: {
|
|
31306
|
+
config: "",
|
|
31307
|
+
css: `${adminPath}/${namespace.globalsFile}`,
|
|
31308
|
+
baseColor: "neutral",
|
|
31309
|
+
cssVariables: true,
|
|
31310
|
+
prefix: ""
|
|
31311
|
+
},
|
|
31312
|
+
iconLibrary: "lucide",
|
|
31313
|
+
aliases: {
|
|
31314
|
+
components: `${namespace.alias}/components`,
|
|
31315
|
+
ui: `${namespace.alias}/components/ui`,
|
|
31316
|
+
hooks: `${namespace.alias}/hooks`,
|
|
31317
|
+
lib: `${namespace.alias}/lib`,
|
|
31318
|
+
utils: `${namespace.alias}/utils/shared/cn`
|
|
31319
|
+
}
|
|
31320
|
+
};
|
|
31321
|
+
}
|
|
31322
|
+
function toPosixPath(value) {
|
|
31323
|
+
return value.replace(/\\/g, "/");
|
|
31324
|
+
}
|
|
31325
|
+
function resolveLocalShadcnBin(cwd) {
|
|
31326
|
+
const binName = process.platform === "win32" ? "shadcn.cmd" : "shadcn";
|
|
31327
|
+
const shadcnBin = path55.join(cwd, "node_modules", ".bin", binName);
|
|
31328
|
+
if (!fs42.existsSync(shadcnBin)) {
|
|
31329
|
+
clack3.cancel(
|
|
31330
|
+
`shadcn is not installed in this project. Run 'betterstart update-deps' and try again.`
|
|
31413
31331
|
);
|
|
31414
|
-
|
|
31332
|
+
process.exit(1);
|
|
31333
|
+
}
|
|
31334
|
+
return shadcnBin;
|
|
31335
|
+
}
|
|
31336
|
+
function getHostProjectFilesToRestore(cwd) {
|
|
31337
|
+
const hostRelativePaths = [
|
|
31338
|
+
"app/layout.tsx",
|
|
31339
|
+
"app/layout.ts",
|
|
31340
|
+
"app/layout.jsx",
|
|
31341
|
+
"app/layout.js",
|
|
31342
|
+
"src/app/layout.tsx",
|
|
31343
|
+
"src/app/layout.ts",
|
|
31344
|
+
"src/app/layout.jsx",
|
|
31345
|
+
"src/app/layout.js",
|
|
31346
|
+
"app/globals.css",
|
|
31347
|
+
"src/app/globals.css"
|
|
31348
|
+
];
|
|
31349
|
+
return hostRelativePaths.map((relativePath) => path55.join(cwd, relativePath));
|
|
31350
|
+
}
|
|
31351
|
+
function snapshotFile(filePath) {
|
|
31352
|
+
if (!fs42.existsSync(filePath)) {
|
|
31353
|
+
return { existed: false };
|
|
31354
|
+
}
|
|
31355
|
+
return { existed: true, content: fs42.readFileSync(filePath, "utf-8") };
|
|
31356
|
+
}
|
|
31357
|
+
function restoreFile(filePath, snapshot) {
|
|
31358
|
+
if (snapshot.existed) {
|
|
31359
|
+
fs42.writeFileSync(filePath, snapshot.content ?? "", "utf-8");
|
|
31415
31360
|
return;
|
|
31416
31361
|
}
|
|
31362
|
+
if (fs42.existsSync(filePath)) {
|
|
31363
|
+
fs42.rmSync(filePath, { force: true });
|
|
31364
|
+
}
|
|
31365
|
+
}
|
|
31366
|
+
|
|
31367
|
+
// adapters/next/commands/menu-choices.ts
|
|
31368
|
+
async function listInstallableChoices(cwd) {
|
|
31417
31369
|
const config = await resolveConfigOrExit(cwd);
|
|
31418
|
-
const
|
|
31419
|
-
|
|
31420
|
-
|
|
31421
|
-
|
|
31370
|
+
const installedPresets = new Set(config.presets.installed);
|
|
31371
|
+
const installedIntegrations = new Set(config.integrations.installed);
|
|
31372
|
+
return {
|
|
31373
|
+
presets: listAvailablePresets().map((preset) => ({
|
|
31374
|
+
id: preset.id,
|
|
31375
|
+
description: preset.description,
|
|
31376
|
+
installed: installedPresets.has(preset.id)
|
|
31377
|
+
})),
|
|
31378
|
+
integrations: listAvailableIntegrations().map((integration) => ({
|
|
31379
|
+
id: integration.id,
|
|
31380
|
+
description: integration.description,
|
|
31381
|
+
installed: installedIntegrations.has(integration.id)
|
|
31382
|
+
}))
|
|
31383
|
+
};
|
|
31384
|
+
}
|
|
31385
|
+
async function listSchemaChoices(cwd) {
|
|
31386
|
+
const config = await resolveConfigOrExit(cwd);
|
|
31387
|
+
const paths = resolveProjectPaths(config);
|
|
31388
|
+
return listSchemaNames(path56.join(cwd, ...paths.schemasDir.split("/")));
|
|
31389
|
+
}
|
|
31390
|
+
async function listComponentChoices(cwd) {
|
|
31391
|
+
const config = await resolveConfigOrExit(cwd);
|
|
31392
|
+
return getAllComponentNamesForConfig(config);
|
|
31393
|
+
}
|
|
31394
|
+
|
|
31395
|
+
// adapters/next/commands/remove.ts
|
|
31396
|
+
import path57 from "path";
|
|
31397
|
+
import * as p29 from "@clack/prompts";
|
|
31398
|
+
async function runRemoveCommand(items, options) {
|
|
31399
|
+
const removeIntegrationsMode = Boolean(options.integration);
|
|
31400
|
+
if (!removeIntegrationsMode && items.includes("core")) {
|
|
31401
|
+
p29.log.error("The core Admin cannot be removed.");
|
|
31402
|
+
process.exit(1);
|
|
31403
|
+
}
|
|
31404
|
+
const presetIds = items.filter(isPresetId);
|
|
31405
|
+
const integrationIds = items.filter(isIntegrationId);
|
|
31406
|
+
if (!removeIntegrationsMode && integrationIds.length > 0) {
|
|
31407
|
+
p29.log.error(
|
|
31408
|
+
`Integration IDs require --integration. Run \`betterstart remove --integration ${integrationIds.join(" ")}\`.`
|
|
31422
31409
|
);
|
|
31423
31410
|
process.exit(1);
|
|
31424
31411
|
}
|
|
31425
|
-
if (
|
|
31426
|
-
|
|
31427
|
-
|
|
31428
|
-
config,
|
|
31429
|
-
preset: options.shadcnPreset.trim(),
|
|
31430
|
-
only: normalizedOnly
|
|
31431
|
-
});
|
|
31432
|
-
return;
|
|
31412
|
+
if (removeIntegrationsMode && presetIds.length > 0) {
|
|
31413
|
+
p29.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
|
|
31414
|
+
process.exit(1);
|
|
31433
31415
|
}
|
|
31434
|
-
|
|
31435
|
-
|
|
31436
|
-
|
|
31416
|
+
const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
31417
|
+
if (invalidItems.length > 0) {
|
|
31418
|
+
p29.log.error(
|
|
31419
|
+
removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
31437
31420
|
);
|
|
31438
31421
|
process.exit(1);
|
|
31439
31422
|
}
|
|
31440
|
-
|
|
31441
|
-
const
|
|
31442
|
-
const
|
|
31443
|
-
|
|
31444
|
-
|
|
31445
|
-
|
|
31446
|
-
|
|
31447
|
-
const updatedStaticNames = /* @__PURE__ */ new Set();
|
|
31448
|
-
const requiredPackageDependencies = /* @__PURE__ */ new Set();
|
|
31449
|
-
const pendingWrites = [];
|
|
31450
|
-
function trackPackageDependencies(name) {
|
|
31451
|
-
for (const dependency of COMPONENT_PACKAGE_DEPENDENCIES[name] ?? []) {
|
|
31452
|
-
requiredPackageDependencies.add(dependency);
|
|
31453
|
-
}
|
|
31454
|
-
}
|
|
31455
|
-
function writeTemplateEntry(name, entry) {
|
|
31456
|
-
if (updatedTemplateNames.has(name)) {
|
|
31457
|
-
return false;
|
|
31458
|
-
}
|
|
31459
|
-
if (entry.requiredPreset && !hasPreset(config, entry.requiredPreset)) {
|
|
31460
|
-
clack4.log.warn(`${name} requires the ${entry.requiredPreset} preset and was skipped.`);
|
|
31461
|
-
skipped++;
|
|
31462
|
-
return false;
|
|
31463
|
-
}
|
|
31464
|
-
if (entry.requiredIntegration && !hasIntegration(config, entry.requiredIntegration)) {
|
|
31465
|
-
clack4.log.warn(
|
|
31466
|
-
`${name} requires the ${entry.requiredIntegration} integration and was skipped.`
|
|
31467
|
-
);
|
|
31468
|
-
skipped++;
|
|
31469
|
-
return false;
|
|
31470
|
-
}
|
|
31471
|
-
const { relPath, content } = applyNamespaceToTemplateEntry(entry, config, cwd);
|
|
31472
|
-
const baseDir = entry.base === "cwd" ? cwd : admin;
|
|
31473
|
-
const destPath = path59.join(baseDir, relPath);
|
|
31474
|
-
if (entry.preserveExisting && fs45.existsSync(destPath)) {
|
|
31475
|
-
clack4.log.info(`Preserved ${relPath}`);
|
|
31476
|
-
updatedTemplateNames.add(name);
|
|
31477
|
-
skipped++;
|
|
31478
|
-
return false;
|
|
31479
|
-
}
|
|
31480
|
-
pendingWrites.push({
|
|
31481
|
-
displayPath: relPath,
|
|
31482
|
-
write: () => {
|
|
31483
|
-
fsExtra.ensureDirSync(path59.dirname(destPath));
|
|
31484
|
-
fs45.writeFileSync(destPath, content, "utf-8");
|
|
31485
|
-
clack4.log.success(`Updated ${relPath}`);
|
|
31486
|
-
}
|
|
31423
|
+
const cwd = options.cwd ? path57.resolve(options.cwd) : process.cwd();
|
|
31424
|
+
const config = await resolveConfigOrExit(cwd);
|
|
31425
|
+
const pm = detectPackageManager(cwd);
|
|
31426
|
+
if (!options.force) {
|
|
31427
|
+
const confirmed = await p29.confirm({
|
|
31428
|
+
message: `Remove ${removeIntegrationsMode ? "integration" : "preset"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
|
|
31429
|
+
initialValue: false
|
|
31487
31430
|
});
|
|
31488
|
-
|
|
31489
|
-
|
|
31490
|
-
|
|
31491
|
-
return true;
|
|
31492
|
-
}
|
|
31493
|
-
function writeTemplateEntryWithDependencies(name, entry) {
|
|
31494
|
-
const wroteEntry = writeTemplateEntry(name, entry);
|
|
31495
|
-
if (!wroteEntry) {
|
|
31496
|
-
return false;
|
|
31497
|
-
}
|
|
31498
|
-
for (const dependencyName of entry.dependencies ?? []) {
|
|
31499
|
-
writeNamedDependency(dependencyName);
|
|
31431
|
+
if (p29.isCancel(confirmed) || !confirmed) {
|
|
31432
|
+
p29.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
|
|
31433
|
+
process.exit(0);
|
|
31500
31434
|
}
|
|
31501
|
-
return true;
|
|
31502
31435
|
}
|
|
31503
|
-
|
|
31504
|
-
const
|
|
31505
|
-
|
|
31506
|
-
|
|
31507
|
-
|
|
31508
|
-
|
|
31509
|
-
const assetFile = findStaticAssetFile(assetDir, name);
|
|
31510
|
-
if (!assetFile) {
|
|
31511
|
-
return false;
|
|
31512
|
-
}
|
|
31513
|
-
const namespace = config.frameworkConfig.next.namespace;
|
|
31514
|
-
const namespacedAssetFile = applyAdminNamespaceToPath(assetFile, namespace);
|
|
31515
|
-
const destPath = path59.join(admin, "components", assetDirectory, namespacedAssetFile);
|
|
31516
|
-
pendingWrites.push({
|
|
31517
|
-
displayPath: `components/${assetDirectory}/${namespacedAssetFile}`,
|
|
31518
|
-
write: () => {
|
|
31519
|
-
fsExtra.ensureDirSync(path59.dirname(destPath));
|
|
31520
|
-
writeNamespacedFile(path59.join(assetDir, assetFile), destPath, namespace);
|
|
31521
|
-
clack4.log.success(`Updated components/${assetDirectory}/${namespacedAssetFile}`);
|
|
31522
|
-
}
|
|
31436
|
+
if (removeIntegrationsMode) {
|
|
31437
|
+
const result2 = await removeIntegrations({
|
|
31438
|
+
cwd,
|
|
31439
|
+
config,
|
|
31440
|
+
pm,
|
|
31441
|
+
integrationIds
|
|
31523
31442
|
});
|
|
31524
|
-
|
|
31525
|
-
|
|
31526
|
-
|
|
31527
|
-
|
|
31528
|
-
const destSubdir = path59.join(admin, "components", assetDirectory, namespacedName);
|
|
31529
|
-
pendingWrites.push({
|
|
31530
|
-
displayPath: `components/${assetDirectory}/${namespacedName}/ (template files)`,
|
|
31531
|
-
write: () => {
|
|
31532
|
-
fsExtra.ensureDirSync(destSubdir);
|
|
31533
|
-
copyNamespacedDirectory(assetSubdir, destSubdir, namespace);
|
|
31534
|
-
clack4.log.success(
|
|
31535
|
-
`Updated components/${assetDirectory}/${namespacedName}/ (template files)`
|
|
31536
|
-
);
|
|
31537
|
-
}
|
|
31538
|
-
});
|
|
31539
|
-
}
|
|
31540
|
-
}
|
|
31541
|
-
updatedStaticNames.add(key);
|
|
31542
|
-
trackPackageDependencies(name);
|
|
31543
|
-
updated++;
|
|
31544
|
-
if (assetDirectory === "custom") {
|
|
31545
|
-
for (const dependencyName of STATIC_CUSTOM_DEPENDENCIES[name] ?? []) {
|
|
31546
|
-
writeNamedDependency(dependencyName);
|
|
31547
|
-
}
|
|
31443
|
+
writeConfigFile(cwd, result2.config);
|
|
31444
|
+
if (result2.removed.length === 0) {
|
|
31445
|
+
p29.outro("No integrations were removed.");
|
|
31446
|
+
return;
|
|
31548
31447
|
}
|
|
31549
|
-
|
|
31550
|
-
|
|
31551
|
-
function writeTiptapTemplates() {
|
|
31552
|
-
const key = "custom:tiptap";
|
|
31553
|
-
if (updatedStaticNames.has(key)) {
|
|
31554
|
-
return true;
|
|
31448
|
+
if (result2.warnings.length > 0) {
|
|
31449
|
+
p29.note(result2.warnings.join("\n"), "Warnings");
|
|
31555
31450
|
}
|
|
31556
|
-
|
|
31557
|
-
"
|
|
31558
|
-
"react-admin",
|
|
31559
|
-
"custom",
|
|
31560
|
-
"content-editor"
|
|
31451
|
+
p29.outro(
|
|
31452
|
+
`Removed integration${result2.removed.length === 1 ? "" : "s"}: ${result2.removed.join(", ")}`
|
|
31561
31453
|
);
|
|
31562
|
-
|
|
31563
|
-
|
|
31564
|
-
|
|
31565
|
-
|
|
31566
|
-
|
|
31567
|
-
|
|
31568
|
-
|
|
31569
|
-
|
|
31570
|
-
|
|
31454
|
+
return;
|
|
31455
|
+
}
|
|
31456
|
+
const result = await removePresets({
|
|
31457
|
+
cwd,
|
|
31458
|
+
config,
|
|
31459
|
+
pm,
|
|
31460
|
+
presetIds
|
|
31461
|
+
});
|
|
31462
|
+
writeConfigFile(cwd, result.config);
|
|
31463
|
+
if (result.removed.length === 0) {
|
|
31464
|
+
p29.outro("No presets were removed.");
|
|
31465
|
+
return;
|
|
31466
|
+
}
|
|
31467
|
+
if (result.warnings.length > 0) {
|
|
31468
|
+
p29.note(result.warnings.join("\n"), "Warnings");
|
|
31469
|
+
}
|
|
31470
|
+
p29.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
|
|
31471
|
+
}
|
|
31472
|
+
|
|
31473
|
+
// adapters/next/commands/remove-schema.ts
|
|
31474
|
+
import fs43 from "fs";
|
|
31475
|
+
import path58 from "path";
|
|
31476
|
+
import * as clack4 from "@clack/prompts";
|
|
31477
|
+
function removePath2(cwd, filePath) {
|
|
31478
|
+
const fullPath = path58.join(cwd, ...filePath.split("/"));
|
|
31479
|
+
const existed = fs43.existsSync(fullPath);
|
|
31480
|
+
fs43.rmSync(fullPath, { recursive: true, force: true });
|
|
31481
|
+
return existed;
|
|
31482
|
+
}
|
|
31483
|
+
function cleanupEmptyDirs3(cwd, deletedPaths, configPaths) {
|
|
31484
|
+
const stopRoots = /* @__PURE__ */ new Set([
|
|
31485
|
+
path58.join(cwd, ...configPaths.adminDir.split("/")),
|
|
31486
|
+
path58.join(cwd, ...configPaths.adminNavigationDir.split("/")),
|
|
31487
|
+
path58.join(cwd, ...configPaths.adminWebhookEventsDir.split("/")),
|
|
31488
|
+
path58.join(cwd, ...configPaths.pagesDir.split("/"))
|
|
31489
|
+
]);
|
|
31490
|
+
for (const deletedPath of deletedPaths) {
|
|
31491
|
+
let current = path58.dirname(path58.join(cwd, ...deletedPath.split("/")));
|
|
31492
|
+
while (!stopRoots.has(current)) {
|
|
31493
|
+
if (!fs43.existsSync(current)) {
|
|
31494
|
+
current = path58.dirname(current);
|
|
31571
31495
|
continue;
|
|
31572
31496
|
}
|
|
31573
|
-
|
|
31574
|
-
|
|
31575
|
-
|
|
31576
|
-
}
|
|
31577
|
-
|
|
31578
|
-
|
|
31579
|
-
return false;
|
|
31580
|
-
}
|
|
31581
|
-
pendingWrites.push({
|
|
31582
|
-
displayPath: "components/custom/content-editor/tiptap-*/ (template files)",
|
|
31583
|
-
write: () => {
|
|
31584
|
-
for (const { srcDir, destDir } of dirsToCopy) {
|
|
31585
|
-
fsExtra.ensureDirSync(destDir);
|
|
31586
|
-
copyNamespacedDirectory(srcDir, destDir, namespace);
|
|
31587
|
-
}
|
|
31588
|
-
clack4.log.success("Updated components/custom/content-editor/tiptap-*/ (template files)");
|
|
31589
|
-
removeLegacyDirectory(path59.join(admin, "components", "custom", "tiptap"));
|
|
31590
|
-
}
|
|
31591
|
-
});
|
|
31592
|
-
updatedStaticNames.add(key);
|
|
31593
|
-
trackPackageDependencies("tiptap");
|
|
31594
|
-
updated++;
|
|
31595
|
-
for (const dependencyName of TIPTAP_TEMPLATE_DEPENDENCIES) {
|
|
31596
|
-
writeNamedDependency(dependencyName);
|
|
31597
|
-
}
|
|
31598
|
-
return true;
|
|
31599
|
-
}
|
|
31600
|
-
function writeNamedDependency(name) {
|
|
31601
|
-
const entry = TEMPLATE_REGISTRY[name];
|
|
31602
|
-
if (entry) {
|
|
31603
|
-
writeTemplateEntryWithDependencies(name, entry);
|
|
31604
|
-
return;
|
|
31497
|
+
const entries = fs43.readdirSync(current);
|
|
31498
|
+
if (entries.length > 0) {
|
|
31499
|
+
break;
|
|
31500
|
+
}
|
|
31501
|
+
fs43.rmdirSync(current);
|
|
31502
|
+
current = path58.dirname(current);
|
|
31605
31503
|
}
|
|
31606
|
-
|
|
31607
|
-
|
|
31504
|
+
}
|
|
31505
|
+
}
|
|
31506
|
+
function resolveSchemaOwnerForRemoval(cwd, schemaName) {
|
|
31507
|
+
const explicitOwner = getSchemaOwner(cwd, schemaName);
|
|
31508
|
+
if (explicitOwner) {
|
|
31509
|
+
return explicitOwner;
|
|
31510
|
+
}
|
|
31511
|
+
if (schemaName === "settings") {
|
|
31512
|
+
return "core";
|
|
31513
|
+
}
|
|
31514
|
+
return "user";
|
|
31515
|
+
}
|
|
31516
|
+
async function runRemoveSchemaCommand(schemaName, options) {
|
|
31517
|
+
const owner = resolveSchemaOwnerForRemoval(
|
|
31518
|
+
options.cwd ? path58.resolve(options.cwd) : process.cwd(),
|
|
31519
|
+
schemaName
|
|
31520
|
+
);
|
|
31521
|
+
if (owner === "core") {
|
|
31522
|
+
clack4.log.error(
|
|
31523
|
+
`"${schemaName}" is a core Admin module and cannot be removed with remove-schema.`
|
|
31524
|
+
);
|
|
31525
|
+
process.exit(1);
|
|
31526
|
+
}
|
|
31527
|
+
if (owner.startsWith("preset:")) {
|
|
31528
|
+
clack4.log.error(`"${schemaName}" is owned by ${owner}. Remove the owning preset instead.`);
|
|
31529
|
+
process.exit(1);
|
|
31530
|
+
}
|
|
31531
|
+
const cwd = options.cwd ? path58.resolve(options.cwd) : process.cwd();
|
|
31532
|
+
const config = await resolveConfigOrExit(cwd);
|
|
31533
|
+
const paths = resolveProjectPaths(config);
|
|
31534
|
+
const manifest = loadManifest(cwd, schemaName);
|
|
31535
|
+
if (!snapshotRootExists(cwd)) {
|
|
31536
|
+
clack4.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
|
|
31537
|
+
process.exit(1);
|
|
31538
|
+
}
|
|
31539
|
+
if (!manifest) {
|
|
31540
|
+
clack4.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
|
|
31541
|
+
process.exit(1);
|
|
31542
|
+
}
|
|
31543
|
+
if (!options.force) {
|
|
31544
|
+
if (!isInteractiveSession()) {
|
|
31545
|
+
clack4.log.error(
|
|
31546
|
+
`Removing generated files for ${schemaName} needs confirmation. Re-run with --force.`
|
|
31547
|
+
);
|
|
31548
|
+
process.exit(1);
|
|
31608
31549
|
}
|
|
31609
|
-
|
|
31550
|
+
const confirmed = await clack4.confirm({
|
|
31551
|
+
message: `Remove generated files for ${schemaName}?`,
|
|
31552
|
+
initialValue: false
|
|
31553
|
+
});
|
|
31554
|
+
if (clack4.isCancel(confirmed) || !confirmed) {
|
|
31555
|
+
clack4.cancel("Cancelled.");
|
|
31610
31556
|
return;
|
|
31611
31557
|
}
|
|
31612
|
-
if (name === "tiptap") {
|
|
31613
|
-
writeTiptapTemplates();
|
|
31614
|
-
}
|
|
31615
31558
|
}
|
|
31616
|
-
|
|
31617
|
-
|
|
31618
|
-
|
|
31619
|
-
|
|
31620
|
-
continue;
|
|
31621
|
-
}
|
|
31622
|
-
if (writeStaticAssetEntry("ui", name)) {
|
|
31623
|
-
continue;
|
|
31559
|
+
const deletedPaths = [];
|
|
31560
|
+
for (const file of [...manifest.files.map((entry) => entry.path), ...manifest.skipped]) {
|
|
31561
|
+
if (removePath2(cwd, file)) {
|
|
31562
|
+
deletedPaths.push(file);
|
|
31624
31563
|
}
|
|
31625
|
-
|
|
31626
|
-
|
|
31564
|
+
}
|
|
31565
|
+
const loaded = (() => {
|
|
31566
|
+
try {
|
|
31567
|
+
return loadSchema(path58.join(cwd, ...paths.schemasDir.split("/")), schemaName);
|
|
31568
|
+
} catch {
|
|
31569
|
+
return null;
|
|
31627
31570
|
}
|
|
31628
|
-
|
|
31629
|
-
|
|
31630
|
-
|
|
31631
|
-
|
|
31632
|
-
}
|
|
31633
|
-
continue;
|
|
31571
|
+
})();
|
|
31572
|
+
const kebabName = toKebabCase(schemaName);
|
|
31573
|
+
if (loaded?.type === "form") {
|
|
31574
|
+
if (removePath2(cwd, `${paths.adminActionsDir}/${schemaName}`)) {
|
|
31575
|
+
deletedPaths.push(`${paths.adminActionsDir}/${schemaName}`);
|
|
31634
31576
|
}
|
|
31635
|
-
|
|
31636
|
-
|
|
31637
|
-
}
|
|
31638
|
-
if (pendingWrites.length > 0) {
|
|
31639
|
-
const displayPaths = pendingWrites.map((entry) => entry.displayPath);
|
|
31640
|
-
const preview = displayPaths.slice(0, MAX_OVERWRITE_PREVIEW_ROWS);
|
|
31641
|
-
if (displayPaths.length > preview.length) {
|
|
31642
|
-
preview.push(`\u2026 and ${displayPaths.length - preview.length} more`);
|
|
31577
|
+
if (removePath2(cwd, `${paths.pagesDir}/forms/${kebabName}`)) {
|
|
31578
|
+
deletedPaths.push(`${paths.pagesDir}/forms/${kebabName}`);
|
|
31643
31579
|
}
|
|
31644
|
-
|
|
31645
|
-
|
|
31646
|
-
|
|
31647
|
-
);
|
|
31648
|
-
if (!options.yes) {
|
|
31649
|
-
if (!isInteractiveSession()) {
|
|
31650
|
-
clack4.log.error(
|
|
31651
|
-
`Overwriting ${displayPaths.length} file${displayPaths.length === 1 ? "" : "s"} needs confirmation. Re-run with --yes.`
|
|
31652
|
-
);
|
|
31653
|
-
process.exit(1);
|
|
31654
|
-
}
|
|
31655
|
-
const proceed = await clack4.confirm({
|
|
31656
|
-
message: "Overwrite these files with the latest templates?",
|
|
31657
|
-
initialValue: true
|
|
31658
|
-
});
|
|
31659
|
-
if (clack4.isCancel(proceed) || !proceed) {
|
|
31660
|
-
clack4.cancel("Update cancelled.");
|
|
31661
|
-
process.exit(0);
|
|
31662
|
-
}
|
|
31580
|
+
} else {
|
|
31581
|
+
if (removePath2(cwd, `${paths.adminActionsDir}/${schemaName}`)) {
|
|
31582
|
+
deletedPaths.push(`${paths.adminActionsDir}/${schemaName}`);
|
|
31663
31583
|
}
|
|
31664
|
-
|
|
31665
|
-
|
|
31584
|
+
if (removePath2(cwd, `${paths.pagesDir}/${schemaName}`)) {
|
|
31585
|
+
deletedPaths.push(`${paths.pagesDir}/${schemaName}`);
|
|
31666
31586
|
}
|
|
31667
31587
|
}
|
|
31668
|
-
|
|
31669
|
-
|
|
31670
|
-
|
|
31671
|
-
|
|
31672
|
-
(dependency) => !hasDeclaredPackage2(projectPackageJson, dependency)
|
|
31673
|
-
);
|
|
31674
|
-
if (missingPackageDependencies.length > 0) {
|
|
31675
|
-
clack4.log.warn(
|
|
31676
|
-
`Updated components require package dependencies that are not declared: ${missingPackageDependencies.join(", ")}. Run 'pnpm betterstart update-deps' before building.`
|
|
31677
|
-
);
|
|
31588
|
+
cleanupEmptyDirs3(cwd, deletedPaths, paths);
|
|
31589
|
+
deleteSnapshot(cwd, schemaName);
|
|
31590
|
+
if (hasTombstone(cwd, schemaName)) {
|
|
31591
|
+
clearTombstone(cwd, schemaName);
|
|
31678
31592
|
}
|
|
31679
|
-
|
|
31680
|
-
|
|
31593
|
+
writeTombstone(cwd, schemaName);
|
|
31594
|
+
await applyGeneratedFiles({
|
|
31595
|
+
cwd,
|
|
31596
|
+
config,
|
|
31597
|
+
scope: BARREL_SCOPE,
|
|
31598
|
+
schemaJson: { name: BARREL_SCOPE },
|
|
31599
|
+
generatedFiles: renderBarrelFiles(cwd, config),
|
|
31600
|
+
force: false,
|
|
31601
|
+
interactive: false
|
|
31602
|
+
});
|
|
31603
|
+
clack4.log.info(
|
|
31604
|
+
`Tombstone written: .betterstart/snapshots/_removed/${schemaName}
|
|
31605
|
+
Schema JSON preserved.`
|
|
31681
31606
|
);
|
|
31607
|
+
clack4.outro(`Removed generated files for ${schemaName}`);
|
|
31682
31608
|
}
|
|
31683
|
-
|
|
31684
|
-
|
|
31685
|
-
|
|
31609
|
+
|
|
31610
|
+
// adapters/next/commands/uninstall.ts
|
|
31611
|
+
import fs45 from "fs";
|
|
31612
|
+
import path59 from "path";
|
|
31613
|
+
import * as p30 from "@clack/prompts";
|
|
31614
|
+
import pc11 from "picocolors";
|
|
31615
|
+
|
|
31616
|
+
// adapters/next/commands/uninstall-cleaners.ts
|
|
31617
|
+
import fs44 from "fs";
|
|
31618
|
+
function stripJsonComments2(input) {
|
|
31619
|
+
let result = "";
|
|
31620
|
+
let i = 0;
|
|
31621
|
+
while (i < input.length) {
|
|
31622
|
+
if (input[i] === '"') {
|
|
31623
|
+
let j = i + 1;
|
|
31624
|
+
while (j < input.length) {
|
|
31625
|
+
if (input[j] === "\\") {
|
|
31626
|
+
j += 2;
|
|
31627
|
+
continue;
|
|
31628
|
+
}
|
|
31629
|
+
if (input[j] === '"') {
|
|
31630
|
+
j++;
|
|
31631
|
+
break;
|
|
31632
|
+
}
|
|
31633
|
+
j++;
|
|
31634
|
+
}
|
|
31635
|
+
result += input.slice(i, j);
|
|
31636
|
+
i = j;
|
|
31637
|
+
} else if (input[i] === "/" && input[i + 1] === "/") {
|
|
31638
|
+
const nl = input.indexOf("\n", i);
|
|
31639
|
+
i = nl === -1 ? input.length : nl;
|
|
31640
|
+
} else if (input[i] === "/" && input[i + 1] === "*") {
|
|
31641
|
+
const end = input.indexOf("*/", i + 2);
|
|
31642
|
+
i = end === -1 ? input.length : end + 2;
|
|
31643
|
+
} else {
|
|
31644
|
+
result += input[i];
|
|
31645
|
+
i++;
|
|
31646
|
+
}
|
|
31686
31647
|
}
|
|
31648
|
+
return result;
|
|
31687
31649
|
}
|
|
31688
|
-
function
|
|
31689
|
-
if (
|
|
31690
|
-
|
|
31691
|
-
|
|
31650
|
+
function cleanTsconfig(tsconfigPath, aliasRoot = "@admin") {
|
|
31651
|
+
if (!fs44.existsSync(tsconfigPath)) return [];
|
|
31652
|
+
const raw = fs44.readFileSync(tsconfigPath, "utf-8");
|
|
31653
|
+
const stripped = stripJsonComments2(raw).replace(/,\s*([\]}])/g, "$1");
|
|
31654
|
+
let tsconfig;
|
|
31655
|
+
try {
|
|
31656
|
+
tsconfig = JSON.parse(stripped);
|
|
31657
|
+
} catch {
|
|
31658
|
+
return [];
|
|
31692
31659
|
}
|
|
31693
|
-
|
|
31694
|
-
|
|
31660
|
+
const compilerOptions = tsconfig.compilerOptions ?? {};
|
|
31661
|
+
const paths = compilerOptions.paths ?? {};
|
|
31662
|
+
const removed = [];
|
|
31663
|
+
for (const key of Object.keys(paths)) {
|
|
31664
|
+
if (key.startsWith("@admin/") || key === "@admin/*" || key.startsWith(`${aliasRoot}/`) || key === `${aliasRoot}/*`) {
|
|
31665
|
+
removed.push(key);
|
|
31666
|
+
delete paths[key];
|
|
31667
|
+
}
|
|
31695
31668
|
}
|
|
31696
|
-
if (
|
|
31697
|
-
|
|
31698
|
-
|
|
31669
|
+
if (removed.length === 0) return [];
|
|
31670
|
+
if (Object.keys(paths).length === 0) {
|
|
31671
|
+
compilerOptions.paths = void 0;
|
|
31672
|
+
} else {
|
|
31673
|
+
compilerOptions.paths = paths;
|
|
31699
31674
|
}
|
|
31700
|
-
|
|
31701
|
-
|
|
31702
|
-
|
|
31675
|
+
tsconfig.compilerOptions = compilerOptions;
|
|
31676
|
+
fs44.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
31677
|
+
`, "utf-8");
|
|
31678
|
+
return removed;
|
|
31679
|
+
}
|
|
31680
|
+
function cleanCss(cssPath, namespace = "admin") {
|
|
31681
|
+
if (!fs44.existsSync(cssPath)) return [];
|
|
31682
|
+
const content = fs44.readFileSync(cssPath, "utf-8");
|
|
31683
|
+
const lines = content.split("\n");
|
|
31684
|
+
const sourcePattern = new RegExp(`^@source\\s+"[^"]*(?:admin|${namespace})[^"]*";\\s*$`);
|
|
31685
|
+
const removed = [];
|
|
31686
|
+
const kept = [];
|
|
31687
|
+
for (const line of lines) {
|
|
31688
|
+
if (sourcePattern.test(line)) {
|
|
31689
|
+
removed.push(line.trim());
|
|
31690
|
+
} else {
|
|
31691
|
+
kept.push(line);
|
|
31692
|
+
}
|
|
31703
31693
|
}
|
|
31704
|
-
if (
|
|
31705
|
-
|
|
31706
|
-
|
|
31694
|
+
if (removed.length === 0) return [];
|
|
31695
|
+
const cleaned = kept.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
31696
|
+
fs44.writeFileSync(cssPath, cleaned, "utf-8");
|
|
31697
|
+
return removed;
|
|
31698
|
+
}
|
|
31699
|
+
function cleanEnvFile(envPath) {
|
|
31700
|
+
if (!fs44.existsSync(envPath)) return [];
|
|
31701
|
+
const content = fs44.readFileSync(envPath, "utf-8");
|
|
31702
|
+
const lines = content.split("\n");
|
|
31703
|
+
const removed = [];
|
|
31704
|
+
const kept = [];
|
|
31705
|
+
const headerPattern = /^# =+$/;
|
|
31706
|
+
const headerTextPattern = /^# BetterStart Admin$/;
|
|
31707
|
+
for (let i = 0; i < lines.length; i++) {
|
|
31708
|
+
const line = lines[i];
|
|
31709
|
+
const trimmed = line.trim();
|
|
31710
|
+
if (trimmed.match(/^BETTERSTART_\w+=/)) {
|
|
31711
|
+
const key = trimmed.split("=")[0];
|
|
31712
|
+
removed.push(key);
|
|
31713
|
+
continue;
|
|
31714
|
+
}
|
|
31715
|
+
if (headerPattern.test(trimmed)) {
|
|
31716
|
+
const next = lines[i + 1]?.trim();
|
|
31717
|
+
const afterNext = lines[i + 2]?.trim();
|
|
31718
|
+
if (next && headerTextPattern.test(next) && afterNext && headerPattern.test(afterNext)) {
|
|
31719
|
+
i += 2;
|
|
31720
|
+
continue;
|
|
31721
|
+
}
|
|
31722
|
+
}
|
|
31723
|
+
if (trimmed.startsWith("#") && !headerPattern.test(trimmed)) {
|
|
31724
|
+
const nextNonEmpty = findNextNonEmptyLine(lines, i + 1);
|
|
31725
|
+
if (nextNonEmpty?.match(/^BETTERSTART_\w+=/)) {
|
|
31726
|
+
continue;
|
|
31727
|
+
}
|
|
31728
|
+
}
|
|
31729
|
+
kept.push(line);
|
|
31730
|
+
}
|
|
31731
|
+
if (removed.length === 0) return [];
|
|
31732
|
+
const result = kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
31733
|
+
if (result === "") {
|
|
31734
|
+
fs44.unlinkSync(envPath);
|
|
31735
|
+
} else {
|
|
31736
|
+
fs44.writeFileSync(envPath, `${result}
|
|
31737
|
+
`, "utf-8");
|
|
31707
31738
|
}
|
|
31739
|
+
return removed;
|
|
31708
31740
|
}
|
|
31709
|
-
function
|
|
31710
|
-
|
|
31711
|
-
|
|
31712
|
-
|
|
31713
|
-
const parts = value.split(",").map((part) => part.trim().toLowerCase()).filter(Boolean);
|
|
31714
|
-
if (parts.length !== 1 || parts[0] !== "theme") {
|
|
31715
|
-
clack4.cancel(
|
|
31716
|
-
"Admin-only shadcn preset updates currently support --only theme. Omit --only to apply the full preset."
|
|
31717
|
-
);
|
|
31718
|
-
process.exit(1);
|
|
31741
|
+
function findNextNonEmptyLine(lines, startIndex) {
|
|
31742
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
31743
|
+
const trimmed = lines[i].trim();
|
|
31744
|
+
if (trimmed !== "") return trimmed;
|
|
31719
31745
|
}
|
|
31720
|
-
return
|
|
31746
|
+
return null;
|
|
31721
31747
|
}
|
|
31722
|
-
|
|
31723
|
-
|
|
31724
|
-
|
|
31725
|
-
|
|
31726
|
-
|
|
31727
|
-
|
|
31728
|
-
|
|
31729
|
-
|
|
31730
|
-
|
|
31731
|
-
|
|
31732
|
-
|
|
31733
|
-
|
|
31734
|
-
shadcnBackupPath,
|
|
31735
|
-
path59.join(cwd, config.paths.admin, "lib", "utils.ts"),
|
|
31736
|
-
...getHostProjectFilesToRestore(cwd)
|
|
31748
|
+
|
|
31749
|
+
// adapters/next/commands/uninstall.ts
|
|
31750
|
+
function findMainCss2(cwd) {
|
|
31751
|
+
const candidates = [
|
|
31752
|
+
"src/app/globals.css",
|
|
31753
|
+
"app/globals.css",
|
|
31754
|
+
"src/app/global.css",
|
|
31755
|
+
"app/global.css",
|
|
31756
|
+
"src/app/app.css",
|
|
31757
|
+
"app/app.css",
|
|
31758
|
+
"src/globals.css",
|
|
31759
|
+
"globals.css"
|
|
31737
31760
|
];
|
|
31738
|
-
|
|
31739
|
-
|
|
31740
|
-
|
|
31741
|
-
}
|
|
31742
|
-
if (!fs45.existsSync(adminGlobalsPath)) {
|
|
31743
|
-
clack4.cancel(
|
|
31744
|
-
`Admin globals file not found at ${path59.relative(cwd, adminGlobalsPath)}. Run 'betterstart update admin-globals' first.`
|
|
31745
|
-
);
|
|
31746
|
-
process.exit(1);
|
|
31761
|
+
for (const candidate of candidates) {
|
|
31762
|
+
const filePath = path59.join(cwd, candidate);
|
|
31763
|
+
if (fs45.existsSync(filePath)) return filePath;
|
|
31747
31764
|
}
|
|
31748
|
-
|
|
31749
|
-
|
|
31750
|
-
|
|
31751
|
-
|
|
31752
|
-
}));
|
|
31753
|
-
clack4.intro("BetterStart Shadcn Preset");
|
|
31754
|
-
clack4.log.info(`Applying preset to ${path59.join(config.paths.admin, "components/ui")}`);
|
|
31755
|
-
let failed = false;
|
|
31765
|
+
return void 0;
|
|
31766
|
+
}
|
|
31767
|
+
function isCLICreatedBiome(biomePath) {
|
|
31768
|
+
if (!fs45.existsSync(biomePath)) return false;
|
|
31756
31769
|
try {
|
|
31757
|
-
fs45.
|
|
31758
|
-
|
|
31759
|
-
`${JSON.stringify(createAdminShadcnComponentsJson(config), null, 2)}
|
|
31760
|
-
`,
|
|
31761
|
-
"utf-8"
|
|
31762
|
-
);
|
|
31763
|
-
const args = ["apply", "--preset", preset, "--cwd", cwd, "--yes"];
|
|
31764
|
-
if (only) {
|
|
31765
|
-
args.push("--only", only);
|
|
31766
|
-
}
|
|
31767
|
-
execFileSync5(shadcnBin, args, { cwd, stdio: "inherit" });
|
|
31770
|
+
const content = JSON.parse(fs45.readFileSync(biomePath, "utf-8"));
|
|
31771
|
+
return content.$schema?.includes("biomejs.dev") && content.formatter?.indentStyle === "space" && content.javascript?.formatter?.quoteStyle === "single" && Array.isArray(content.files?.ignore) && content.files.ignore.includes(".next");
|
|
31768
31772
|
} catch {
|
|
31769
|
-
|
|
31770
|
-
}
|
|
31771
|
-
|
|
31772
|
-
|
|
31773
|
+
return false;
|
|
31774
|
+
}
|
|
31775
|
+
}
|
|
31776
|
+
function buildUninstallPlan(cwd, namespaceValue) {
|
|
31777
|
+
const steps = [];
|
|
31778
|
+
const namespace = resolveAdminNamespace(namespaceValue);
|
|
31779
|
+
const hasSrc = fs45.existsSync(path59.join(cwd, "src"));
|
|
31780
|
+
const appBase = hasSrc ? "src/app" : "app";
|
|
31781
|
+
const dirs = [];
|
|
31782
|
+
const adminDir = path59.join(cwd, namespace.segment);
|
|
31783
|
+
const legacyAdminDir = path59.join(cwd, "admin");
|
|
31784
|
+
const adminRouteGroup = path59.join(cwd, appBase, namespace.routeGroup);
|
|
31785
|
+
const legacyAdminRouteGroup = path59.join(cwd, appBase, "(admin)");
|
|
31786
|
+
if (fs45.existsSync(adminDir)) dirs.push(`${namespace.segment}/`);
|
|
31787
|
+
if (namespace.segment !== "admin" && fs45.existsSync(legacyAdminDir)) dirs.push("admin/");
|
|
31788
|
+
if (fs45.existsSync(adminRouteGroup)) dirs.push(`${appBase}/${namespace.routeGroup}/`);
|
|
31789
|
+
if (namespace.segment !== "admin" && fs45.existsSync(legacyAdminRouteGroup))
|
|
31790
|
+
dirs.push(`${appBase}/(admin)/`);
|
|
31791
|
+
if (dirs.length > 0) {
|
|
31792
|
+
steps.push({
|
|
31793
|
+
label: "Admin directories",
|
|
31794
|
+
items: dirs,
|
|
31795
|
+
count: dirs.length,
|
|
31796
|
+
unit: dirs.length === 1 ? "directory" : "directories",
|
|
31797
|
+
execute() {
|
|
31798
|
+
if (fs45.existsSync(adminDir)) fs45.rmSync(adminDir, { recursive: true, force: true });
|
|
31799
|
+
if (fs45.existsSync(legacyAdminDir))
|
|
31800
|
+
fs45.rmSync(legacyAdminDir, { recursive: true, force: true });
|
|
31801
|
+
if (fs45.existsSync(adminRouteGroup)) {
|
|
31802
|
+
fs45.rmSync(adminRouteGroup, { recursive: true, force: true });
|
|
31803
|
+
}
|
|
31804
|
+
if (fs45.existsSync(legacyAdminRouteGroup)) {
|
|
31805
|
+
fs45.rmSync(legacyAdminRouteGroup, { recursive: true, force: true });
|
|
31806
|
+
}
|
|
31807
|
+
}
|
|
31808
|
+
});
|
|
31809
|
+
}
|
|
31810
|
+
const configFiles = [];
|
|
31811
|
+
const configPaths = [];
|
|
31812
|
+
const candidates = [
|
|
31813
|
+
[CONFIG_FILE_NAME, path59.join(cwd, CONFIG_FILE_NAME)],
|
|
31814
|
+
["drizzle.config.ts", path59.join(cwd, "drizzle.config.ts")],
|
|
31815
|
+
["ADMIN.md", path59.join(cwd, "ADMIN.md")]
|
|
31816
|
+
];
|
|
31817
|
+
for (const [label, fullPath] of candidates) {
|
|
31818
|
+
if (fs45.existsSync(fullPath)) {
|
|
31819
|
+
configFiles.push(label);
|
|
31820
|
+
configPaths.push(fullPath);
|
|
31773
31821
|
}
|
|
31774
31822
|
}
|
|
31775
|
-
|
|
31776
|
-
|
|
31777
|
-
|
|
31823
|
+
const biomePath = path59.join(cwd, "biome.json");
|
|
31824
|
+
if (isCLICreatedBiome(biomePath)) {
|
|
31825
|
+
configFiles.push("biome.json (CLI-created)");
|
|
31826
|
+
configPaths.push(biomePath);
|
|
31778
31827
|
}
|
|
31779
|
-
|
|
31780
|
-
|
|
31781
|
-
|
|
31782
|
-
|
|
31783
|
-
|
|
31784
|
-
|
|
31785
|
-
|
|
31786
|
-
|
|
31787
|
-
|
|
31788
|
-
|
|
31789
|
-
|
|
31790
|
-
|
|
31791
|
-
|
|
31792
|
-
|
|
31793
|
-
|
|
31794
|
-
|
|
31795
|
-
|
|
31796
|
-
|
|
31797
|
-
|
|
31798
|
-
|
|
31799
|
-
|
|
31800
|
-
|
|
31801
|
-
|
|
31802
|
-
|
|
31803
|
-
|
|
31804
|
-
|
|
31828
|
+
if (configFiles.length > 0) {
|
|
31829
|
+
steps.push({
|
|
31830
|
+
label: "Config files",
|
|
31831
|
+
items: configFiles,
|
|
31832
|
+
count: configFiles.length,
|
|
31833
|
+
unit: configFiles.length === 1 ? "file" : "files",
|
|
31834
|
+
execute() {
|
|
31835
|
+
for (const p32 of configPaths) {
|
|
31836
|
+
if (fs45.existsSync(p32)) fs45.unlinkSync(p32);
|
|
31837
|
+
}
|
|
31838
|
+
}
|
|
31839
|
+
});
|
|
31840
|
+
}
|
|
31841
|
+
const tsconfigPath = path59.join(cwd, "tsconfig.json");
|
|
31842
|
+
if (fs45.existsSync(tsconfigPath)) {
|
|
31843
|
+
const content = fs45.readFileSync(tsconfigPath, "utf-8");
|
|
31844
|
+
const aliasMatches = [
|
|
31845
|
+
...content.match(/"@admin\//g) ?? [],
|
|
31846
|
+
...content.match(new RegExp(`"${namespace.alias}/`, "g")) ?? []
|
|
31847
|
+
];
|
|
31848
|
+
if (aliasMatches && aliasMatches.length > 0) {
|
|
31849
|
+
const aliasCount = aliasMatches.length;
|
|
31850
|
+
steps.push({
|
|
31851
|
+
label: "tsconfig.json path aliases",
|
|
31852
|
+
items: [`${namespace.alias}/* aliases in tsconfig.json`],
|
|
31853
|
+
count: aliasCount,
|
|
31854
|
+
unit: aliasCount === 1 ? "alias" : "aliases",
|
|
31855
|
+
execute() {
|
|
31856
|
+
cleanTsconfig(tsconfigPath, namespace.alias);
|
|
31857
|
+
}
|
|
31858
|
+
});
|
|
31805
31859
|
}
|
|
31806
|
-
}
|
|
31807
|
-
|
|
31808
|
-
|
|
31809
|
-
|
|
31810
|
-
|
|
31811
|
-
|
|
31812
|
-
const binName = process.platform === "win32" ? "shadcn.cmd" : "shadcn";
|
|
31813
|
-
const shadcnBin = path59.join(cwd, "node_modules", ".bin", binName);
|
|
31814
|
-
if (!fs45.existsSync(shadcnBin)) {
|
|
31815
|
-
clack4.cancel(
|
|
31816
|
-
`shadcn is not installed in this project. Run 'betterstart update-deps' and try again.`
|
|
31860
|
+
}
|
|
31861
|
+
const cssFile = findMainCss2(cwd);
|
|
31862
|
+
if (cssFile) {
|
|
31863
|
+
const cssContent = fs45.readFileSync(cssFile, "utf-8");
|
|
31864
|
+
const sourceLines = cssContent.split("\n").filter(
|
|
31865
|
+
(l) => new RegExp(`^@source\\s+"[^"]*(?:admin|${namespace.segment})[^"]*";\\s*$`).test(l)
|
|
31817
31866
|
);
|
|
31818
|
-
|
|
31867
|
+
if (sourceLines.length > 0) {
|
|
31868
|
+
const relCss = path59.relative(cwd, cssFile);
|
|
31869
|
+
steps.push({
|
|
31870
|
+
label: `CSS @source lines (${relCss})`,
|
|
31871
|
+
items: [`@source lines in ${relCss}`],
|
|
31872
|
+
count: sourceLines.length,
|
|
31873
|
+
unit: sourceLines.length === 1 ? "line" : "lines",
|
|
31874
|
+
execute() {
|
|
31875
|
+
cleanCss(cssFile, namespace.segment);
|
|
31876
|
+
}
|
|
31877
|
+
});
|
|
31878
|
+
}
|
|
31819
31879
|
}
|
|
31820
|
-
|
|
31821
|
-
|
|
31822
|
-
|
|
31823
|
-
|
|
31824
|
-
|
|
31825
|
-
|
|
31826
|
-
|
|
31827
|
-
|
|
31828
|
-
|
|
31829
|
-
|
|
31830
|
-
|
|
31831
|
-
|
|
31832
|
-
|
|
31833
|
-
|
|
31834
|
-
|
|
31835
|
-
return hostRelativePaths.map((relativePath) => path59.join(cwd, relativePath));
|
|
31836
|
-
}
|
|
31837
|
-
function snapshotFile(filePath) {
|
|
31838
|
-
if (!fs45.existsSync(filePath)) {
|
|
31839
|
-
return { existed: false };
|
|
31880
|
+
const envPath = path59.join(cwd, ".env.local");
|
|
31881
|
+
if (fs45.existsSync(envPath)) {
|
|
31882
|
+
const envContent = fs45.readFileSync(envPath, "utf-8");
|
|
31883
|
+
const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
|
|
31884
|
+
if (bsVars.length > 0) {
|
|
31885
|
+
steps.push({
|
|
31886
|
+
label: ".env.local variables",
|
|
31887
|
+
items: ["BETTERSTART_* vars in .env.local"],
|
|
31888
|
+
count: bsVars.length,
|
|
31889
|
+
unit: bsVars.length === 1 ? "variable" : "variables",
|
|
31890
|
+
execute() {
|
|
31891
|
+
cleanEnvFile(envPath);
|
|
31892
|
+
}
|
|
31893
|
+
});
|
|
31894
|
+
}
|
|
31840
31895
|
}
|
|
31841
|
-
return
|
|
31896
|
+
return steps;
|
|
31842
31897
|
}
|
|
31843
|
-
function
|
|
31844
|
-
|
|
31845
|
-
|
|
31898
|
+
async function runUninstallCommand(options) {
|
|
31899
|
+
const cwd = options.cwd ? path59.resolve(options.cwd) : process.cwd();
|
|
31900
|
+
p30.intro(pc11.bgRed(pc11.white(" BetterStart Uninstall ")));
|
|
31901
|
+
let namespace = DEFAULT_ADMIN_NAMESPACE;
|
|
31902
|
+
try {
|
|
31903
|
+
const config = await resolveConfig(cwd);
|
|
31904
|
+
namespace = config.frameworkConfig.next.namespace;
|
|
31905
|
+
} catch {
|
|
31906
|
+
}
|
|
31907
|
+
const steps = buildUninstallPlan(cwd, namespace);
|
|
31908
|
+
if (steps.length === 0) {
|
|
31909
|
+
p30.log.success(`${pc11.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
|
|
31910
|
+
p30.outro("Project already clean");
|
|
31846
31911
|
return;
|
|
31847
31912
|
}
|
|
31848
|
-
|
|
31849
|
-
|
|
31913
|
+
const planLines = steps.map((step) => {
|
|
31914
|
+
const names = step.items.join(" ");
|
|
31915
|
+
const countLabel = pc11.dim(`${step.count} ${step.unit}`);
|
|
31916
|
+
return `${pc11.red("\u2717")} ${names} ${countLabel}`;
|
|
31917
|
+
});
|
|
31918
|
+
p30.note(planLines.join("\n"), "Uninstall plan");
|
|
31919
|
+
if (!options.force) {
|
|
31920
|
+
const confirmed = await p30.confirm({
|
|
31921
|
+
message: "Proceed with uninstall?",
|
|
31922
|
+
initialValue: false
|
|
31923
|
+
});
|
|
31924
|
+
if (p30.isCancel(confirmed) || !confirmed) {
|
|
31925
|
+
p30.cancel("Uninstall cancelled.");
|
|
31926
|
+
process.exit(0);
|
|
31927
|
+
}
|
|
31928
|
+
}
|
|
31929
|
+
const s = spinner2();
|
|
31930
|
+
s.start(steps[0].label);
|
|
31931
|
+
for (const step of steps) {
|
|
31932
|
+
s.message(step.label);
|
|
31933
|
+
step.execute();
|
|
31850
31934
|
}
|
|
31935
|
+
const parts = steps.map((step) => `${step.count} ${step.unit}`);
|
|
31936
|
+
s.stop(`Removed ${parts.join(", ")}`);
|
|
31937
|
+
p30.note(pc11.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
|
|
31938
|
+
p30.outro("Uninstall complete");
|
|
31851
31939
|
}
|
|
31852
31940
|
|
|
31853
31941
|
// adapters/next/commands/update-deps.ts
|
|
@@ -31913,6 +32001,7 @@ async function runUpdateStylesCommand(options) {
|
|
|
31913
32001
|
|
|
31914
32002
|
// adapters/next/commands-runtime.ts
|
|
31915
32003
|
var nextCommandRuntime = {
|
|
32004
|
+
listComponentChoices,
|
|
31916
32005
|
listInstallableChoices,
|
|
31917
32006
|
listSchemaChoices,
|
|
31918
32007
|
runAdd: runAddCommand,
|