betterstart-cli 0.0.99 → 0.0.100
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/api/upload-route.ts +2 -1
- package/dist/assets/adapters/next/templates/init/components/layouts/admin-settings-sidebar.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/components/layouts/admin-sign-out.tsx +27 -8
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/components/shared/delete-dialog.tsx +3 -2
- package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-version-restore-dialog.tsx +4 -3
- package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-button.tsx +5 -2
- package/dist/assets/adapters/next/templates/init/components/shared/media/edit-media-dialog-content.tsx +11 -5
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-dialog.tsx +6 -4
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-delete-drawer.tsx +12 -8
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-empty-state.tsx +6 -5
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-grid-pagination.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-url-importer.tsx +5 -3
- package/dist/assets/adapters/next/templates/init/components/shared/search-input.tsx +2 -0
- package/dist/assets/adapters/next/templates/init/components/shared/sort-order-dialog.tsx +12 -7
- package/dist/assets/adapters/next/templates/init/hooks/use-entity-versions.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/forms/upsert-form-settings.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/create-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media-bulk.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/change-own-password.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +2 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/users/change-user-password.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/create-user.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/delete-user.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/create-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/delete-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/get-webhook-secret.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/regenerate-webhook-secret.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/send-test-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/update-webhook.ts +2 -1
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-form.tsx +7 -7
- package/dist/assets/adapters/next/templates/init/pages/login-form.tsx +7 -7
- package/dist/assets/adapters/next/templates/init/pages/login-page.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/media/media-page-content.tsx +5 -4
- package/dist/assets/adapters/next/templates/init/pages/profile/profile-form.tsx +13 -10
- package/dist/assets/adapters/next/templates/init/pages/reset-password-form.tsx +5 -5
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx +10 -5
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/delete-webhook-dialog.tsx +19 -10
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-actions.tsx +9 -4
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-endpoint-dialog.tsx +26 -20
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-logs-page-content.tsx +4 -4
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-logs-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-table.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/pages/users/change-password-dialog.tsx +6 -5
- package/dist/assets/adapters/next/templates/init/pages/users/create-user-dialog.tsx +5 -5
- package/dist/assets/adapters/next/templates/init/pages/users/delete-user-dialog.tsx +6 -4
- package/dist/assets/adapters/next/templates/init/pages/users/edit-role-dialog.tsx +9 -5
- package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/utils/error/action-error.ts +35 -0
- package/dist/assets/shared-assets/react-admin/schema.json +8 -0
- package/dist/assets/shared-assets/react-admin/ui/sonner.tsx +3 -8
- package/dist/assets/shared-assets/react-admin/ui/spinner.tsx +1 -1
- package/dist/{chunk-SO2CAJFC.js → chunk-45Z6XDG5.js} +418 -79
- package/dist/chunk-45Z6XDG5.js.map +1 -0
- package/dist/cli.js +2027 -2391
- package/dist/cli.js.map +1 -1
- package/dist/{template-reader-XMWPFYIK.js → template-reader-J6G7N5V6.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-SO2CAJFC.js.map +0 -1
- /package/dist/{template-reader-XMWPFYIK.js.map → template-reader-J6G7N5V6.js.map} +0 -0
|
@@ -1,58 +1,407 @@
|
|
|
1
1
|
// adapters/next/template-reader.ts
|
|
2
|
+
import fs3 from "fs";
|
|
3
|
+
import path3 from "path";
|
|
4
|
+
|
|
5
|
+
// utils/paths.ts
|
|
2
6
|
import fs2 from "fs";
|
|
3
7
|
import path2 from "path";
|
|
4
|
-
|
|
5
|
-
// core-engine/utils/cli-root.ts
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
8
|
import { fileURLToPath } from "url";
|
|
9
9
|
|
|
10
10
|
// constants/cli.ts
|
|
11
11
|
var CLI_PACKAGE_NAME = "betterstart-cli";
|
|
12
12
|
var REDACTED = "[redacted]";
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
// constants/paths.ts
|
|
15
|
+
var BETTERSTART_DIR = ".betterstart";
|
|
16
|
+
var CONFIG_FILE_NAME = "betterstart.config.ts";
|
|
17
|
+
var DEVELOPMENT_ENV_FILES = [
|
|
18
|
+
".env.development.local",
|
|
19
|
+
".env.local",
|
|
20
|
+
".env.development",
|
|
21
|
+
".env"
|
|
22
|
+
];
|
|
23
|
+
var LOCKFILE_MAP = {
|
|
24
|
+
"pnpm-lock.yaml": "pnpm",
|
|
25
|
+
"package-lock.json": "npm",
|
|
26
|
+
"yarn.lock": "yarn",
|
|
27
|
+
"bun.lockb": "bun",
|
|
28
|
+
"bun.lock": "bun"
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// utils/files.ts
|
|
32
|
+
import crypto from "crypto";
|
|
33
|
+
import fs from "fs";
|
|
34
|
+
import path from "path";
|
|
35
|
+
import { parseEnv } from "util";
|
|
36
|
+
|
|
37
|
+
// utils/text.ts
|
|
38
|
+
import { stripVTControlCharacters } from "util";
|
|
39
|
+
function stripAnsi(text, options = {}) {
|
|
40
|
+
const stripped = stripVTControlCharacters(text);
|
|
41
|
+
return options.stripCarriageReturns ? stripped.replaceAll("\r", "") : stripped;
|
|
42
|
+
}
|
|
43
|
+
function toPascalCase(str) {
|
|
44
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
|
|
45
|
+
}
|
|
46
|
+
function toCamelCase(str) {
|
|
47
|
+
const p = toPascalCase(str);
|
|
48
|
+
return p.charAt(0).toLowerCase() + p.slice(1);
|
|
49
|
+
}
|
|
50
|
+
function singularize(str) {
|
|
51
|
+
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
52
|
+
if (str.endsWith("ves")) return `${str.slice(0, -3)}f`;
|
|
53
|
+
if (str.endsWith("sses") || str.endsWith("xes") || str.endsWith("ches") || str.endsWith("shes") || str.endsWith("zes"))
|
|
54
|
+
return str.slice(0, -2);
|
|
55
|
+
if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
56
|
+
return str;
|
|
57
|
+
}
|
|
58
|
+
function pluralize(str) {
|
|
59
|
+
if (str.endsWith("s") && !str.endsWith("ss")) return str;
|
|
60
|
+
if (str.endsWith("y") && !["ay", "ey", "iy", "oy", "uy"].some((v) => str.endsWith(v)))
|
|
61
|
+
return `${str.slice(0, -1)}ies`;
|
|
62
|
+
if (str.endsWith("s") || str.endsWith("x") || str.endsWith("ch") || str.endsWith("sh"))
|
|
63
|
+
return `${str}es`;
|
|
64
|
+
return `${str}s`;
|
|
65
|
+
}
|
|
66
|
+
function toKebabCase(str) {
|
|
67
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
68
|
+
}
|
|
69
|
+
function toScreamingSnake(str) {
|
|
70
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
71
|
+
}
|
|
72
|
+
function quotePropertyName(name) {
|
|
73
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
74
|
+
}
|
|
75
|
+
function humanizeName(name) {
|
|
76
|
+
return name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().split(/\s+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
77
|
+
}
|
|
78
|
+
function singularizeLabel(label) {
|
|
79
|
+
const words = label.split(" ");
|
|
80
|
+
const lastWord = words[words.length - 1];
|
|
81
|
+
words[words.length - 1] = singularize(lastWord.toLowerCase());
|
|
82
|
+
words[words.length - 1] = words[words.length - 1].charAt(0).toUpperCase() + words[words.length - 1].slice(1);
|
|
83
|
+
return words.join(" ");
|
|
84
|
+
}
|
|
85
|
+
function quoteLiteral(value, quote = "'") {
|
|
86
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(new RegExp(escapeRegExp(quote), "g"), `\\${quote}`).replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
87
|
+
return `${quote}${escaped}${quote}`;
|
|
88
|
+
}
|
|
89
|
+
function escapeTemplateText(value) {
|
|
90
|
+
return value.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
91
|
+
}
|
|
92
|
+
function normalizeLineEndings(content) {
|
|
93
|
+
return content.replace(/\r\n/g, "\n");
|
|
94
|
+
}
|
|
95
|
+
function escapeRegExp(value) {
|
|
96
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
97
|
+
}
|
|
98
|
+
function hasConflictMarkers(content) {
|
|
99
|
+
return /^(<{7}|={7}|>{7})( |$)/m.test(content);
|
|
100
|
+
}
|
|
101
|
+
function splitLines(content) {
|
|
102
|
+
return normalizeLineEndings(content).split("\n");
|
|
103
|
+
}
|
|
104
|
+
function normalizeWhitespace(value) {
|
|
105
|
+
return value.trim().replace(/\s+/g, " ");
|
|
106
|
+
}
|
|
107
|
+
function escapeJsx(str) {
|
|
108
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
109
|
+
}
|
|
110
|
+
function escapeAttribute(str) {
|
|
111
|
+
return escapeJsx(str).replace(/"/g, """);
|
|
112
|
+
}
|
|
113
|
+
function findNextNonEmptyLine(lines, startIndex) {
|
|
114
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
115
|
+
const trimmed = lines[i].trim();
|
|
116
|
+
if (trimmed !== "") return trimmed;
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
function levenshtein(a, b) {
|
|
121
|
+
const matrix = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
122
|
+
for (let i = 0; i <= a.length; i++) matrix[i][0] = i;
|
|
123
|
+
for (let j = 0; j <= b.length; j++) matrix[0][j] = j;
|
|
124
|
+
for (let i = 1; i <= a.length; i++) {
|
|
125
|
+
for (let j = 1; j <= b.length; j++) {
|
|
126
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
127
|
+
matrix[i][j] = Math.min(
|
|
128
|
+
matrix[i - 1][j] + 1,
|
|
129
|
+
matrix[i][j - 1] + 1,
|
|
130
|
+
matrix[i - 1][j - 1] + cost
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return matrix[a.length][b.length];
|
|
135
|
+
}
|
|
136
|
+
function toTitleCase(value) {
|
|
137
|
+
return normalizeWhitespace(value).split(" ").map((word) => word ? `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}` : word).join(" ");
|
|
138
|
+
}
|
|
139
|
+
function slugify(value) {
|
|
140
|
+
return value.trim().toLowerCase().replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// utils/files.ts
|
|
144
|
+
import fse from "fs-extra";
|
|
145
|
+
function findUpwards(startDir, visit) {
|
|
146
|
+
let dir = path.resolve(startDir);
|
|
17
147
|
for (; ; ) {
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
148
|
+
const found = visit(dir);
|
|
149
|
+
if (found !== void 0) return found;
|
|
150
|
+
const parent = path.dirname(dir);
|
|
151
|
+
if (parent === dir) return void 0;
|
|
152
|
+
dir = parent;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function hashContent(content) {
|
|
156
|
+
return `sha256-${crypto.createHash("sha256").update(normalizeLineEndings(content)).digest("hex")}`;
|
|
157
|
+
}
|
|
158
|
+
function ensureDir(dirPath) {
|
|
159
|
+
fse.ensureDirSync(dirPath);
|
|
160
|
+
}
|
|
161
|
+
function safeWriteFile(filePath, content, force = false) {
|
|
162
|
+
if (!force && fs.existsSync(filePath)) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
ensureDir(path.dirname(filePath));
|
|
166
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
function createGeneratedFile(filePath, content) {
|
|
170
|
+
return {
|
|
171
|
+
path: filePath.split(path.sep).join("/"),
|
|
172
|
+
content
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function stripJsonComments(input) {
|
|
176
|
+
let result = "";
|
|
177
|
+
let i = 0;
|
|
178
|
+
while (i < input.length) {
|
|
179
|
+
if (input[i] === '"') {
|
|
180
|
+
let j = i + 1;
|
|
181
|
+
while (j < input.length) {
|
|
182
|
+
if (input[j] === "\\") {
|
|
183
|
+
j += 2;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (input[j] === '"') {
|
|
187
|
+
j++;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
j++;
|
|
191
|
+
}
|
|
192
|
+
result += input.slice(i, j);
|
|
193
|
+
i = j;
|
|
194
|
+
} else if (input[i] === "/" && input[i + 1] === "/") {
|
|
195
|
+
const nl = input.indexOf("\n", i);
|
|
196
|
+
i = nl === -1 ? input.length : nl;
|
|
197
|
+
} else if (input[i] === "/" && input[i + 1] === "*") {
|
|
198
|
+
const end = input.indexOf("*/", i + 2);
|
|
199
|
+
i = end === -1 ? input.length : end + 2;
|
|
200
|
+
} else {
|
|
201
|
+
result += input[i];
|
|
202
|
+
i++;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
function toStrictJson(input) {
|
|
208
|
+
return stripJsonComments(input).replace(/,\s*([\]}])/g, "$1");
|
|
209
|
+
}
|
|
210
|
+
function parseDotenvFile(filePath) {
|
|
211
|
+
if (!fs.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
212
|
+
try {
|
|
213
|
+
const parsed = Object.entries(parseEnv(fs.readFileSync(filePath, "utf-8")));
|
|
214
|
+
return new Map(
|
|
215
|
+
parsed.filter((entry) => typeof entry[1] === "string")
|
|
216
|
+
);
|
|
217
|
+
} catch {
|
|
218
|
+
return /* @__PURE__ */ new Map();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function readEnvVar(cwd, key) {
|
|
222
|
+
return parseDotenvFile(path.join(cwd, ".env.local")).get(key);
|
|
223
|
+
}
|
|
224
|
+
function resolveProjectEnvVar(cwd, key) {
|
|
225
|
+
for (const envFile of DEVELOPMENT_ENV_FILES) {
|
|
226
|
+
const value = parseDotenvFile(path.join(cwd, envFile)).get(key)?.trim();
|
|
227
|
+
if (value) return { source: envFile, value };
|
|
228
|
+
}
|
|
229
|
+
return void 0;
|
|
230
|
+
}
|
|
231
|
+
function readProjectEnvVar(cwd, key) {
|
|
232
|
+
return resolveProjectEnvVar(cwd, key)?.value;
|
|
233
|
+
}
|
|
234
|
+
function appendEnvVars(cwd, sections, overwrite) {
|
|
235
|
+
const envPath = path.join(cwd, ".env.local");
|
|
236
|
+
let existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, "utf-8") : "";
|
|
237
|
+
const existingKeys = new Set(
|
|
238
|
+
existing.split("\n").filter((line) => line.trim() && !line.trim().startsWith("#")).map((line) => line.split("=")[0]?.trim()).filter(Boolean)
|
|
239
|
+
);
|
|
240
|
+
const added = [];
|
|
241
|
+
const skipped = [];
|
|
242
|
+
const updated = [];
|
|
243
|
+
const lines = [];
|
|
244
|
+
if (overwrite) {
|
|
245
|
+
for (const section of sections) {
|
|
246
|
+
for (const v of section.vars) {
|
|
247
|
+
if (overwrite.has(v.key) && existingKeys.has(v.key)) {
|
|
248
|
+
const pattern = new RegExp(`^${v.key}=.*$`, "m");
|
|
249
|
+
const replacement = v.comment ? `${v.key}="${v.value}" # ${v.comment}` : `${v.key}="${v.value}"`;
|
|
250
|
+
existing = existing.replace(pattern, replacement);
|
|
251
|
+
updated.push(v.key);
|
|
24
252
|
}
|
|
25
|
-
} catch {
|
|
26
253
|
}
|
|
27
254
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
255
|
+
}
|
|
256
|
+
if (existing.trim()) {
|
|
257
|
+
lines.push("");
|
|
258
|
+
}
|
|
259
|
+
for (const section of sections) {
|
|
260
|
+
const sectionVars = section.vars.filter((v) => {
|
|
261
|
+
if (existingKeys.has(v.key)) {
|
|
262
|
+
if (!updated.includes(v.key)) skipped.push(v.key);
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
added.push(v.key);
|
|
266
|
+
return true;
|
|
267
|
+
});
|
|
268
|
+
if (sectionVars.length === 0) continue;
|
|
269
|
+
lines.push(`# ${section.header}`);
|
|
270
|
+
for (const v of sectionVars) {
|
|
271
|
+
const line = v.comment ? `${v.key}="${v.value}" # ${v.comment}` : `${v.key}="${v.value}"`;
|
|
272
|
+
lines.push(line);
|
|
31
273
|
}
|
|
32
|
-
|
|
274
|
+
lines.push("");
|
|
275
|
+
}
|
|
276
|
+
if (added.length > 0 || updated.length > 0) {
|
|
277
|
+
const header = existing.trim() ? "" : "# ============================================\n# BetterStart Admin\n# ============================================\n";
|
|
278
|
+
const content = existing.trim() ? `${existing.trimEnd()}
|
|
279
|
+
${lines.join("\n")}` : header + lines.join("\n");
|
|
280
|
+
fs.writeFileSync(envPath, content);
|
|
33
281
|
}
|
|
282
|
+
return { added, skipped, updated };
|
|
283
|
+
}
|
|
284
|
+
function removeEnvVars(cwd, keys) {
|
|
285
|
+
const envPath = path.join(cwd, ".env.local");
|
|
286
|
+
if (!fs.existsSync(envPath) || keys.length === 0) {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
const keySet = new Set(keys);
|
|
290
|
+
const removed = [];
|
|
291
|
+
const filteredLines = fs.readFileSync(envPath, "utf-8").split("\n").filter((line) => {
|
|
292
|
+
const trimmed = line.trim();
|
|
293
|
+
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
const [key] = trimmed.split("=");
|
|
297
|
+
const normalizedKey = key?.trim();
|
|
298
|
+
if (normalizedKey && keySet.has(normalizedKey)) {
|
|
299
|
+
removed.push(normalizedKey);
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
return true;
|
|
303
|
+
});
|
|
304
|
+
fs.writeFileSync(envPath, `${filteredLines.join("\n").trimEnd()}
|
|
305
|
+
`, "utf-8");
|
|
306
|
+
return removed;
|
|
307
|
+
}
|
|
308
|
+
function captureFile(filePath) {
|
|
309
|
+
if (!fs.existsSync(filePath)) {
|
|
310
|
+
return { existed: false };
|
|
311
|
+
}
|
|
312
|
+
return { existed: true, content: fs.readFileSync(filePath, "utf-8") };
|
|
313
|
+
}
|
|
314
|
+
function restoreFile(filePath, snapshot) {
|
|
315
|
+
if (snapshot.existed) {
|
|
316
|
+
fs.writeFileSync(filePath, snapshot.content ?? "", "utf-8");
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (fs.existsSync(filePath)) {
|
|
320
|
+
fs.rmSync(filePath, { force: true });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// utils/paths.ts
|
|
325
|
+
function betterstartDir(cwd, ...segments) {
|
|
326
|
+
return path2.join(cwd, BETTERSTART_DIR, ...segments);
|
|
327
|
+
}
|
|
328
|
+
function toPosixPath(value) {
|
|
329
|
+
return value.replace(/\\/g, "/");
|
|
330
|
+
}
|
|
331
|
+
function trimDotSlash(value) {
|
|
332
|
+
return value.replace(/^[.][/\\]/, "");
|
|
333
|
+
}
|
|
334
|
+
function normalizePosixDir(value) {
|
|
335
|
+
return trimDotSlash(toPosixPath(value)).replace(/\/+$/, "");
|
|
336
|
+
}
|
|
337
|
+
function toProjectAbsolutePath(cwd, filePath) {
|
|
338
|
+
return path2.isAbsolute(filePath) ? filePath : path2.join(cwd, ...filePath.split("/"));
|
|
339
|
+
}
|
|
340
|
+
function readLocalProjectFile(cwd, filePath) {
|
|
341
|
+
const fullPath = toProjectAbsolutePath(cwd, filePath);
|
|
342
|
+
return fs2.existsSync(fullPath) ? fs2.readFileSync(fullPath, "utf-8") : null;
|
|
343
|
+
}
|
|
344
|
+
function isInsideDir(child, parent) {
|
|
345
|
+
const relative = path2.relative(parent, child);
|
|
346
|
+
return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
|
|
347
|
+
}
|
|
348
|
+
function removePath(cwd, filePath) {
|
|
349
|
+
const fullPath = toProjectAbsolutePath(cwd, filePath);
|
|
350
|
+
const existed = fs2.existsSync(fullPath);
|
|
351
|
+
fs2.rmSync(fullPath, { recursive: true, force: true });
|
|
352
|
+
return existed;
|
|
353
|
+
}
|
|
354
|
+
function cleanupEmptyDirs(cwd, deletedPaths, stopRoots) {
|
|
355
|
+
const projectRoot = path2.resolve(cwd);
|
|
356
|
+
const stops = /* @__PURE__ */ new Set([projectRoot, ...stopRoots]);
|
|
357
|
+
for (const deletedPath of deletedPaths) {
|
|
358
|
+
let currentDir = path2.dirname(toProjectAbsolutePath(cwd, deletedPath));
|
|
359
|
+
while (isInsideDir(currentDir, projectRoot) && !stops.has(currentDir)) {
|
|
360
|
+
if (!fs2.existsSync(currentDir)) {
|
|
361
|
+
currentDir = path2.dirname(currentDir);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (fs2.readdirSync(currentDir).length > 0) {
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
fs2.rmdirSync(currentDir);
|
|
368
|
+
currentDir = path2.dirname(currentDir);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function findCliPackage() {
|
|
373
|
+
const start = path2.dirname(fileURLToPath(import.meta.url));
|
|
374
|
+
return findUpwards(start, (dir) => {
|
|
375
|
+
const pkgPath = path2.join(dir, "package.json");
|
|
376
|
+
if (!fs2.existsSync(pkgPath)) return void 0;
|
|
377
|
+
try {
|
|
378
|
+
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
379
|
+
return pkg.name === CLI_PACKAGE_NAME ? { dir, pkg } : void 0;
|
|
380
|
+
} catch {
|
|
381
|
+
return void 0;
|
|
382
|
+
}
|
|
383
|
+
}) ?? null;
|
|
34
384
|
}
|
|
35
385
|
function findCliRoot() {
|
|
36
386
|
const found = findCliPackage();
|
|
37
387
|
if (found) {
|
|
38
388
|
return found.dir;
|
|
39
389
|
}
|
|
40
|
-
return
|
|
390
|
+
return path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
41
391
|
}
|
|
42
392
|
function getCurrentCliVersion() {
|
|
43
393
|
return findCliPackage()?.pkg.version ?? "0.0.0";
|
|
44
394
|
}
|
|
45
395
|
function resolveCliAssetPath(...segments) {
|
|
46
396
|
const root = findCliRoot();
|
|
47
|
-
const builtPath =
|
|
48
|
-
if (
|
|
397
|
+
const builtPath = path2.join(root, "dist", "assets", ...segments);
|
|
398
|
+
if (fs2.existsSync(builtPath)) {
|
|
49
399
|
return builtPath;
|
|
50
400
|
}
|
|
51
|
-
return
|
|
401
|
+
return path2.join(root, ...segments);
|
|
52
402
|
}
|
|
53
403
|
|
|
54
404
|
// constants/patterns.ts
|
|
55
|
-
var ANSI_ESCAPE_PATTERN = /\u001B\[[0-?]*[ -/]*[@-~]/g;
|
|
56
405
|
var REMOVABLE_NAMESPACE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
57
406
|
var SCHEMA_NAME_PATTERN = /^[a-z][a-zA-Z0-9-]*$/;
|
|
58
407
|
var NAMESPACE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
@@ -157,53 +506,6 @@ var R2_ENV_KEYS = [
|
|
|
157
506
|
"BETTERSTART_R2_PUBLIC_URL"
|
|
158
507
|
];
|
|
159
508
|
|
|
160
|
-
// core-engine/utils/string.ts
|
|
161
|
-
function toPascalCase(str) {
|
|
162
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
|
|
163
|
-
}
|
|
164
|
-
function toCamelCase(str) {
|
|
165
|
-
const p = toPascalCase(str);
|
|
166
|
-
return p.charAt(0).toLowerCase() + p.slice(1);
|
|
167
|
-
}
|
|
168
|
-
function singularize(str) {
|
|
169
|
-
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
170
|
-
if (str.endsWith("ves")) return `${str.slice(0, -3)}f`;
|
|
171
|
-
if (str.endsWith("sses") || str.endsWith("xes") || str.endsWith("ches") || str.endsWith("shes") || str.endsWith("zes"))
|
|
172
|
-
return str.slice(0, -2);
|
|
173
|
-
if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
174
|
-
return str;
|
|
175
|
-
}
|
|
176
|
-
function pluralize(str) {
|
|
177
|
-
if (str.endsWith("s") && !str.endsWith("ss")) return str;
|
|
178
|
-
if (str.endsWith("y") && !["ay", "ey", "iy", "oy", "uy"].some((v) => str.endsWith(v)))
|
|
179
|
-
return `${str.slice(0, -1)}ies`;
|
|
180
|
-
if (str.endsWith("s") || str.endsWith("x") || str.endsWith("ch") || str.endsWith("sh"))
|
|
181
|
-
return `${str}es`;
|
|
182
|
-
return `${str}s`;
|
|
183
|
-
}
|
|
184
|
-
function toKebabCase(str) {
|
|
185
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
186
|
-
}
|
|
187
|
-
function toScreamingSnake(str) {
|
|
188
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
189
|
-
}
|
|
190
|
-
function quotePropertyName(name) {
|
|
191
|
-
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`;
|
|
192
|
-
}
|
|
193
|
-
function singularizeLabel(label) {
|
|
194
|
-
const words = label.split(" ");
|
|
195
|
-
const lastWord = words[words.length - 1];
|
|
196
|
-
words[words.length - 1] = singularize(lastWord.toLowerCase());
|
|
197
|
-
words[words.length - 1] = words[words.length - 1].charAt(0).toUpperCase() + words[words.length - 1].slice(1);
|
|
198
|
-
return words.join(" ");
|
|
199
|
-
}
|
|
200
|
-
function singleQuote(value) {
|
|
201
|
-
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
202
|
-
}
|
|
203
|
-
function escapeTemplateText(value) {
|
|
204
|
-
return value.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
509
|
// adapters/next/config/namespace.ts
|
|
208
510
|
function validateAdminNamespace(value) {
|
|
209
511
|
const segment = value.trim();
|
|
@@ -418,8 +720,8 @@ function applyAdminNamespaceToContent(content, namespaceValue) {
|
|
|
418
720
|
|
|
419
721
|
// adapters/next/template-reader.ts
|
|
420
722
|
function readTemplate(relativePath) {
|
|
421
|
-
return
|
|
422
|
-
|
|
723
|
+
return fs3.readFileSync(
|
|
724
|
+
path3.join(resolveCliAssetPath("adapters", "next", "templates", "init"), relativePath),
|
|
423
725
|
"utf-8"
|
|
424
726
|
);
|
|
425
727
|
}
|
|
@@ -443,15 +745,57 @@ function namespacedTemplatePath(relativePath, namespace) {
|
|
|
443
745
|
}
|
|
444
746
|
|
|
445
747
|
export {
|
|
748
|
+
BETTERSTART_DIR,
|
|
749
|
+
CONFIG_FILE_NAME,
|
|
750
|
+
LOCKFILE_MAP,
|
|
751
|
+
stripAnsi,
|
|
446
752
|
toPascalCase,
|
|
447
753
|
toCamelCase,
|
|
448
754
|
singularize,
|
|
449
755
|
pluralize,
|
|
450
756
|
toKebabCase,
|
|
451
757
|
quotePropertyName,
|
|
758
|
+
humanizeName,
|
|
452
759
|
singularizeLabel,
|
|
453
|
-
|
|
760
|
+
quoteLiteral,
|
|
454
761
|
escapeTemplateText,
|
|
762
|
+
normalizeLineEndings,
|
|
763
|
+
escapeRegExp,
|
|
764
|
+
hasConflictMarkers,
|
|
765
|
+
splitLines,
|
|
766
|
+
normalizeWhitespace,
|
|
767
|
+
escapeJsx,
|
|
768
|
+
escapeAttribute,
|
|
769
|
+
findNextNonEmptyLine,
|
|
770
|
+
levenshtein,
|
|
771
|
+
toTitleCase,
|
|
772
|
+
slugify,
|
|
773
|
+
findUpwards,
|
|
774
|
+
hashContent,
|
|
775
|
+
ensureDir,
|
|
776
|
+
safeWriteFile,
|
|
777
|
+
createGeneratedFile,
|
|
778
|
+
toStrictJson,
|
|
779
|
+
parseDotenvFile,
|
|
780
|
+
readEnvVar,
|
|
781
|
+
resolveProjectEnvVar,
|
|
782
|
+
readProjectEnvVar,
|
|
783
|
+
appendEnvVars,
|
|
784
|
+
removeEnvVars,
|
|
785
|
+
captureFile,
|
|
786
|
+
restoreFile,
|
|
787
|
+
CLI_PACKAGE_NAME,
|
|
788
|
+
REDACTED,
|
|
789
|
+
betterstartDir,
|
|
790
|
+
toPosixPath,
|
|
791
|
+
trimDotSlash,
|
|
792
|
+
normalizePosixDir,
|
|
793
|
+
toProjectAbsolutePath,
|
|
794
|
+
readLocalProjectFile,
|
|
795
|
+
removePath,
|
|
796
|
+
cleanupEmptyDirs,
|
|
797
|
+
getCurrentCliVersion,
|
|
798
|
+
resolveCliAssetPath,
|
|
455
799
|
DEFAULT_ADMIN_NAMESPACE,
|
|
456
800
|
ADMIN_THEME_BLOCK,
|
|
457
801
|
ADMIN_SHADOW_INPUT_UTILITY,
|
|
@@ -465,7 +809,6 @@ export {
|
|
|
465
809
|
TIPTAP_CONTENT_EDITOR_DIRECTORIES,
|
|
466
810
|
RAILWAY_BUCKET_ENV_KEYS,
|
|
467
811
|
R2_ENV_KEYS,
|
|
468
|
-
ANSI_ESCAPE_PATTERN,
|
|
469
812
|
REMOVABLE_NAMESPACE_PATTERN,
|
|
470
813
|
SCHEMA_NAME_PATTERN,
|
|
471
814
|
DEV_PORT_FLAG_PATTERN,
|
|
@@ -482,13 +825,9 @@ export {
|
|
|
482
825
|
deriveMigrationsDir,
|
|
483
826
|
applyAdminNamespaceToPath,
|
|
484
827
|
applyAdminNamespaceToContent,
|
|
485
|
-
CLI_PACKAGE_NAME,
|
|
486
|
-
REDACTED,
|
|
487
|
-
getCurrentCliVersion,
|
|
488
|
-
resolveCliAssetPath,
|
|
489
828
|
readTemplate,
|
|
490
829
|
applyNextCacheApiForVersion,
|
|
491
830
|
readNamespacedTemplate,
|
|
492
831
|
namespacedTemplatePath
|
|
493
832
|
};
|
|
494
|
-
//# sourceMappingURL=chunk-
|
|
833
|
+
//# sourceMappingURL=chunk-45Z6XDG5.js.map
|