betterstart-cli 0.0.87 → 0.0.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +378 -314
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
|
|
23
23
|
// cli.ts
|
|
24
24
|
import { readFileSync } from "fs";
|
|
25
|
-
import * as
|
|
25
|
+
import * as p30 from "@clack/prompts";
|
|
26
26
|
|
|
27
27
|
// core-engine/commands/require-init.ts
|
|
28
28
|
import path2 from "path";
|
|
@@ -198,7 +198,7 @@ function createUpdateStylesCommand(runtime) {
|
|
|
198
198
|
|
|
199
199
|
// adapters/next/commands/add.ts
|
|
200
200
|
import path27 from "path";
|
|
201
|
-
import * as
|
|
201
|
+
import * as p7 from "@clack/prompts";
|
|
202
202
|
|
|
203
203
|
// core-engine/config/serialize.ts
|
|
204
204
|
import fs3 from "fs";
|
|
@@ -750,7 +750,7 @@ async function resolveConfigOrExit(cwd) {
|
|
|
750
750
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
751
751
|
import fs8 from "fs";
|
|
752
752
|
import path10 from "path";
|
|
753
|
-
import * as
|
|
753
|
+
import * as p4 from "@clack/prompts";
|
|
754
754
|
|
|
755
755
|
// adapters/next/init/scaffolders/dependencies.ts
|
|
756
756
|
import { spawn } from "child_process";
|
|
@@ -1633,6 +1633,7 @@ async function syncProjectCliDependency(cwd, pm) {
|
|
|
1633
1633
|
// adapters/next/utils/drizzle-push.ts
|
|
1634
1634
|
import { spawn as spawn2 } from "child_process";
|
|
1635
1635
|
import path9 from "path";
|
|
1636
|
+
import * as p2 from "@clack/prompts";
|
|
1636
1637
|
var PG_SSL_WARNING_START = "Warning: SECURITY WARNING: The SSL modes 'prefer', 'require', and 'verify-ca' are treated as aliases for 'verify-full'.";
|
|
1637
1638
|
var PG_SSL_WARNING_END = "See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode definitions.";
|
|
1638
1639
|
var NODE_TRACE_WARNING_HINT = "(Use `node --trace-warnings";
|
|
@@ -1654,6 +1655,36 @@ var ANSI_ESCAPE_PATTERN = /\u001B\[[0-9;]*[A-Za-z]/g;
|
|
|
1654
1655
|
function resolveDrizzlePushStdio(interactive) {
|
|
1655
1656
|
return interactive ? ["inherit", "pipe", "pipe"] : "pipe";
|
|
1656
1657
|
}
|
|
1658
|
+
var DRIZZLE_TTY_PROMPT_ERROR = "Interactive prompts require a TTY terminal";
|
|
1659
|
+
function createTtyPromptErrorSuppressor(forward) {
|
|
1660
|
+
let inStack = false;
|
|
1661
|
+
let saw = false;
|
|
1662
|
+
return {
|
|
1663
|
+
write(chunk) {
|
|
1664
|
+
const lines = chunk.match(/[^\n]*\n|[^\n]+/g) ?? [];
|
|
1665
|
+
const kept = [];
|
|
1666
|
+
for (const line of lines) {
|
|
1667
|
+
const text7 = stripAnsi(line).trim();
|
|
1668
|
+
if (text7.includes(DRIZZLE_TTY_PROMPT_ERROR)) {
|
|
1669
|
+
saw = true;
|
|
1670
|
+
inStack = true;
|
|
1671
|
+
continue;
|
|
1672
|
+
}
|
|
1673
|
+
if (inStack) {
|
|
1674
|
+
if (text7.startsWith("at ") || text7 === "") {
|
|
1675
|
+
continue;
|
|
1676
|
+
}
|
|
1677
|
+
inStack = false;
|
|
1678
|
+
}
|
|
1679
|
+
kept.push(line);
|
|
1680
|
+
}
|
|
1681
|
+
if (kept.length > 0) {
|
|
1682
|
+
forward(kept.join(""));
|
|
1683
|
+
}
|
|
1684
|
+
},
|
|
1685
|
+
sawError: () => saw
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1657
1688
|
function stripAnsi(text7) {
|
|
1658
1689
|
return text7.replace(ANSI_ESCAPE_PATTERN, "").replaceAll("\r", "");
|
|
1659
1690
|
}
|
|
@@ -1740,18 +1771,24 @@ function runDrizzlePush(cwd, options = {}) {
|
|
|
1740
1771
|
outputNotified = true;
|
|
1741
1772
|
options.onOutput?.();
|
|
1742
1773
|
};
|
|
1774
|
+
const stderrTtySuppressor = createTtyPromptErrorSuppressor((chunk) => {
|
|
1775
|
+
notifyOutput();
|
|
1776
|
+
process.stderr.write(chunk);
|
|
1777
|
+
});
|
|
1778
|
+
const stdoutTtySuppressor = createTtyPromptErrorSuppressor((chunk) => {
|
|
1779
|
+
notifyOutput();
|
|
1780
|
+
process.stdout.write(chunk);
|
|
1781
|
+
});
|
|
1743
1782
|
const stderrFilter = createDrizzleNoiseFilter((chunk) => {
|
|
1744
1783
|
if (options.interactive) {
|
|
1745
|
-
|
|
1746
|
-
process.stderr.write(chunk);
|
|
1784
|
+
stderrTtySuppressor.write(chunk);
|
|
1747
1785
|
return;
|
|
1748
1786
|
}
|
|
1749
1787
|
stderr += chunk;
|
|
1750
1788
|
});
|
|
1751
1789
|
const stdoutFilter = createDrizzleNoiseFilter((chunk) => {
|
|
1752
1790
|
if (options.interactive) {
|
|
1753
|
-
|
|
1754
|
-
process.stdout.write(chunk);
|
|
1791
|
+
stdoutTtySuppressor.write(chunk);
|
|
1755
1792
|
return;
|
|
1756
1793
|
}
|
|
1757
1794
|
stdout += chunk;
|
|
@@ -1770,6 +1807,29 @@ function runDrizzlePush(cwd, options = {}) {
|
|
|
1770
1807
|
resolve({ success: true, error: null });
|
|
1771
1808
|
return;
|
|
1772
1809
|
}
|
|
1810
|
+
if (stdoutTtySuppressor.sawError() || stderrTtySuppressor.sawError()) {
|
|
1811
|
+
notifyOutput();
|
|
1812
|
+
p2.log.info("Database changes need your input \u2014 continuing in drizzle-kit.");
|
|
1813
|
+
const attached = spawn2(drizzleBin, ["push", "--force"], {
|
|
1814
|
+
cwd,
|
|
1815
|
+
stdio: "inherit",
|
|
1816
|
+
env: { ...process.env }
|
|
1817
|
+
});
|
|
1818
|
+
attached.on("close", (attachedCode, attachedSignal) => {
|
|
1819
|
+
if (attachedCode === 0) {
|
|
1820
|
+
resolve({ success: true, error: null });
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
resolve({
|
|
1824
|
+
success: false,
|
|
1825
|
+
error: attachedSignal ? `drizzle-kit push exited with signal ${attachedSignal}` : `drizzle-kit push exited with code ${attachedCode}`
|
|
1826
|
+
});
|
|
1827
|
+
});
|
|
1828
|
+
attached.on("error", (err) => {
|
|
1829
|
+
resolve({ success: false, error: err.message });
|
|
1830
|
+
});
|
|
1831
|
+
return;
|
|
1832
|
+
}
|
|
1773
1833
|
resolve({
|
|
1774
1834
|
success: false,
|
|
1775
1835
|
error: signal ? `drizzle-kit push exited with signal ${signal}` : `drizzle-kit push exited with code ${code}`
|
|
@@ -1795,7 +1855,7 @@ ${stderr}`.trim();
|
|
|
1795
1855
|
}
|
|
1796
1856
|
|
|
1797
1857
|
// adapters/next/utils/next-steps.ts
|
|
1798
|
-
import * as
|
|
1858
|
+
import * as p3 from "@clack/prompts";
|
|
1799
1859
|
function printNextSteps(options) {
|
|
1800
1860
|
const steps = [`1. Review ${options.reviewLabel}`];
|
|
1801
1861
|
if (options.needsMigration) {
|
|
@@ -1804,7 +1864,7 @@ function printNextSteps(options) {
|
|
|
1804
1864
|
} else {
|
|
1805
1865
|
steps.push(`2. Start the dev server and visit ${options.route}`);
|
|
1806
1866
|
}
|
|
1807
|
-
|
|
1867
|
+
p3.note(steps.join("\n"), "Next steps");
|
|
1808
1868
|
}
|
|
1809
1869
|
|
|
1810
1870
|
// adapters/next/generators/post-generate.ts
|
|
@@ -1906,25 +1966,25 @@ function ensureDatabasePushDependencies(cwd, pm) {
|
|
|
1906
1966
|
if (missing.length === 0) {
|
|
1907
1967
|
return true;
|
|
1908
1968
|
}
|
|
1909
|
-
|
|
1969
|
+
p4.log.info(
|
|
1910
1970
|
`Installing database push dependencies (${missing.map((dependency) => dependency.name).join(", ")})...`
|
|
1911
1971
|
);
|
|
1912
1972
|
for (const dependency of missing) {
|
|
1913
1973
|
const installed2 = installDependency(cwd, pm, dependency.name, dependency.dev);
|
|
1914
1974
|
if (!installed2) {
|
|
1915
|
-
|
|
1975
|
+
p4.log.warn(`Failed to install ${dependency.name}`);
|
|
1916
1976
|
return false;
|
|
1917
1977
|
}
|
|
1918
1978
|
}
|
|
1919
1979
|
const ready = hasPostgresRuntimeDependency(cwd) && hasDrizzleKitPostgresDriverDependency(cwd);
|
|
1920
1980
|
if (ready) {
|
|
1921
|
-
|
|
1981
|
+
p4.log.success("Database push dependencies installed");
|
|
1922
1982
|
} else {
|
|
1923
1983
|
const unresolved = [
|
|
1924
1984
|
!hasPostgresRuntimeDependency(cwd) ? POSTGRES_RUNTIME_DEP : null,
|
|
1925
1985
|
!hasDrizzleKitPostgresDriverDependency(cwd) ? DRIZZLE_KIT_POSTGRES_DRIVER_DEP : null
|
|
1926
1986
|
].filter((dependency) => Boolean(dependency));
|
|
1927
|
-
|
|
1987
|
+
p4.log.warn(`Installed dependencies but could not resolve ${unresolved.join(", ")}`);
|
|
1928
1988
|
}
|
|
1929
1989
|
return ready;
|
|
1930
1990
|
}
|
|
@@ -1967,8 +2027,8 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
|
|
|
1967
2027
|
"Formatting: skipped (biome refuses files with conflict markers)",
|
|
1968
2028
|
...(options.conflictPaths ?? []).map((conflictPath) => ` - ${conflictPath}`)
|
|
1969
2029
|
];
|
|
1970
|
-
|
|
1971
|
-
|
|
2030
|
+
p4.log.warn(lines.join("\n"));
|
|
2031
|
+
p4.log.message(
|
|
1972
2032
|
"Resolve markers in the files above and re-run the BetterStart command that wrote them. Post-write tasks run automatically once every file is clean."
|
|
1973
2033
|
);
|
|
1974
2034
|
return result;
|
|
@@ -1978,7 +2038,7 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
|
|
|
1978
2038
|
const dbUrl = process.env.DATABASE_URL;
|
|
1979
2039
|
if (!dbUrl) {
|
|
1980
2040
|
result.dbPush = "no-db-url";
|
|
1981
|
-
|
|
2041
|
+
p4.log.warn(
|
|
1982
2042
|
[
|
|
1983
2043
|
"Database: skipped (no DATABASE_URL configured)",
|
|
1984
2044
|
" To sync later: run db:push after setting DATABASE_URL"
|
|
@@ -1986,43 +2046,43 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
|
|
|
1986
2046
|
);
|
|
1987
2047
|
} else if (!ensureDatabasePushDependencies(cwd, pm)) {
|
|
1988
2048
|
result.dbPush = "failed";
|
|
1989
|
-
|
|
2049
|
+
p4.log.warn(
|
|
1990
2050
|
"Database push failed (install database dependencies and run drizzle-kit push manually)"
|
|
1991
2051
|
);
|
|
1992
2052
|
} else if (hasPkgScript(cwd, "db:push")) {
|
|
1993
|
-
|
|
2053
|
+
p4.log.info("Running db:push...");
|
|
1994
2054
|
const ok = runPmScript(pm, "db:push", cwd);
|
|
1995
2055
|
result.dbPush = ok ? "success" : "failed";
|
|
1996
2056
|
if (ok) {
|
|
1997
|
-
|
|
2057
|
+
p4.log.success("Database schema synced");
|
|
1998
2058
|
} else {
|
|
1999
|
-
|
|
2059
|
+
p4.log.warn("Database push failed (run db:push manually)");
|
|
2000
2060
|
}
|
|
2001
2061
|
} else {
|
|
2002
|
-
|
|
2062
|
+
p4.log.info("Running drizzle-kit push...");
|
|
2003
2063
|
try {
|
|
2004
2064
|
const pushResult = await runDrizzlePush(cwd, { interactive: true });
|
|
2005
2065
|
if (!pushResult.success) {
|
|
2006
2066
|
throw new Error(pushResult.error ?? "drizzle-kit push failed");
|
|
2007
2067
|
}
|
|
2008
2068
|
result.dbPush = "success";
|
|
2009
|
-
|
|
2069
|
+
p4.log.success("Database schema synced");
|
|
2010
2070
|
} catch {
|
|
2011
2071
|
result.dbPush = "failed";
|
|
2012
|
-
|
|
2072
|
+
p4.log.warn("Database push failed (run drizzle-kit push manually)");
|
|
2013
2073
|
}
|
|
2014
2074
|
}
|
|
2015
2075
|
} else {
|
|
2016
|
-
|
|
2076
|
+
p4.log.info(`Database: skipped (${options.skipMigrationMessage ?? "--skip-migration"})`);
|
|
2017
2077
|
}
|
|
2018
2078
|
if (hasPkgScript(cwd, "lint:fix")) {
|
|
2019
|
-
|
|
2079
|
+
p4.log.info("Running lint:fix...");
|
|
2020
2080
|
const ok = runPmScript(pm, "lint:fix", cwd, BIOME_FORMAT_TIMEOUT_MS);
|
|
2021
2081
|
result.lintFix = ok ? "success" : "failed";
|
|
2022
2082
|
if (ok) {
|
|
2023
|
-
|
|
2083
|
+
p4.log.success("Code formatted");
|
|
2024
2084
|
} else {
|
|
2025
|
-
|
|
2085
|
+
p4.log.warn("Lint fix had issues (run lint:fix manually)");
|
|
2026
2086
|
}
|
|
2027
2087
|
} else {
|
|
2028
2088
|
try {
|
|
@@ -2030,10 +2090,10 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
|
|
|
2030
2090
|
throw new Error("Biome binary not found");
|
|
2031
2091
|
}
|
|
2032
2092
|
result.lintFix = "success";
|
|
2033
|
-
|
|
2093
|
+
p4.log.success("Code formatted with Biome");
|
|
2034
2094
|
} catch {
|
|
2035
2095
|
result.lintFix = "failed";
|
|
2036
|
-
|
|
2096
|
+
p4.log.warn("Biome formatting had issues (run biome check --write manually)");
|
|
2037
2097
|
}
|
|
2038
2098
|
}
|
|
2039
2099
|
if (options.showNextSteps !== false) {
|
|
@@ -2050,7 +2110,7 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
|
|
|
2050
2110
|
// adapters/next/integration-runtime.ts
|
|
2051
2111
|
import fs14 from "fs";
|
|
2052
2112
|
import path17 from "path";
|
|
2053
|
-
import * as
|
|
2113
|
+
import * as p5 from "@clack/prompts";
|
|
2054
2114
|
|
|
2055
2115
|
// core-engine/schema/schema-reader.ts
|
|
2056
2116
|
import fs9 from "fs";
|
|
@@ -3376,12 +3436,12 @@ async function resolveTextEnvValue(options) {
|
|
|
3376
3436
|
if (existingValue) {
|
|
3377
3437
|
return existingValue;
|
|
3378
3438
|
}
|
|
3379
|
-
const result = await
|
|
3439
|
+
const result = await p5.text({
|
|
3380
3440
|
message: options.message,
|
|
3381
3441
|
defaultValue: options.defaultValue,
|
|
3382
3442
|
validate: options.validate
|
|
3383
3443
|
});
|
|
3384
|
-
if (
|
|
3444
|
+
if (p5.isCancel(result)) {
|
|
3385
3445
|
throw new Error(options.cancelMessage);
|
|
3386
3446
|
}
|
|
3387
3447
|
options.overwriteEnvKeys.add(options.key);
|
|
@@ -3392,11 +3452,11 @@ async function resolvePasswordEnvValue(options) {
|
|
|
3392
3452
|
if (existingValue) {
|
|
3393
3453
|
return existingValue;
|
|
3394
3454
|
}
|
|
3395
|
-
const result = await
|
|
3455
|
+
const result = await p5.password({
|
|
3396
3456
|
message: options.message,
|
|
3397
3457
|
validate: options.validate
|
|
3398
3458
|
});
|
|
3399
|
-
if (
|
|
3459
|
+
if (p5.isCancel(result)) {
|
|
3400
3460
|
throw new Error(options.cancelMessage);
|
|
3401
3461
|
}
|
|
3402
3462
|
options.overwriteEnvKeys.add(options.key);
|
|
@@ -5777,14 +5837,14 @@ function buildStepsConstant(steps) {
|
|
|
5777
5837
|
${entries.join(",\n")}
|
|
5778
5838
|
]`;
|
|
5779
5839
|
}
|
|
5780
|
-
function buildComponentSource(
|
|
5840
|
+
function buildComponentSource(p31) {
|
|
5781
5841
|
const providerOpen = ` <NuqsAdapter>
|
|
5782
5842
|
<React.Suspense fallback={null}>
|
|
5783
|
-
<${
|
|
5843
|
+
<${p31.pascal}FormInner />
|
|
5784
5844
|
</React.Suspense>
|
|
5785
5845
|
</NuqsAdapter>`;
|
|
5786
5846
|
const exportWrapper = `
|
|
5787
|
-
export function ${
|
|
5847
|
+
export function ${p31.pascal}Form() {
|
|
5788
5848
|
return (
|
|
5789
5849
|
${providerOpen}
|
|
5790
5850
|
)
|
|
@@ -5793,22 +5853,22 @@ ${providerOpen}
|
|
|
5793
5853
|
return `'use client'
|
|
5794
5854
|
|
|
5795
5855
|
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
|
|
5796
|
-
import { ChevronLeft, ChevronRight${
|
|
5856
|
+
import { ChevronLeft, ChevronRight${p31.hasListFields ? ", Trash2" : ""} } from 'lucide-react'
|
|
5797
5857
|
import { createParser, useQueryState } from 'nuqs'
|
|
5798
5858
|
import { NuqsAdapter } from 'nuqs/adapters/next/app'
|
|
5799
5859
|
import * as React from 'react'
|
|
5800
|
-
${
|
|
5860
|
+
${p31.rhfImport}
|
|
5801
5861
|
import { z } from 'zod/v3'
|
|
5802
|
-
import { create${
|
|
5862
|
+
import { create${p31.pascal}Submission } from '@admin/actions/${p31.actionImportPath}'
|
|
5803
5863
|
|
|
5804
5864
|
const formSchema = z.object({
|
|
5805
|
-
${
|
|
5865
|
+
${p31.zodFields}
|
|
5806
5866
|
})
|
|
5807
5867
|
|
|
5808
5868
|
type FormValues = z.infer<typeof formSchema>
|
|
5809
5869
|
${buildFieldErrorHelper()}
|
|
5810
5870
|
|
|
5811
|
-
${
|
|
5871
|
+
${p31.stepsConst}
|
|
5812
5872
|
|
|
5813
5873
|
const stepParser = createParser({
|
|
5814
5874
|
parse(value) {
|
|
@@ -5826,7 +5886,7 @@ const stepParser = createParser({
|
|
|
5826
5886
|
}
|
|
5827
5887
|
}).withDefault(0)
|
|
5828
5888
|
|
|
5829
|
-
function ${
|
|
5889
|
+
function ${p31.pascal}FormInner() {
|
|
5830
5890
|
const [currentStep, setCurrentStep] = useQueryState('step', stepParser)
|
|
5831
5891
|
const [submitted, setSubmitted] = React.useState(false)
|
|
5832
5892
|
const [submitting, startSubmitTransition] = React.useTransition()
|
|
@@ -5834,11 +5894,11 @@ function ${p30.pascal}FormInner() {
|
|
|
5834
5894
|
const form = useForm<FormValues>({
|
|
5835
5895
|
resolver: standardSchemaResolver(formSchema),
|
|
5836
5896
|
defaultValues: {
|
|
5837
|
-
${
|
|
5897
|
+
${p31.defaults}
|
|
5838
5898
|
},
|
|
5839
5899
|
})
|
|
5840
5900
|
|
|
5841
|
-
${
|
|
5901
|
+
${p31.fieldArraySetup}${p31.watchSetup}
|
|
5842
5902
|
async function handleNext() {
|
|
5843
5903
|
const stepFields = STEPS[currentStep].fields as (keyof FormValues)[]
|
|
5844
5904
|
const isValid = await form.trigger(stepFields, { shouldFocus: true })
|
|
@@ -5854,9 +5914,9 @@ ${p30.fieldArraySetup}${p30.watchSetup}
|
|
|
5854
5914
|
function onSubmit(values: FormValues) {
|
|
5855
5915
|
startSubmitTransition(async () => {
|
|
5856
5916
|
try {
|
|
5857
|
-
const result = await create${
|
|
5917
|
+
const result = await create${p31.pascal}Submission(values)
|
|
5858
5918
|
if (result.success) {
|
|
5859
|
-
${
|
|
5919
|
+
${p31.successHandler}
|
|
5860
5920
|
} else {
|
|
5861
5921
|
form.setError('root', { message: result.error || 'Something went wrong' })
|
|
5862
5922
|
}
|
|
@@ -5870,7 +5930,7 @@ ${p30.fieldArraySetup}${p30.watchSetup}
|
|
|
5870
5930
|
return (
|
|
5871
5931
|
<div className="rounded-sm border p-6 text-center">
|
|
5872
5932
|
<h3 className="text-lg font-semibold">Thank you!</h3>
|
|
5873
|
-
<p className="mt-2 text-muted-foreground">${
|
|
5933
|
+
<p className="mt-2 text-muted-foreground">${p31.successMessage}</p>
|
|
5874
5934
|
</div>
|
|
5875
5935
|
)
|
|
5876
5936
|
}
|
|
@@ -5887,7 +5947,7 @@ ${p30.fieldArraySetup}${p30.watchSetup}
|
|
|
5887
5947
|
|
|
5888
5948
|
{/* Step content */}
|
|
5889
5949
|
<div key={currentStep} className="animate-in fade-in duration-300 space-y-6">
|
|
5890
|
-
${
|
|
5950
|
+
${p31.stepContentBlocks}
|
|
5891
5951
|
</div>
|
|
5892
5952
|
|
|
5893
5953
|
{form.formState.errors.root && (
|
|
@@ -5921,7 +5981,7 @@ ${p30.stepContentBlocks}
|
|
|
5921
5981
|
onClick={() => form.handleSubmit(onSubmit)()}
|
|
5922
5982
|
className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-xs transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
|
|
5923
5983
|
>
|
|
5924
|
-
{submitting ? 'Submitting...' : ${
|
|
5984
|
+
{submitting ? 'Submitting...' : ${p31.submitText}}
|
|
5925
5985
|
</button>
|
|
5926
5986
|
)}
|
|
5927
5987
|
</div>
|
|
@@ -17745,7 +17805,7 @@ function readPresetTemplate(presetId, relativePath) {
|
|
|
17745
17805
|
// adapters/next/snapshots/apply.ts
|
|
17746
17806
|
import fs20 from "fs";
|
|
17747
17807
|
import path24 from "path";
|
|
17748
|
-
import * as
|
|
17808
|
+
import * as p6 from "@clack/prompts";
|
|
17749
17809
|
|
|
17750
17810
|
// core-engine/snapshots/ast-substitution.ts
|
|
17751
17811
|
import { Node, Project } from "ts-morph";
|
|
@@ -18412,7 +18472,7 @@ function isInteractiveSession(interactive) {
|
|
|
18412
18472
|
return interactive && Boolean(process.stdin.isTTY) && process.env.CI !== "true";
|
|
18413
18473
|
}
|
|
18414
18474
|
async function promptNoBaseDecision(filePath) {
|
|
18415
|
-
const answer = await
|
|
18475
|
+
const answer = await p6.select({
|
|
18416
18476
|
message: `File already exists without snapshot base: ${filePath}`,
|
|
18417
18477
|
options: [
|
|
18418
18478
|
{ value: "backup", label: "Backup and overwrite", hint: "recommended" },
|
|
@@ -18421,7 +18481,7 @@ async function promptNoBaseDecision(filePath) {
|
|
|
18421
18481
|
],
|
|
18422
18482
|
initialValue: "backup"
|
|
18423
18483
|
});
|
|
18424
|
-
if (
|
|
18484
|
+
if (p6.isCancel(answer)) {
|
|
18425
18485
|
throw new Error("Generation cancelled.");
|
|
18426
18486
|
}
|
|
18427
18487
|
return answer;
|
|
@@ -19302,18 +19362,18 @@ async function runAddCommand(items, options) {
|
|
|
19302
19362
|
const presetIds = items.filter(isPresetId);
|
|
19303
19363
|
const integrationIds = items.filter(isIntegrationId);
|
|
19304
19364
|
if (!installIntegrationsMode && integrationIds.length > 0) {
|
|
19305
|
-
|
|
19365
|
+
p7.log.error(
|
|
19306
19366
|
`Integration IDs require --integration. Run \`betterstart add --integration ${integrationIds.join(" ")}\`.`
|
|
19307
19367
|
);
|
|
19308
19368
|
process.exit(1);
|
|
19309
19369
|
}
|
|
19310
19370
|
if (installIntegrationsMode && presetIds.length > 0) {
|
|
19311
|
-
|
|
19371
|
+
p7.log.error(`Preset IDs cannot be installed with --integration: ${presetIds.join(", ")}`);
|
|
19312
19372
|
process.exit(1);
|
|
19313
19373
|
}
|
|
19314
19374
|
const invalidItems = installIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
19315
19375
|
if (invalidItems.length > 0) {
|
|
19316
|
-
|
|
19376
|
+
p7.log.error(
|
|
19317
19377
|
installIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
19318
19378
|
);
|
|
19319
19379
|
process.exit(1);
|
|
@@ -19324,7 +19384,7 @@ async function runAddCommand(items, options) {
|
|
|
19324
19384
|
const pm = detectPackageManager(cwd);
|
|
19325
19385
|
const cliSyncResult = await syncProjectCliDependency(cwd, pm);
|
|
19326
19386
|
if (cliSyncResult && !cliSyncResult.success) {
|
|
19327
|
-
|
|
19387
|
+
p7.log.error(cliSyncResult.error ?? "Failed to sync betterstart-cli");
|
|
19328
19388
|
process.exit(1);
|
|
19329
19389
|
}
|
|
19330
19390
|
if (installIntegrationsMode) {
|
|
@@ -19338,10 +19398,10 @@ async function runAddCommand(items, options) {
|
|
|
19338
19398
|
});
|
|
19339
19399
|
writeConfigFile(cwd, result2.config);
|
|
19340
19400
|
if (result2.warnings.length > 0) {
|
|
19341
|
-
|
|
19401
|
+
p7.note(result2.warnings.join("\n"), "Warnings");
|
|
19342
19402
|
}
|
|
19343
19403
|
if (result2.installed.length === 0 && result2.activated.length === 0 && result2.skipped.length > 0) {
|
|
19344
|
-
|
|
19404
|
+
p7.outro(`No changes made. Already installed: ${result2.skipped.join(", ")}`);
|
|
19345
19405
|
return;
|
|
19346
19406
|
}
|
|
19347
19407
|
const conflictPaths2 = scanConflictPaths(cwd);
|
|
@@ -19363,12 +19423,12 @@ async function runAddCommand(items, options) {
|
|
|
19363
19423
|
result2.installed.length > 0 ? `Installed integration${result2.installed.length === 1 ? "" : "s"}: ${result2.installed.join(", ")}` : null,
|
|
19364
19424
|
result2.activated.length > 0 ? `Activated integration${result2.activated.length === 1 ? "" : "s"}: ${result2.activated.join(", ")}` : null
|
|
19365
19425
|
].filter(Boolean);
|
|
19366
|
-
|
|
19426
|
+
p7.outro(messages.join("\n"));
|
|
19367
19427
|
return;
|
|
19368
19428
|
}
|
|
19369
19429
|
const invalidPresets = items.filter((presetId) => !isPresetId(presetId));
|
|
19370
19430
|
if (invalidPresets.length > 0) {
|
|
19371
|
-
|
|
19431
|
+
p7.log.error(formatUnknownPresetMessage(invalidPresets));
|
|
19372
19432
|
process.exit(1);
|
|
19373
19433
|
}
|
|
19374
19434
|
const result = await installPresets({
|
|
@@ -19381,11 +19441,11 @@ async function runAddCommand(items, options) {
|
|
|
19381
19441
|
});
|
|
19382
19442
|
writeConfigFile(cwd, result.config);
|
|
19383
19443
|
if (result.installed.length === 0 && result.skipped.length > 0) {
|
|
19384
|
-
|
|
19444
|
+
p7.outro(`No changes made. Already installed: ${result.skipped.join(", ")}`);
|
|
19385
19445
|
return;
|
|
19386
19446
|
}
|
|
19387
19447
|
if (result.warnings.length > 0) {
|
|
19388
|
-
|
|
19448
|
+
p7.note(result.warnings.join("\n"), "Warnings");
|
|
19389
19449
|
}
|
|
19390
19450
|
const installedSchemaNames = result.installed.flatMap(
|
|
19391
19451
|
(presetId) => getPresetDefinition(presetId).schemaFiles.map((schemaFile) => schemaFile.replace(/\.json$/, ""))
|
|
@@ -19402,14 +19462,14 @@ async function runAddCommand(items, options) {
|
|
|
19402
19462
|
if (conflictPaths.length === 0) {
|
|
19403
19463
|
printAddNextSteps("preset", hasSchemaChanges, postGenerateResult, adminRoutePath);
|
|
19404
19464
|
}
|
|
19405
|
-
|
|
19465
|
+
p7.outro(
|
|
19406
19466
|
`Installed preset${result.installed.length === 1 ? "" : "s"}: ${result.installed.join(", ")}`
|
|
19407
19467
|
);
|
|
19408
19468
|
}
|
|
19409
19469
|
|
|
19410
19470
|
// adapters/next/commands/add-field.ts
|
|
19411
19471
|
import path30 from "path";
|
|
19412
|
-
import * as
|
|
19472
|
+
import * as p11 from "@clack/prompts";
|
|
19413
19473
|
|
|
19414
19474
|
// core-engine/schema/add-field.ts
|
|
19415
19475
|
import fs23 from "fs";
|
|
@@ -20061,7 +20121,7 @@ function getTabFields(tab) {
|
|
|
20061
20121
|
// adapters/next/commands/generate.ts
|
|
20062
20122
|
import fs24 from "fs";
|
|
20063
20123
|
import path29 from "path";
|
|
20064
|
-
import * as
|
|
20124
|
+
import * as p9 from "@clack/prompts";
|
|
20065
20125
|
|
|
20066
20126
|
// core-engine/snapshots/rename-detector.ts
|
|
20067
20127
|
function levenshtein(a, b) {
|
|
@@ -20155,7 +20215,7 @@ function diffSchemas(before, after) {
|
|
|
20155
20215
|
|
|
20156
20216
|
// core-engine/utils/spinner.ts
|
|
20157
20217
|
import { stripVTControlCharacters } from "util";
|
|
20158
|
-
import * as
|
|
20218
|
+
import * as p8 from "@clack/prompts";
|
|
20159
20219
|
var RENDER_OVERHEAD = 7;
|
|
20160
20220
|
var MIN_MESSAGE_WIDTH = 8;
|
|
20161
20221
|
function fitSpinnerMessage(message) {
|
|
@@ -20202,7 +20262,7 @@ function hasActiveSpinner() {
|
|
|
20202
20262
|
return activeSpinners > 0;
|
|
20203
20263
|
}
|
|
20204
20264
|
function spinner2(options) {
|
|
20205
|
-
const inner =
|
|
20265
|
+
const inner = p8.spinner({ ...options, cancelMessage: "Setup cancelled." });
|
|
20206
20266
|
const guided = options?.withGuide !== false;
|
|
20207
20267
|
let started = false;
|
|
20208
20268
|
const setStarted = (next) => {
|
|
@@ -20321,7 +20381,7 @@ function assertSnapshotStateOrExit(cwd) {
|
|
|
20321
20381
|
if (snapshotRootExists(cwd)) {
|
|
20322
20382
|
return;
|
|
20323
20383
|
}
|
|
20324
|
-
|
|
20384
|
+
p9.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
|
|
20325
20385
|
process.exit(1);
|
|
20326
20386
|
}
|
|
20327
20387
|
function printSchemaDiff(scope, loaded, cwd) {
|
|
@@ -20356,14 +20416,14 @@ function printSchemaDiff(scope, loaded, cwd) {
|
|
|
20356
20416
|
` custom cells: +[${diff.customComponents.added.join(", ")}] -[${diff.customComponents.removed.join(", ")}]`
|
|
20357
20417
|
);
|
|
20358
20418
|
}
|
|
20359
|
-
|
|
20419
|
+
p9.log.message(lines.join("\n"));
|
|
20360
20420
|
}
|
|
20361
20421
|
async function promptConfirm(message) {
|
|
20362
|
-
const result = await
|
|
20422
|
+
const result = await p9.confirm({
|
|
20363
20423
|
message,
|
|
20364
20424
|
initialValue: true
|
|
20365
20425
|
});
|
|
20366
|
-
if (
|
|
20426
|
+
if (p9.isCancel(result)) {
|
|
20367
20427
|
throw new Error("Generation cancelled.");
|
|
20368
20428
|
}
|
|
20369
20429
|
return Boolean(result);
|
|
@@ -20493,7 +20553,7 @@ async function maybeBuildRenamePlan(loaded, cwd, config, generatedFiles, options
|
|
|
20493
20553
|
};
|
|
20494
20554
|
if (finalPlan.fields.length === 0 && finalPlan.customCells.length === 0) {
|
|
20495
20555
|
if (validatedCustomCells.warnings.length > 0) {
|
|
20496
|
-
|
|
20556
|
+
p9.log.warn(validatedCustomCells.warnings.join("\n"));
|
|
20497
20557
|
}
|
|
20498
20558
|
return void 0;
|
|
20499
20559
|
}
|
|
@@ -20511,10 +20571,10 @@ async function maybeBuildRenamePlan(loaded, cwd, config, generatedFiles, options
|
|
|
20511
20571
|
if (preview.previewLines.length > previewLines.length) {
|
|
20512
20572
|
renameLines.push(` ... ${preview.previewLines.length - previewLines.length} more change(s)`);
|
|
20513
20573
|
}
|
|
20514
|
-
|
|
20574
|
+
p9.log.message(renameLines.join("\n"));
|
|
20515
20575
|
const warnings = [...validatedCustomCells.warnings, ...preview.warnings];
|
|
20516
20576
|
if (warnings.length > 0) {
|
|
20517
|
-
|
|
20577
|
+
p9.log.warn(warnings.join("\n"));
|
|
20518
20578
|
}
|
|
20519
20579
|
const confirmed = await promptConfirm("Apply these rename substitutions before merge?");
|
|
20520
20580
|
return confirmed ? finalPlan : void 0;
|
|
@@ -20625,7 +20685,7 @@ function printApplySummary(schemaName, summary) {
|
|
|
20625
20685
|
if (summary.skippedCleared.length > 0) {
|
|
20626
20686
|
lines.push(` skip entries cleared: ${summary.skippedCleared.join(", ")}`);
|
|
20627
20687
|
}
|
|
20628
|
-
|
|
20688
|
+
p9.log.message(lines.join("\n"));
|
|
20629
20689
|
}
|
|
20630
20690
|
async function runGenerateCommand(schemaName, options) {
|
|
20631
20691
|
const cwd = options.cwd ? path29.resolve(options.cwd) : process.cwd();
|
|
@@ -20634,7 +20694,7 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20634
20694
|
try {
|
|
20635
20695
|
config = await resolveConfig(cwd);
|
|
20636
20696
|
} catch (error) {
|
|
20637
|
-
|
|
20697
|
+
p9.log.error(`Error loading config: ${error instanceof Error ? error.message : String(error)}`);
|
|
20638
20698
|
process.exit(1);
|
|
20639
20699
|
}
|
|
20640
20700
|
assertSnapshotStateOrExit(cwd);
|
|
@@ -20644,7 +20704,7 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20644
20704
|
if (options.all) {
|
|
20645
20705
|
const schemaNames = listSchemaNames(schemasDir);
|
|
20646
20706
|
if (schemaNames.length === 0) {
|
|
20647
|
-
|
|
20707
|
+
p9.log.error(`No schemas found in ${schemasDir}`);
|
|
20648
20708
|
process.exit(1);
|
|
20649
20709
|
}
|
|
20650
20710
|
const failed = [];
|
|
@@ -20652,14 +20712,14 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20652
20712
|
const processedRoutes = [];
|
|
20653
20713
|
let markdownDepsChecked = false;
|
|
20654
20714
|
const adminRoutePath2 = resolveAdminNamespace(config.frameworkConfig.next.namespace).routePath;
|
|
20655
|
-
|
|
20715
|
+
p9.intro(`BetterStart Generator \u2014 regenerating ${schemaNames.length} schema(s)`);
|
|
20656
20716
|
for (const name of schemaNames) {
|
|
20657
20717
|
if (hasTombstone(cwd, name)) {
|
|
20658
20718
|
if (loadManifest(cwd, name)) {
|
|
20659
20719
|
clearTombstone(cwd, name);
|
|
20660
|
-
|
|
20720
|
+
p9.log.warn(`${name}: tombstone cleared (manifest present)`);
|
|
20661
20721
|
} else {
|
|
20662
|
-
|
|
20722
|
+
p9.log.message(`${name}: skipped (tombstoned)`);
|
|
20663
20723
|
continue;
|
|
20664
20724
|
}
|
|
20665
20725
|
}
|
|
@@ -20685,7 +20745,7 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20685
20745
|
processed.push(name);
|
|
20686
20746
|
processedRoutes.push(getGeneratedSchemaRoutePath(loaded2, adminRoutePath2));
|
|
20687
20747
|
} catch (error) {
|
|
20688
|
-
|
|
20748
|
+
p9.log.error(`${name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
20689
20749
|
failed.push(name);
|
|
20690
20750
|
}
|
|
20691
20751
|
}
|
|
@@ -20708,14 +20768,14 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20708
20768
|
});
|
|
20709
20769
|
}
|
|
20710
20770
|
if (failed.length > 0) {
|
|
20711
|
-
|
|
20771
|
+
p9.log.error(`Failed: ${failed.join(", ")}`);
|
|
20712
20772
|
process.exit(1);
|
|
20713
20773
|
}
|
|
20714
|
-
|
|
20774
|
+
p9.outro(`Regenerated ${processed.length}/${schemaNames.length} schema(s)`);
|
|
20715
20775
|
return;
|
|
20716
20776
|
}
|
|
20717
20777
|
if (!schemaName) {
|
|
20718
|
-
|
|
20778
|
+
p9.log.error("Error: schema name is required (or use --all)");
|
|
20719
20779
|
process.exit(1);
|
|
20720
20780
|
}
|
|
20721
20781
|
let loaded;
|
|
@@ -20723,20 +20783,20 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20723
20783
|
loaded = loadSchema(schemasDir, schemaName);
|
|
20724
20784
|
} catch (error) {
|
|
20725
20785
|
if (error instanceof SchemaNotFoundError) {
|
|
20726
|
-
|
|
20786
|
+
p9.log.error(error.message);
|
|
20727
20787
|
} else {
|
|
20728
|
-
|
|
20788
|
+
p9.log.error(`Error loading schema: ${error instanceof Error ? error.message : String(error)}`);
|
|
20729
20789
|
}
|
|
20730
20790
|
process.exit(1);
|
|
20731
20791
|
}
|
|
20732
20792
|
const validationErrors = validateLoadedSchema(loaded);
|
|
20733
20793
|
if (validationErrors.length > 0) {
|
|
20734
|
-
|
|
20794
|
+
p9.log.error(
|
|
20735
20795
|
["Schema validation failed:", ...validationErrors.map((error) => ` - ${error}`)].join("\n")
|
|
20736
20796
|
);
|
|
20737
20797
|
process.exit(1);
|
|
20738
20798
|
}
|
|
20739
|
-
|
|
20799
|
+
p9.intro(`BetterStart Generator \u2014 ${loaded.schema.name}`);
|
|
20740
20800
|
const needsMarkdownRenderer = schemaNeedsMarkdownRenderer(loaded);
|
|
20741
20801
|
await ensureMarkdownRendererDependencies(cwd, needsMarkdownRenderer);
|
|
20742
20802
|
const result = await applySchemaGeneration(loaded, cwd, config, {
|
|
@@ -20761,38 +20821,38 @@ async function runGenerateCommand(schemaName, options) {
|
|
|
20761
20821
|
adminRoutePath,
|
|
20762
20822
|
schemaRoutePath: getGeneratedSchemaRoutePath(loaded, adminRoutePath)
|
|
20763
20823
|
});
|
|
20764
|
-
|
|
20824
|
+
p9.outro(`Generated ${loaded.schema.name}`);
|
|
20765
20825
|
}
|
|
20766
20826
|
|
|
20767
20827
|
// adapters/next/commands/schema-prompts.ts
|
|
20768
|
-
import * as
|
|
20828
|
+
import * as p10 from "@clack/prompts";
|
|
20769
20829
|
function isInteractiveSession3() {
|
|
20770
20830
|
return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
|
|
20771
20831
|
}
|
|
20772
20832
|
function fail(message) {
|
|
20773
|
-
|
|
20833
|
+
p10.log.error(message);
|
|
20774
20834
|
process.exit(1);
|
|
20775
20835
|
}
|
|
20776
20836
|
function cancel2(context) {
|
|
20777
|
-
|
|
20837
|
+
p10.cancel(context.cancelMessage);
|
|
20778
20838
|
process.exit(0);
|
|
20779
20839
|
}
|
|
20780
20840
|
function cancelIfNeeded(context, value) {
|
|
20781
|
-
if (
|
|
20841
|
+
if (p10.isCancel(value)) {
|
|
20782
20842
|
cancel2(context);
|
|
20783
20843
|
}
|
|
20784
20844
|
return value;
|
|
20785
20845
|
}
|
|
20786
20846
|
async function promptConfirm2(context, message, initialValue = true) {
|
|
20787
|
-
const confirmed = await
|
|
20788
|
-
if (
|
|
20847
|
+
const confirmed = await p10.confirm({ message, initialValue });
|
|
20848
|
+
if (p10.isCancel(confirmed)) {
|
|
20789
20849
|
cancel2(context);
|
|
20790
20850
|
}
|
|
20791
20851
|
return Boolean(confirmed);
|
|
20792
20852
|
}
|
|
20793
20853
|
async function promptText(context, message, optionsOrDefaultValue) {
|
|
20794
20854
|
const options = typeof optionsOrDefaultValue === "string" ? { defaultValue: optionsOrDefaultValue } : optionsOrDefaultValue ?? {};
|
|
20795
|
-
const value = await
|
|
20855
|
+
const value = await p10.text({
|
|
20796
20856
|
message,
|
|
20797
20857
|
defaultValue: options.defaultValue,
|
|
20798
20858
|
placeholder: options.placeholder,
|
|
@@ -20809,7 +20869,7 @@ async function promptText(context, message, optionsOrDefaultValue) {
|
|
|
20809
20869
|
return String(cancelIfNeeded(context, value)).trim();
|
|
20810
20870
|
}
|
|
20811
20871
|
async function promptOptionalText(context, message) {
|
|
20812
|
-
const value = await
|
|
20872
|
+
const value = await p10.text({
|
|
20813
20873
|
message,
|
|
20814
20874
|
placeholder: "Leave blank to skip"
|
|
20815
20875
|
});
|
|
@@ -20817,7 +20877,7 @@ async function promptOptionalText(context, message) {
|
|
|
20817
20877
|
return result || void 0;
|
|
20818
20878
|
}
|
|
20819
20879
|
async function promptSelectValue(context, message, options, initialValue) {
|
|
20820
|
-
const value = await
|
|
20880
|
+
const value = await p10.select({
|
|
20821
20881
|
message,
|
|
20822
20882
|
options,
|
|
20823
20883
|
initialValue
|
|
@@ -21036,7 +21096,7 @@ async function shouldPromptRequired(type) {
|
|
|
21036
21096
|
return !["group", "section", "tabs", "separator"].includes(type);
|
|
21037
21097
|
}
|
|
21038
21098
|
async function promptFormFileOptions(context) {
|
|
21039
|
-
const selected = await
|
|
21099
|
+
const selected = await p10.multiselect({
|
|
21040
21100
|
message: "Field options",
|
|
21041
21101
|
options: [
|
|
21042
21102
|
{ value: "required", label: "Required field?" },
|
|
@@ -21075,7 +21135,7 @@ async function promptFieldOptions(context, kind, type, creatable) {
|
|
|
21075
21135
|
try {
|
|
21076
21136
|
return parseInteractiveOptionsList(value);
|
|
21077
21137
|
} catch (error) {
|
|
21078
|
-
|
|
21138
|
+
p10.log.error(error instanceof Error ? error.message : String(error));
|
|
21079
21139
|
}
|
|
21080
21140
|
}
|
|
21081
21141
|
}
|
|
@@ -21193,7 +21253,7 @@ async function promptChildFields(context, kind, schemasDir, scope, fields, depth
|
|
|
21193
21253
|
const addChild = fields.length === 0 ? await promptConfirm2(context, "Add a child field?", true) : await promptConfirm2(context, "Add another child field?", false);
|
|
21194
21254
|
if (!addChild) {
|
|
21195
21255
|
if (fields.length === 0) {
|
|
21196
|
-
|
|
21256
|
+
p10.log.warn("Containers need at least one child field.");
|
|
21197
21257
|
continue;
|
|
21198
21258
|
}
|
|
21199
21259
|
return;
|
|
@@ -21218,7 +21278,7 @@ async function promptTabsField(context, kind, schemasDir, scope, name, label, de
|
|
|
21218
21278
|
const addTab = field.tabs.length === 0 ? await promptConfirm2(context, "Add a tab?", true) : await promptConfirm2(context, "Add another tab?", false);
|
|
21219
21279
|
if (!addTab) {
|
|
21220
21280
|
if (field.tabs.length === 0) {
|
|
21221
|
-
|
|
21281
|
+
p10.log.warn("Tabs need at least one tab.");
|
|
21222
21282
|
continue;
|
|
21223
21283
|
}
|
|
21224
21284
|
return field;
|
|
@@ -21243,7 +21303,7 @@ async function promptTabsField(context, kind, schemasDir, scope, name, label, de
|
|
|
21243
21303
|
const addChild = mainFields.length + sidebarFields.length === 0 ? await promptConfirm2(context, "Add a tab child field?", true) : await promptConfirm2(context, "Add another tab child field?", false);
|
|
21244
21304
|
if (!addChild) {
|
|
21245
21305
|
if (mainFields.length + sidebarFields.length === 0) {
|
|
21246
|
-
|
|
21306
|
+
p10.log.warn("Tabs need at least one child field.");
|
|
21247
21307
|
continue;
|
|
21248
21308
|
}
|
|
21249
21309
|
break;
|
|
@@ -21314,7 +21374,7 @@ async function applyAdvancedOptions(context, field, kind, type, options) {
|
|
|
21314
21374
|
if (Number.isInteger(parsed) && parsed > 0) {
|
|
21315
21375
|
record.length = parsed;
|
|
21316
21376
|
} else {
|
|
21317
|
-
|
|
21377
|
+
p10.log.warn("Skipped invalid length.");
|
|
21318
21378
|
}
|
|
21319
21379
|
}
|
|
21320
21380
|
}
|
|
@@ -21472,11 +21532,11 @@ function hasNonInteractiveFieldOptions(options) {
|
|
|
21472
21532
|
);
|
|
21473
21533
|
}
|
|
21474
21534
|
function fail2(message) {
|
|
21475
|
-
|
|
21535
|
+
p11.log.error(message);
|
|
21476
21536
|
process.exit(1);
|
|
21477
21537
|
}
|
|
21478
21538
|
function cancel4(message = "Add field cancelled.") {
|
|
21479
|
-
|
|
21539
|
+
p11.cancel(message);
|
|
21480
21540
|
process.exit(0);
|
|
21481
21541
|
}
|
|
21482
21542
|
function schemaNameFromLoaded(loaded) {
|
|
@@ -21581,7 +21641,7 @@ function printPreview(loaded, owner, firstTimeGeneration, insertion, options) {
|
|
|
21581
21641
|
} else {
|
|
21582
21642
|
lines.push("schema integration: none");
|
|
21583
21643
|
}
|
|
21584
|
-
|
|
21644
|
+
p11.note(
|
|
21585
21645
|
`${lines.join("\n")}
|
|
21586
21646
|
|
|
21587
21647
|
${stringifyProjectJson(insertion.field).trim()}`,
|
|
@@ -21614,7 +21674,7 @@ Re-run with --yes to confirm these warning cases.`);
|
|
|
21614
21674
|
}
|
|
21615
21675
|
return;
|
|
21616
21676
|
}
|
|
21617
|
-
|
|
21677
|
+
p11.note(warnings.join("\n"), "Warnings");
|
|
21618
21678
|
const confirmed = await promptConfirm3("Continue with these warnings?", true);
|
|
21619
21679
|
if (!confirmed) {
|
|
21620
21680
|
cancel4();
|
|
@@ -21731,7 +21791,7 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
21731
21791
|
}
|
|
21732
21792
|
}
|
|
21733
21793
|
writeAuthoredGeneratedSchema(loaded);
|
|
21734
|
-
|
|
21794
|
+
p11.log.success(`Updated ${path30.relative(cwd, loaded.filePath)}`);
|
|
21735
21795
|
try {
|
|
21736
21796
|
await runGenerateCommand(selectedSchemaName, {
|
|
21737
21797
|
force: false,
|
|
@@ -21742,8 +21802,8 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
21742
21802
|
cwd
|
|
21743
21803
|
});
|
|
21744
21804
|
} catch (error) {
|
|
21745
|
-
|
|
21746
|
-
|
|
21805
|
+
p11.log.error(error instanceof Error ? error.message : String(error));
|
|
21806
|
+
p11.log.info(
|
|
21747
21807
|
`Schema JSON was kept. Re-run \`betterstart generate ${selectedSchemaName}${options.skipMigration ? " --skip-migration" : ""}\` after resolving the issue.`
|
|
21748
21808
|
);
|
|
21749
21809
|
process.exit(1);
|
|
@@ -21753,7 +21813,7 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
21753
21813
|
// adapters/next/commands/create.ts
|
|
21754
21814
|
import fs25 from "fs";
|
|
21755
21815
|
import path31 from "path";
|
|
21756
|
-
import * as
|
|
21816
|
+
import * as p12 from "@clack/prompts";
|
|
21757
21817
|
var CREATE_PROMPT_CONTEXT = {
|
|
21758
21818
|
cancelMessage: "Create schema cancelled."
|
|
21759
21819
|
};
|
|
@@ -21944,7 +22004,7 @@ async function promptTabSlotFields(kind, schemasDir, titleField) {
|
|
|
21944
22004
|
);
|
|
21945
22005
|
if (!addField) {
|
|
21946
22006
|
if (!hasFields) {
|
|
21947
|
-
|
|
22007
|
+
p12.log.warn("Tabs need at least one child field.");
|
|
21948
22008
|
continue;
|
|
21949
22009
|
}
|
|
21950
22010
|
return { main, sidebar };
|
|
@@ -21992,7 +22052,7 @@ async function promptSchemaTab(kind, schemasDir, titleField, existingTabs) {
|
|
|
21992
22052
|
while (fields.length === 0) {
|
|
21993
22053
|
await promptAdditionalSchemaFields(kind, schemasDir, fields);
|
|
21994
22054
|
if (fields.length === 0) {
|
|
21995
|
-
|
|
22055
|
+
p12.log.warn("Tabs need at least one child field.");
|
|
21996
22056
|
}
|
|
21997
22057
|
}
|
|
21998
22058
|
}
|
|
@@ -22082,7 +22142,7 @@ async function promptFormSubmissionColumns(schema) {
|
|
|
22082
22142
|
}
|
|
22083
22143
|
const existingColumnNames = schema.columns ? new Set(schema.columns.map((column) => column.accessorKey)) : void 0;
|
|
22084
22144
|
const initialValues = existingColumnNames ? fields.filter((field) => existingColumnNames.has(field.name)).map((field) => field.name) : fields.map((field) => field.name);
|
|
22085
|
-
const selected = await
|
|
22145
|
+
const selected = await p12.multiselect({
|
|
22086
22146
|
message: "Submission table columns",
|
|
22087
22147
|
options: fields.map((field) => ({
|
|
22088
22148
|
value: field.name,
|
|
@@ -22091,7 +22151,7 @@ async function promptFormSubmissionColumns(schema) {
|
|
|
22091
22151
|
initialValues,
|
|
22092
22152
|
required: false
|
|
22093
22153
|
});
|
|
22094
|
-
if (
|
|
22154
|
+
if (p12.isCancel(selected)) {
|
|
22095
22155
|
cancel2(CREATE_PROMPT_CONTEXT);
|
|
22096
22156
|
}
|
|
22097
22157
|
const selectedNames = new Set(selected);
|
|
@@ -22151,7 +22211,7 @@ function schemaFilePath(kind, schemasDir, schemaName) {
|
|
|
22151
22211
|
return kind === "form" ? path31.join(schemasDir, "forms", `${schemaName}.json`) : path31.join(schemasDir, `${schemaName}.json`);
|
|
22152
22212
|
}
|
|
22153
22213
|
function printPreview2(loaded, cwd) {
|
|
22154
|
-
|
|
22214
|
+
p12.note(
|
|
22155
22215
|
`schema: ${loaded.name} (${loaded.kind})
|
|
22156
22216
|
path: ${path31.relative(cwd, loaded.filePath)}
|
|
22157
22217
|
owner: user
|
|
@@ -22204,7 +22264,7 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
22204
22264
|
}
|
|
22205
22265
|
fs25.mkdirSync(path31.dirname(filePath), { recursive: true });
|
|
22206
22266
|
writeAuthoredGeneratedSchema(loaded);
|
|
22207
|
-
|
|
22267
|
+
p12.log.success(`Created ${path31.relative(cwd, filePath)}`);
|
|
22208
22268
|
try {
|
|
22209
22269
|
await runGenerateCommand(metadata.name, {
|
|
22210
22270
|
force: false,
|
|
@@ -22215,8 +22275,8 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
|
|
|
22215
22275
|
cwd
|
|
22216
22276
|
});
|
|
22217
22277
|
} catch (error) {
|
|
22218
|
-
|
|
22219
|
-
|
|
22278
|
+
p12.log.error(error instanceof Error ? error.message : String(error));
|
|
22279
|
+
p12.log.info(
|
|
22220
22280
|
`Schema JSON was kept. Re-run \`betterstart generate ${metadata.name}${options.skipMigration ? " --skip-migration" : ""}\` after resolving the issue.`
|
|
22221
22281
|
);
|
|
22222
22282
|
process.exit(1);
|
|
@@ -22228,14 +22288,14 @@ import { execFileSync as execFileSync5, spawn as spawn6 } from "child_process";
|
|
|
22228
22288
|
import fs41 from "fs";
|
|
22229
22289
|
import path52 from "path";
|
|
22230
22290
|
import { PassThrough } from "stream";
|
|
22231
|
-
import * as
|
|
22291
|
+
import * as p25 from "@clack/prompts";
|
|
22232
22292
|
|
|
22233
22293
|
// core-engine/utils/cancel-guard.ts
|
|
22234
|
-
import * as
|
|
22294
|
+
import * as p13 from "@clack/prompts";
|
|
22235
22295
|
function installSetupCancelGuard() {
|
|
22236
22296
|
const onSignal = () => {
|
|
22237
22297
|
if (!hasActiveSpinner()) {
|
|
22238
|
-
|
|
22298
|
+
p13.cancel("Setup cancelled.");
|
|
22239
22299
|
}
|
|
22240
22300
|
process.exit(0);
|
|
22241
22301
|
};
|
|
@@ -22290,11 +22350,11 @@ function redactSecrets(text7) {
|
|
|
22290
22350
|
|
|
22291
22351
|
// adapters/next/init/prompts/database.ts
|
|
22292
22352
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22293
|
-
import * as
|
|
22353
|
+
import * as p14 from "@clack/prompts";
|
|
22294
22354
|
import pc from "picocolors";
|
|
22295
22355
|
var VERCEL_NEON_URL = "https://vercel.com/dashboard/integrations/checkout/neon";
|
|
22296
22356
|
async function promptServices() {
|
|
22297
|
-
const choice = await
|
|
22357
|
+
const choice = await p14.select({
|
|
22298
22358
|
message: "Connect a PostgreSQL Database",
|
|
22299
22359
|
options: [
|
|
22300
22360
|
{
|
|
@@ -22315,8 +22375,8 @@ async function promptServices() {
|
|
|
22315
22375
|
],
|
|
22316
22376
|
initialValue: "vercel"
|
|
22317
22377
|
});
|
|
22318
|
-
if (
|
|
22319
|
-
|
|
22378
|
+
if (p14.isCancel(choice)) {
|
|
22379
|
+
p14.cancel("Setup cancelled.");
|
|
22320
22380
|
process.exit(0);
|
|
22321
22381
|
}
|
|
22322
22382
|
if (choice === "vercel") {
|
|
@@ -22330,7 +22390,7 @@ async function promptServices() {
|
|
|
22330
22390
|
}
|
|
22331
22391
|
function openBrowserVercelNeon() {
|
|
22332
22392
|
openBrowser(VERCEL_NEON_URL);
|
|
22333
|
-
|
|
22393
|
+
p14.log.info(
|
|
22334
22394
|
`Opening Vercel... Create a Neon Postgres database, then copy the ${pc.cyan("DATABASE_URL")} from the dashboard.`
|
|
22335
22395
|
);
|
|
22336
22396
|
}
|
|
@@ -22340,12 +22400,12 @@ function openBrowserVercelNeonResource(url) {
|
|
|
22340
22400
|
return;
|
|
22341
22401
|
}
|
|
22342
22402
|
openBrowser(url);
|
|
22343
|
-
|
|
22403
|
+
p14.log.info(
|
|
22344
22404
|
`Opening Vercel... Copy the Neon ${pc.cyan("DATABASE_URL")} from the database dashboard, then paste it below.`
|
|
22345
22405
|
);
|
|
22346
22406
|
}
|
|
22347
22407
|
async function promptConnectionString() {
|
|
22348
|
-
const input = await
|
|
22408
|
+
const input = await p14.text({
|
|
22349
22409
|
message: "Paste your PostgreSQL connection string",
|
|
22350
22410
|
placeholder: "postgres://user:pass@host/db",
|
|
22351
22411
|
validate(val) {
|
|
@@ -22359,8 +22419,8 @@ async function promptConnectionString() {
|
|
|
22359
22419
|
}
|
|
22360
22420
|
}
|
|
22361
22421
|
});
|
|
22362
|
-
if (
|
|
22363
|
-
|
|
22422
|
+
if (p14.isCancel(input)) {
|
|
22423
|
+
p14.cancel("Setup cancelled.");
|
|
22364
22424
|
process.exit(0);
|
|
22365
22425
|
}
|
|
22366
22426
|
return input.replace(/^['"]|['"]$/g, "").trim();
|
|
@@ -22380,7 +22440,7 @@ function openBrowser(url) {
|
|
|
22380
22440
|
}
|
|
22381
22441
|
|
|
22382
22442
|
// adapters/next/init/prompts/presets.ts
|
|
22383
|
-
import * as
|
|
22443
|
+
import * as p15 from "@clack/prompts";
|
|
22384
22444
|
|
|
22385
22445
|
// adapters/next/init/scaffolders/env.ts
|
|
22386
22446
|
import crypto2 from "crypto";
|
|
@@ -22545,7 +22605,7 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22545
22605
|
overwriteKeys.add(key);
|
|
22546
22606
|
}
|
|
22547
22607
|
};
|
|
22548
|
-
const storage = await
|
|
22608
|
+
const storage = await p15.select({
|
|
22549
22609
|
message: "Choose a file storage",
|
|
22550
22610
|
options: [
|
|
22551
22611
|
{
|
|
@@ -22569,8 +22629,8 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22569
22629
|
],
|
|
22570
22630
|
initialValue: "vercel-blob"
|
|
22571
22631
|
});
|
|
22572
|
-
if (
|
|
22573
|
-
|
|
22632
|
+
if (p15.isCancel(storage)) {
|
|
22633
|
+
p15.cancel("Setup cancelled.");
|
|
22574
22634
|
process.exit(0);
|
|
22575
22635
|
}
|
|
22576
22636
|
if (storage === "r2") {
|
|
@@ -22580,7 +22640,7 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22580
22640
|
if (flow?.ok && flow.config) {
|
|
22581
22641
|
mergeIntegrationConfig(flow.config);
|
|
22582
22642
|
} else if (flow) {
|
|
22583
|
-
|
|
22643
|
+
p15.log.warn(
|
|
22584
22644
|
"Continuing without Railway bucket credentials \u2014 rerun betterstart add --integration railway-bucket after fixing Railway access."
|
|
22585
22645
|
);
|
|
22586
22646
|
} else {
|
|
@@ -22597,7 +22657,7 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22597
22657
|
});
|
|
22598
22658
|
overwriteKeys.add("BLOB_READ_WRITE_TOKEN");
|
|
22599
22659
|
} else if (flow) {
|
|
22600
|
-
|
|
22660
|
+
p15.log.warn(
|
|
22601
22661
|
"Continuing without a Blob token \u2014 add BLOB_READ_WRITE_TOKEN to .env.local from the store on vercel.com/dashboard/stores."
|
|
22602
22662
|
);
|
|
22603
22663
|
sections.push({
|
|
@@ -22606,7 +22666,7 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22606
22666
|
});
|
|
22607
22667
|
} else {
|
|
22608
22668
|
if (existingToken) {
|
|
22609
|
-
|
|
22669
|
+
p15.log.info(
|
|
22610
22670
|
`Using the existing BLOB_READ_WRITE_TOKEN from .env.local ${pc2.dim(
|
|
22611
22671
|
`(${maskBlobToken(existingToken)})`
|
|
22612
22672
|
)}`
|
|
@@ -22615,7 +22675,7 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22615
22675
|
mergeIntegrationConfig(await collectIntegrationConfig(cwd, ["vercel-blob"]));
|
|
22616
22676
|
}
|
|
22617
22677
|
}
|
|
22618
|
-
const selectedPresets = await
|
|
22678
|
+
const selectedPresets = await p15.multiselect({
|
|
22619
22679
|
message: "Select presets",
|
|
22620
22680
|
options: [
|
|
22621
22681
|
{
|
|
@@ -22627,8 +22687,8 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22627
22687
|
required: false,
|
|
22628
22688
|
initialValues: ["blog"]
|
|
22629
22689
|
});
|
|
22630
|
-
if (
|
|
22631
|
-
|
|
22690
|
+
if (p15.isCancel(selectedPresets)) {
|
|
22691
|
+
p15.cancel("Setup cancelled.");
|
|
22632
22692
|
process.exit(0);
|
|
22633
22693
|
}
|
|
22634
22694
|
const integrations = [];
|
|
@@ -22655,9 +22715,9 @@ async function promptPresets(cwd, options = {}) {
|
|
|
22655
22715
|
}
|
|
22656
22716
|
|
|
22657
22717
|
// adapters/next/init/prompts/project.ts
|
|
22658
|
-
import * as
|
|
22718
|
+
import * as p16 from "@clack/prompts";
|
|
22659
22719
|
async function promptProject(defaultName) {
|
|
22660
|
-
const projectName = await
|
|
22720
|
+
const projectName = await p16.text({
|
|
22661
22721
|
message: "What is your project named?",
|
|
22662
22722
|
placeholder: defaultName ?? "(Press Enter to use default)",
|
|
22663
22723
|
defaultValue: defaultName ?? ".",
|
|
@@ -22670,15 +22730,15 @@ async function promptProject(defaultName) {
|
|
|
22670
22730
|
return void 0;
|
|
22671
22731
|
}
|
|
22672
22732
|
});
|
|
22673
|
-
if (
|
|
22674
|
-
|
|
22733
|
+
if (p16.isCancel(projectName)) {
|
|
22734
|
+
p16.cancel("Setup cancelled.");
|
|
22675
22735
|
process.exit(0);
|
|
22676
22736
|
}
|
|
22677
22737
|
return { projectName: projectName.trim() || "." };
|
|
22678
22738
|
}
|
|
22679
22739
|
|
|
22680
22740
|
// adapters/next/init/providers.ts
|
|
22681
|
-
import * as
|
|
22741
|
+
import * as p17 from "@clack/prompts";
|
|
22682
22742
|
var DATABASE_PROVIDERS = ["vercel", "railway", "manual"];
|
|
22683
22743
|
var STORAGE_PROVIDERS = ["vercel-blob", "railway-bucket", "r2", "local"];
|
|
22684
22744
|
var DEPLOY_PROVIDERS = ["vercel", "railway", "none"];
|
|
@@ -22735,7 +22795,7 @@ function validateResolvedDatabaseProvider(provider, options) {
|
|
|
22735
22795
|
}
|
|
22736
22796
|
}
|
|
22737
22797
|
async function promptDeployProvider(initialValue = "none") {
|
|
22738
|
-
const provider = await
|
|
22798
|
+
const provider = await p17.select({
|
|
22739
22799
|
message: "Deploy this project",
|
|
22740
22800
|
options: [
|
|
22741
22801
|
{
|
|
@@ -22753,8 +22813,8 @@ async function promptDeployProvider(initialValue = "none") {
|
|
|
22753
22813
|
],
|
|
22754
22814
|
initialValue
|
|
22755
22815
|
});
|
|
22756
|
-
if (
|
|
22757
|
-
|
|
22816
|
+
if (p17.isCancel(provider)) {
|
|
22817
|
+
p17.cancel("Setup cancelled.");
|
|
22758
22818
|
process.exit(0);
|
|
22759
22819
|
}
|
|
22760
22820
|
return provider;
|
|
@@ -22763,7 +22823,7 @@ async function promptDeployProvider(initialValue = "none") {
|
|
|
22763
22823
|
// adapters/next/init/railway/deploy.ts
|
|
22764
22824
|
import fs28 from "fs";
|
|
22765
22825
|
import path34 from "path";
|
|
22766
|
-
import * as
|
|
22826
|
+
import * as p19 from "@clack/prompts";
|
|
22767
22827
|
|
|
22768
22828
|
// adapters/next/init/deploy/guard.ts
|
|
22769
22829
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -22860,7 +22920,7 @@ function guardBetterstartConfig(cwd, restores) {
|
|
|
22860
22920
|
}
|
|
22861
22921
|
|
|
22862
22922
|
// adapters/next/init/railway/project.ts
|
|
22863
|
-
import * as
|
|
22923
|
+
import * as p18 from "@clack/prompts";
|
|
22864
22924
|
|
|
22865
22925
|
// adapters/next/init/railway/runner.ts
|
|
22866
22926
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -23144,15 +23204,15 @@ async function ensureRailwayProject(runner, options) {
|
|
|
23144
23204
|
createWorkspace = options.workspaces[0]?.id;
|
|
23145
23205
|
} else if (!createWorkspace && options.interactive && options.workspaces?.length) {
|
|
23146
23206
|
projectSpinner.clear();
|
|
23147
|
-
const workspace = await
|
|
23207
|
+
const workspace = await p18.select({
|
|
23148
23208
|
message: "Choose a Railway workspace",
|
|
23149
23209
|
options: options.workspaces.map((candidate) => ({
|
|
23150
23210
|
value: candidate.id,
|
|
23151
23211
|
label: candidate.name
|
|
23152
23212
|
}))
|
|
23153
23213
|
});
|
|
23154
|
-
if (
|
|
23155
|
-
|
|
23214
|
+
if (p18.isCancel(workspace)) {
|
|
23215
|
+
p18.cancel("Setup cancelled.");
|
|
23156
23216
|
process.exit(0);
|
|
23157
23217
|
}
|
|
23158
23218
|
createWorkspace = workspace;
|
|
@@ -23678,7 +23738,7 @@ async function runRailwayDeployFlow(options) {
|
|
|
23678
23738
|
);
|
|
23679
23739
|
envSpinner.clear();
|
|
23680
23740
|
for (const key of sync.failed) {
|
|
23681
|
-
|
|
23741
|
+
p19.log.warn(`Could not set ${pc4.cyan(key)} on Railway.`);
|
|
23682
23742
|
}
|
|
23683
23743
|
if (sync.failed.length > 0) {
|
|
23684
23744
|
return {
|
|
@@ -23693,12 +23753,12 @@ async function runRailwayDeployFlow(options) {
|
|
|
23693
23753
|
const packageGuard = await guardProjectForDeploy(options.cwd);
|
|
23694
23754
|
guardSpinner.clear();
|
|
23695
23755
|
if (packageGuard.lockfile === "failed") {
|
|
23696
|
-
|
|
23756
|
+
p19.log.warn(
|
|
23697
23757
|
"Could not refresh pnpm-lock.yaml after removing betterstart-cli \u2014 the remote install may fail."
|
|
23698
23758
|
);
|
|
23699
23759
|
}
|
|
23700
23760
|
for (const dependency of packageGuard.localSpecDeps) {
|
|
23701
|
-
|
|
23761
|
+
p19.log.warn(
|
|
23702
23762
|
`Dependency ${pc4.cyan(dependency)} uses a local spec that cannot install on Railway.`
|
|
23703
23763
|
);
|
|
23704
23764
|
}
|
|
@@ -23751,7 +23811,7 @@ ${deploy.stderr}`) ?? deploy.errorMessage
|
|
|
23751
23811
|
}
|
|
23752
23812
|
|
|
23753
23813
|
// adapters/next/init/railway/auth.ts
|
|
23754
|
-
import * as
|
|
23814
|
+
import * as p20 from "@clack/prompts";
|
|
23755
23815
|
import pc5 from "picocolors";
|
|
23756
23816
|
var WHOAMI_TIMEOUT_MS = 3e4;
|
|
23757
23817
|
var LOGIN_TIMEOUT_MS = 3e5;
|
|
@@ -23821,7 +23881,7 @@ async function ensureRailwayAuth(runner, cwd, options) {
|
|
|
23821
23881
|
return { authed: false, reason: existing.reason };
|
|
23822
23882
|
}
|
|
23823
23883
|
checkSpinner.clear();
|
|
23824
|
-
|
|
23884
|
+
p20.log.info(
|
|
23825
23885
|
"Sign in to Railway to continue. Railway will open your browser or show a device code."
|
|
23826
23886
|
);
|
|
23827
23887
|
const login = await runRailway(runner, ["login"], {
|
|
@@ -25708,11 +25768,11 @@ function scaffoldTsconfig(cwd, config) {
|
|
|
25708
25768
|
}
|
|
25709
25769
|
|
|
25710
25770
|
// adapters/next/init/vercel/flow.ts
|
|
25711
|
-
import * as
|
|
25771
|
+
import * as p24 from "@clack/prompts";
|
|
25712
25772
|
import pc9 from "picocolors";
|
|
25713
25773
|
|
|
25714
25774
|
// adapters/next/init/vercel/auth.ts
|
|
25715
|
-
import * as
|
|
25775
|
+
import * as p21 from "@clack/prompts";
|
|
25716
25776
|
import pc6 from "picocolors";
|
|
25717
25777
|
|
|
25718
25778
|
// adapters/next/init/vercel/runner.ts
|
|
@@ -25956,7 +26016,7 @@ async function ensureVercelAuth(runner, cwd, options) {
|
|
|
25956
26016
|
checkSpinner.clear();
|
|
25957
26017
|
const signInMessage = `Sign in to Vercel to continue ${pc6.dim("(or press Ctrl-C to enter a connection string manually)")}`;
|
|
25958
26018
|
const signInRows = clackLogRows(signInMessage);
|
|
25959
|
-
|
|
26019
|
+
p21.log.info(signInMessage);
|
|
25960
26020
|
let streamedRows = 0;
|
|
25961
26021
|
const login = await runVercel(runner, ["login"], {
|
|
25962
26022
|
cwd,
|
|
@@ -25988,7 +26048,7 @@ function signedInMessage(username) {
|
|
|
25988
26048
|
}
|
|
25989
26049
|
|
|
25990
26050
|
// adapters/next/init/vercel/blob.ts
|
|
25991
|
-
import * as
|
|
26051
|
+
import * as p22 from "@clack/prompts";
|
|
25992
26052
|
import pc7 from "picocolors";
|
|
25993
26053
|
|
|
25994
26054
|
// adapters/next/init/vercel/env-pull.ts
|
|
@@ -26230,7 +26290,7 @@ async function provisionBlobStoreInteractive(runner, cwd, options) {
|
|
|
26230
26290
|
if (terminalFallbackRan) break;
|
|
26231
26291
|
terminalFallbackRan = true;
|
|
26232
26292
|
quietSpinner.clear();
|
|
26233
|
-
|
|
26293
|
+
p22.log.info(
|
|
26234
26294
|
`Create your Blob store in the Vercel prompts below ${pc7.dim(
|
|
26235
26295
|
"(connect it to all environments)."
|
|
26236
26296
|
)}`
|
|
@@ -26429,7 +26489,7 @@ function guardEnvLocal(cwd) {
|
|
|
26429
26489
|
}
|
|
26430
26490
|
|
|
26431
26491
|
// adapters/next/init/vercel/neon.ts
|
|
26432
|
-
import * as
|
|
26492
|
+
import * as p23 from "@clack/prompts";
|
|
26433
26493
|
import pc8 from "picocolors";
|
|
26434
26494
|
var PROVISION_TIMEOUT_MS2 = 18e4;
|
|
26435
26495
|
var INTERACTIVE_PROVISION_TIMEOUT_MS2 = 6e5;
|
|
@@ -26448,7 +26508,7 @@ async function provisionNeonInteractive(runner, cwd, options) {
|
|
|
26448
26508
|
termsResolved = true;
|
|
26449
26509
|
quietSpinner.clear();
|
|
26450
26510
|
eraseRows(termsNotice.rows);
|
|
26451
|
-
|
|
26511
|
+
p23.log.step(termsNotice.text);
|
|
26452
26512
|
};
|
|
26453
26513
|
const quiet = await runVercel(runner, neonAddArgs(options), {
|
|
26454
26514
|
cwd,
|
|
@@ -26467,7 +26527,7 @@ ${pc8.dim(termsUrl)}`,
|
|
|
26467
26527
|
rows: clackLogRows(message) + clackLogRows(termsUrl) - 1
|
|
26468
26528
|
};
|
|
26469
26529
|
quietSpinner.clear();
|
|
26470
|
-
|
|
26530
|
+
p23.log.info(termsNotice.text);
|
|
26471
26531
|
quietSpinner.start("Waiting for the terms to be accepted");
|
|
26472
26532
|
return;
|
|
26473
26533
|
}
|
|
@@ -26483,7 +26543,7 @@ ${pc8.dim(termsUrl)}`,
|
|
|
26483
26543
|
return readNeonProvisionInfo(quiet.stdout);
|
|
26484
26544
|
}
|
|
26485
26545
|
quietSpinner.clear();
|
|
26486
|
-
|
|
26546
|
+
p23.log.info(
|
|
26487
26547
|
`Create your Neon database in the Vercel prompts below ${pc8.dim(
|
|
26488
26548
|
"(the Free plan is recommended)."
|
|
26489
26549
|
)}`
|
|
@@ -26560,14 +26620,14 @@ async function runVercelNeonFlow(options) {
|
|
|
26560
26620
|
allowLogin: options.interactive
|
|
26561
26621
|
});
|
|
26562
26622
|
if (!auth.authed) {
|
|
26563
|
-
|
|
26623
|
+
p24.log.warn(authFailureMessage(auth.reason));
|
|
26564
26624
|
return { ok: false };
|
|
26565
26625
|
}
|
|
26566
26626
|
await ensureLinkedProject(runner, options.cwd, options.projectName, env, auth.username);
|
|
26567
26627
|
const neon = await provisionNeonForMode(runner, options);
|
|
26568
26628
|
if (neon.failure) {
|
|
26569
|
-
|
|
26570
|
-
if (neon.detail)
|
|
26629
|
+
p24.log.warn(neonFailureMessage(neon.failure));
|
|
26630
|
+
if (neon.detail) p24.log.message(pc9.dim(redactSecrets(neon.detail)));
|
|
26571
26631
|
return { ok: false };
|
|
26572
26632
|
}
|
|
26573
26633
|
const databaseUrl = await pullNeonDatabaseUrl(runner, options.cwd, env);
|
|
@@ -26580,7 +26640,7 @@ async function runVercelNeonFlow(options) {
|
|
|
26580
26640
|
dismissSignedInNote
|
|
26581
26641
|
};
|
|
26582
26642
|
} catch (error) {
|
|
26583
|
-
|
|
26643
|
+
p24.log.warn(
|
|
26584
26644
|
`Vercel provisioning failed: ${error instanceof Error ? error.message : String(error)}`
|
|
26585
26645
|
);
|
|
26586
26646
|
return { ok: false };
|
|
@@ -26602,14 +26662,14 @@ async function runVercelBlobFlow(options) {
|
|
|
26602
26662
|
allowLogin: options.interactive
|
|
26603
26663
|
});
|
|
26604
26664
|
if (!auth.authed) {
|
|
26605
|
-
|
|
26665
|
+
p24.log.warn(authFailureMessage(auth.reason));
|
|
26606
26666
|
return { ok: false };
|
|
26607
26667
|
}
|
|
26608
26668
|
await ensureLinkedProject(runner, options.cwd, options.projectName, env, auth.username);
|
|
26609
26669
|
const blob = await provisionBlobForMode(runner, options);
|
|
26610
26670
|
if (blob.failure || !blob.token) {
|
|
26611
|
-
|
|
26612
|
-
if (blob.detail)
|
|
26671
|
+
p24.log.warn(blobFailureMessage(blob.failure));
|
|
26672
|
+
if (blob.detail) p24.log.message(pc9.dim(redactSecrets(blob.detail)));
|
|
26613
26673
|
return { ok: false };
|
|
26614
26674
|
}
|
|
26615
26675
|
return {
|
|
@@ -26618,7 +26678,7 @@ async function runVercelBlobFlow(options) {
|
|
|
26618
26678
|
blobStoreName: blob.storeName
|
|
26619
26679
|
};
|
|
26620
26680
|
} catch (error) {
|
|
26621
|
-
|
|
26681
|
+
p24.log.warn(
|
|
26622
26682
|
`Vercel provisioning failed: ${error instanceof Error ? error.message : String(error)}`
|
|
26623
26683
|
);
|
|
26624
26684
|
return { ok: false };
|
|
@@ -26640,7 +26700,7 @@ async function runVercelDeployFlow(options) {
|
|
|
26640
26700
|
allowLogin: options.interactive ?? true
|
|
26641
26701
|
});
|
|
26642
26702
|
if (!auth.authed) {
|
|
26643
|
-
|
|
26703
|
+
p24.log.warn(authFailureMessage(auth.reason));
|
|
26644
26704
|
printManualDeployHint();
|
|
26645
26705
|
return { ok: false };
|
|
26646
26706
|
}
|
|
@@ -26650,7 +26710,7 @@ async function runVercelDeployFlow(options) {
|
|
|
26650
26710
|
const sync = await syncVercelProductionEnv(runner, options.cwd, env);
|
|
26651
26711
|
envSpinner.clear();
|
|
26652
26712
|
for (const key of sync.failed) {
|
|
26653
|
-
|
|
26713
|
+
p24.log.warn(
|
|
26654
26714
|
`Could not set ${pc9.cyan(key)} on Vercel \u2014 add it in the project's environment settings.`
|
|
26655
26715
|
);
|
|
26656
26716
|
}
|
|
@@ -26660,12 +26720,12 @@ async function runVercelDeployFlow(options) {
|
|
|
26660
26720
|
const packageGuard = await guardProjectForDeploy(options.cwd);
|
|
26661
26721
|
guardSpinner.clear();
|
|
26662
26722
|
if (packageGuard.lockfile === "failed") {
|
|
26663
|
-
|
|
26723
|
+
p24.log.warn(
|
|
26664
26724
|
"Could not refresh pnpm-lock.yaml after removing betterstart-cli \u2014 the remote install may fail."
|
|
26665
26725
|
);
|
|
26666
26726
|
}
|
|
26667
26727
|
for (const dep of packageGuard.localSpecDeps) {
|
|
26668
|
-
|
|
26728
|
+
p24.log.warn(
|
|
26669
26729
|
`Dependency ${pc9.cyan(dep)} uses a local spec that cannot install on Vercel \u2014 the remote build may fail.`
|
|
26670
26730
|
);
|
|
26671
26731
|
}
|
|
@@ -26682,7 +26742,7 @@ async function runVercelDeployFlow(options) {
|
|
|
26682
26742
|
}
|
|
26683
26743
|
if (deploy.failure) {
|
|
26684
26744
|
deploySpinner.stop(`${pc9.yellow("\u25B2")} ${deployFailureMessage(deploy.failure)}`);
|
|
26685
|
-
if (deploy.detail)
|
|
26745
|
+
if (deploy.detail) p24.log.message(pc9.dim(redactSecrets(deploy.detail)));
|
|
26686
26746
|
printManualDeployHint();
|
|
26687
26747
|
return { ok: false };
|
|
26688
26748
|
}
|
|
@@ -26690,7 +26750,7 @@ async function runVercelDeployFlow(options) {
|
|
|
26690
26750
|
deploySpinner.stop(url ? `Deployed ${pc9.cyan(url)}` : "Deployed to Vercel");
|
|
26691
26751
|
return { ok: true, url, syncedEnvKeys: sync.synced };
|
|
26692
26752
|
} catch (error) {
|
|
26693
|
-
|
|
26753
|
+
p24.log.warn(`Vercel deploy failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
26694
26754
|
printManualDeployHint();
|
|
26695
26755
|
return { ok: false };
|
|
26696
26756
|
} finally {
|
|
@@ -26698,7 +26758,7 @@ async function runVercelDeployFlow(options) {
|
|
|
26698
26758
|
}
|
|
26699
26759
|
}
|
|
26700
26760
|
function printManualDeployHint() {
|
|
26701
|
-
|
|
26761
|
+
p24.log.info(`You can deploy manually: ${pc9.cyan("vercel deploy --prod")}`);
|
|
26702
26762
|
}
|
|
26703
26763
|
async function ensureLinkedProject(runner, cwd, projectName, env, scope) {
|
|
26704
26764
|
if (readLinkedProjectId(cwd)) return;
|
|
@@ -27134,16 +27194,16 @@ function addVersionToBoxBottomBorder(box2, version2) {
|
|
|
27134
27194
|
if (!bottomLine) {
|
|
27135
27195
|
return box2;
|
|
27136
27196
|
}
|
|
27137
|
-
const leftCornerIndex = bottomLine.indexOf(
|
|
27138
|
-
const rightCornerIndex = bottomLine.lastIndexOf(
|
|
27197
|
+
const leftCornerIndex = bottomLine.indexOf(p25.S_CORNER_BOTTOM_LEFT);
|
|
27198
|
+
const rightCornerIndex = bottomLine.lastIndexOf(p25.S_CORNER_BOTTOM_RIGHT);
|
|
27139
27199
|
const label = ` v${version2} `;
|
|
27140
|
-
const borderWidth = rightCornerIndex - leftCornerIndex -
|
|
27200
|
+
const borderWidth = rightCornerIndex - leftCornerIndex - p25.S_CORNER_BOTTOM_LEFT.length;
|
|
27141
27201
|
if (leftCornerIndex === -1 || rightCornerIndex === -1 || borderWidth < label.length) {
|
|
27142
27202
|
return box2;
|
|
27143
27203
|
}
|
|
27144
27204
|
const leftBorderWidth = Math.floor((borderWidth - label.length) / 2);
|
|
27145
27205
|
const rightBorderWidth = borderWidth - label.length - leftBorderWidth;
|
|
27146
|
-
lines[bottomLineIndex] = `${bottomLine.slice(0, leftCornerIndex +
|
|
27206
|
+
lines[bottomLineIndex] = `${bottomLine.slice(0, leftCornerIndex + p25.S_CORNER_BOTTOM_LEFT.length)}${p25.S_BAR_H.repeat(leftBorderWidth)}${label}${p25.S_BAR_H.repeat(rightBorderWidth)}${bottomLine.slice(rightCornerIndex)}`;
|
|
27147
27207
|
return lines.join("\n");
|
|
27148
27208
|
}
|
|
27149
27209
|
function renderInitBanner() {
|
|
@@ -27153,7 +27213,7 @@ function renderInitBanner() {
|
|
|
27153
27213
|
output.on("data", (chunk) => {
|
|
27154
27214
|
box2 += chunk.toString();
|
|
27155
27215
|
});
|
|
27156
|
-
|
|
27216
|
+
p25.box(
|
|
27157
27217
|
`
|
|
27158
27218
|
\u2584 \u2597 \u2597 \u2584\u2596\u2597 \u2597
|
|
27159
27219
|
\u2599\u2598\u2588\u258C\u259C\u2598\u259C\u2598\u2588\u258C\u259B\u2598\u259A \u259C\u2598\u2580\u258C\u259B\u2598\u259C\u2598
|
|
@@ -27249,7 +27309,7 @@ async function runInitCommand(name, options) {
|
|
|
27249
27309
|
let restoreStdout;
|
|
27250
27310
|
if (options.json) {
|
|
27251
27311
|
if (!options.yes) {
|
|
27252
|
-
|
|
27312
|
+
p25.log.error("--json requires --yes.");
|
|
27253
27313
|
process.exit(1);
|
|
27254
27314
|
}
|
|
27255
27315
|
restoreStdout = redirectStdoutToStderr();
|
|
@@ -27270,7 +27330,7 @@ async function runInitCommand(name, options) {
|
|
|
27270
27330
|
}
|
|
27271
27331
|
} catch (error) {
|
|
27272
27332
|
disposeCancelGuard();
|
|
27273
|
-
|
|
27333
|
+
p25.log.error(error instanceof Error ? error.message : String(error));
|
|
27274
27334
|
process.exit(1);
|
|
27275
27335
|
}
|
|
27276
27336
|
let cwd = process.cwd();
|
|
@@ -27281,7 +27341,7 @@ async function runInitCommand(name, options) {
|
|
|
27281
27341
|
try {
|
|
27282
27342
|
namespace = validateAdminNamespace(options.namespace);
|
|
27283
27343
|
} catch (error) {
|
|
27284
|
-
|
|
27344
|
+
p25.log.error(error instanceof Error ? error.message : String(error));
|
|
27285
27345
|
process.exit(1);
|
|
27286
27346
|
}
|
|
27287
27347
|
}
|
|
@@ -27290,13 +27350,13 @@ async function runInitCommand(name, options) {
|
|
|
27290
27350
|
try {
|
|
27291
27351
|
projectPrompt = options.yes ? resolveNonInteractiveProject(name) : await promptProject(name);
|
|
27292
27352
|
} catch (error) {
|
|
27293
|
-
|
|
27353
|
+
p25.log.error(error instanceof Error ? error.message : String(error));
|
|
27294
27354
|
process.exit(1);
|
|
27295
27355
|
}
|
|
27296
27356
|
}
|
|
27297
27357
|
if (!options.yes && !options.namespace) {
|
|
27298
27358
|
const defaultDashboardPath = resolveAdminNamespace(DEFAULT_ADMIN_NAMESPACE).routePath;
|
|
27299
|
-
const namespaceInput = await
|
|
27359
|
+
const namespaceInput = await p25.text({
|
|
27300
27360
|
message: "Enter the dashboard path",
|
|
27301
27361
|
placeholder: `eg. ${defaultDashboardPath}`,
|
|
27302
27362
|
defaultValue: defaultDashboardPath,
|
|
@@ -27309,8 +27369,8 @@ async function runInitCommand(name, options) {
|
|
|
27309
27369
|
}
|
|
27310
27370
|
}
|
|
27311
27371
|
});
|
|
27312
|
-
if (
|
|
27313
|
-
|
|
27372
|
+
if (p25.isCancel(namespaceInput)) {
|
|
27373
|
+
p25.cancel("Setup cancelled.");
|
|
27314
27374
|
process.exit(0);
|
|
27315
27375
|
}
|
|
27316
27376
|
namespace = validateAdminDashboardPath(namespaceInput);
|
|
@@ -27322,13 +27382,13 @@ async function runInitCommand(name, options) {
|
|
|
27322
27382
|
if (project2.isExisting) {
|
|
27323
27383
|
srcDir = project2.hasSrcDir;
|
|
27324
27384
|
if (!project2.hasTypeScript) {
|
|
27325
|
-
|
|
27385
|
+
p25.log.error("TypeScript is required. Please add a tsconfig.json first.");
|
|
27326
27386
|
process.exit(1);
|
|
27327
27387
|
}
|
|
27328
27388
|
if (forceMode) {
|
|
27329
27389
|
const nuked = removeExistingAdminPaths(cwd, await resolveForceInitNamespaces(cwd, namespace));
|
|
27330
27390
|
if (nuked > 0) {
|
|
27331
|
-
|
|
27391
|
+
p25.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
|
|
27332
27392
|
}
|
|
27333
27393
|
project2 = detectProject(cwd, namespace);
|
|
27334
27394
|
} else if (project2.conflicts.length > 0) {
|
|
@@ -27337,14 +27397,14 @@ async function runInitCommand(name, options) {
|
|
|
27337
27397
|
"",
|
|
27338
27398
|
pc10.dim(`Use ${pc10.bold("--force")} to remove existing admin files before scaffolding.`)
|
|
27339
27399
|
);
|
|
27340
|
-
|
|
27400
|
+
p25.note(conflictLines.join("\n"), pc10.yellow("Conflicts"));
|
|
27341
27401
|
if (options.yes) {
|
|
27342
|
-
|
|
27402
|
+
p25.log.error(
|
|
27343
27403
|
"Can't continue with --yes while admin files conflict. Re-run with --force to remove them first."
|
|
27344
27404
|
);
|
|
27345
27405
|
process.exit(1);
|
|
27346
27406
|
}
|
|
27347
|
-
const proceed = await
|
|
27407
|
+
const proceed = await p25.confirm({
|
|
27348
27408
|
message: [
|
|
27349
27409
|
`Continue with ${pc10.bold(pc10.cyan("--force"))}?`,
|
|
27350
27410
|
`${pc10.cyan("\u2502")} ${pc10.dim("This will force overwrite the existing admin code.")}`,
|
|
@@ -27352,14 +27412,14 @@ async function runInitCommand(name, options) {
|
|
|
27352
27412
|
].join("\n"),
|
|
27353
27413
|
initialValue: true
|
|
27354
27414
|
});
|
|
27355
|
-
if (
|
|
27356
|
-
|
|
27415
|
+
if (p25.isCancel(proceed) || !proceed) {
|
|
27416
|
+
p25.cancel("Setup cancelled.");
|
|
27357
27417
|
process.exit(0);
|
|
27358
27418
|
}
|
|
27359
27419
|
forceMode = true;
|
|
27360
27420
|
const nuked = removeExistingAdminPaths(cwd, await resolveForceInitNamespaces(cwd, namespace));
|
|
27361
27421
|
if (nuked > 0) {
|
|
27362
|
-
|
|
27422
|
+
p25.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
|
|
27363
27423
|
}
|
|
27364
27424
|
project2 = detectProject(cwd, namespace);
|
|
27365
27425
|
}
|
|
@@ -27367,7 +27427,7 @@ async function runInitCommand(name, options) {
|
|
|
27367
27427
|
const freshProject = projectPrompt;
|
|
27368
27428
|
srcDir = false;
|
|
27369
27429
|
if (!options.yes) {
|
|
27370
|
-
const pmChoice = await
|
|
27430
|
+
const pmChoice = await p25.select({
|
|
27371
27431
|
message: "Which package manager do you want to use?",
|
|
27372
27432
|
options: [
|
|
27373
27433
|
{ value: "pnpm", label: "pnpm", hint: "recommended" },
|
|
@@ -27375,8 +27435,8 @@ async function runInitCommand(name, options) {
|
|
|
27375
27435
|
{ value: "bun", label: "bun" }
|
|
27376
27436
|
]
|
|
27377
27437
|
});
|
|
27378
|
-
if (
|
|
27379
|
-
|
|
27438
|
+
if (p25.isCancel(pmChoice)) {
|
|
27439
|
+
p25.cancel("Setup cancelled.");
|
|
27380
27440
|
process.exit(0);
|
|
27381
27441
|
}
|
|
27382
27442
|
pm = pmChoice;
|
|
@@ -27411,8 +27471,8 @@ async function runInitCommand(name, options) {
|
|
|
27411
27471
|
process.stderr.write(`${createNextAppResult.output.trimEnd()}
|
|
27412
27472
|
`);
|
|
27413
27473
|
}
|
|
27414
|
-
|
|
27415
|
-
|
|
27474
|
+
p25.log.error(createNextAppResult.error);
|
|
27475
|
+
p25.log.info(
|
|
27416
27476
|
`You can create the project manually:
|
|
27417
27477
|
${pc10.cyan(`npx create-next-app@latest ${freshProject.projectName} --typescript --tailwind --app`)}
|
|
27418
27478
|
Then run ${pc10.cyan("betterstart init")} inside it.`
|
|
@@ -27426,11 +27486,11 @@ async function runInitCommand(name, options) {
|
|
|
27426
27486
|
);
|
|
27427
27487
|
if (!hasPackageJson || !hasNextConfig) {
|
|
27428
27488
|
createNextAppSpinner.stop(`Failed to create Next.js app: ${displayName}`);
|
|
27429
|
-
|
|
27489
|
+
p25.log.error(
|
|
27430
27490
|
"create-next-app completed but the project was not created. This can happen with nested npx calls."
|
|
27431
27491
|
);
|
|
27432
27492
|
const manualCmd = `npx create-next-app@latest ${freshProject.projectName} --typescript --tailwind --app`;
|
|
27433
|
-
|
|
27493
|
+
p25.log.info(
|
|
27434
27494
|
`Create the project manually:
|
|
27435
27495
|
${pc10.cyan(manualCmd)}
|
|
27436
27496
|
Then run ${pc10.cyan("betterstart init")} inside it.`
|
|
@@ -27479,13 +27539,13 @@ async function runInitCommand(name, options) {
|
|
|
27479
27539
|
try {
|
|
27480
27540
|
validateResolvedDatabaseProvider(databaseProvider, options);
|
|
27481
27541
|
} catch (error) {
|
|
27482
|
-
|
|
27542
|
+
p25.log.error(error instanceof Error ? error.message : String(error));
|
|
27483
27543
|
process.exit(1);
|
|
27484
27544
|
}
|
|
27485
27545
|
if (databaseProvider === "manual") {
|
|
27486
27546
|
const candidate = options.databaseUrl ?? existingDbUrl ?? promptedManualUrl;
|
|
27487
27547
|
if (candidate && !isValidDbUrl(candidate)) {
|
|
27488
|
-
|
|
27548
|
+
p25.log.error(
|
|
27489
27549
|
`Invalid database URL. Must start with ${pc10.cyan("postgres://")} or ${pc10.cyan("postgresql://")}`
|
|
27490
27550
|
);
|
|
27491
27551
|
process.exit(1);
|
|
@@ -27493,7 +27553,7 @@ async function runInitCommand(name, options) {
|
|
|
27493
27553
|
if (candidate) {
|
|
27494
27554
|
databaseUrl = candidate;
|
|
27495
27555
|
if (existingDbUrl === candidate && !options.databaseUrl) {
|
|
27496
|
-
|
|
27556
|
+
p25.log.info(
|
|
27497
27557
|
`Using the existing DATABASE_URL from .env.local ${pc10.dim(`(${maskDbUrl(candidate)})`)}`
|
|
27498
27558
|
);
|
|
27499
27559
|
}
|
|
@@ -27513,7 +27573,7 @@ async function runInitCommand(name, options) {
|
|
|
27513
27573
|
persistDatabaseUrl(cwd, databaseUrl);
|
|
27514
27574
|
dismissVercelSignedInNote = flow.dismissSignedInNote;
|
|
27515
27575
|
} else if (options.yes) {
|
|
27516
|
-
|
|
27576
|
+
p25.log.error(
|
|
27517
27577
|
flow.ok ? "Created a Neon database, but DATABASE_URL could not be retrieved from Vercel." : "Vercel database provisioning did not complete."
|
|
27518
27578
|
);
|
|
27519
27579
|
process.exit(1);
|
|
@@ -27522,7 +27582,7 @@ async function runInitCommand(name, options) {
|
|
|
27522
27582
|
databaseUrl = await promptConnectionString();
|
|
27523
27583
|
persistDatabaseUrl(cwd, databaseUrl);
|
|
27524
27584
|
} else {
|
|
27525
|
-
|
|
27585
|
+
p25.log.info("Falling back to a manual database connection string.");
|
|
27526
27586
|
openBrowserVercelNeon();
|
|
27527
27587
|
databaseUrl = await promptConnectionString();
|
|
27528
27588
|
}
|
|
@@ -27536,11 +27596,11 @@ async function runInitCommand(name, options) {
|
|
|
27536
27596
|
} catch (error) {
|
|
27537
27597
|
const message = error instanceof Error ? error.message : String(error);
|
|
27538
27598
|
if (options.yes) {
|
|
27539
|
-
|
|
27599
|
+
p25.log.error(`Railway database provisioning failed: ${message}`);
|
|
27540
27600
|
process.exit(1);
|
|
27541
27601
|
}
|
|
27542
|
-
|
|
27543
|
-
|
|
27602
|
+
p25.log.warn(`Railway database provisioning failed: ${message}`);
|
|
27603
|
+
p25.log.info("Falling back to a manual database connection string.");
|
|
27544
27604
|
databaseUrl = await promptConnectionString();
|
|
27545
27605
|
}
|
|
27546
27606
|
}
|
|
@@ -27570,7 +27630,7 @@ async function runInitCommand(name, options) {
|
|
|
27570
27630
|
return { ok: true, config: config2 };
|
|
27571
27631
|
} catch (error) {
|
|
27572
27632
|
const message = error instanceof Error ? error.message : String(error);
|
|
27573
|
-
|
|
27633
|
+
p25.log.warn(`Railway bucket provisioning failed: ${message}`);
|
|
27574
27634
|
return { ok: false };
|
|
27575
27635
|
}
|
|
27576
27636
|
};
|
|
@@ -27584,7 +27644,7 @@ async function runInitCommand(name, options) {
|
|
|
27584
27644
|
if (storage === "r2") {
|
|
27585
27645
|
const missingR2Keys = R2_ENV_KEYS.filter((key) => !readEnvVar(cwd, key)?.trim());
|
|
27586
27646
|
if (options.yes && missingR2Keys.length > 0) {
|
|
27587
|
-
|
|
27647
|
+
p25.log.error(
|
|
27588
27648
|
`Cloudflare R2 is missing required environment variables: ${missingR2Keys.join(", ")}.`
|
|
27589
27649
|
);
|
|
27590
27650
|
process.exit(1);
|
|
@@ -27598,7 +27658,7 @@ async function runInitCommand(name, options) {
|
|
|
27598
27658
|
if (flow.ok && flow.config) {
|
|
27599
27659
|
mergeCollectedIntegrationConfig(flow.config);
|
|
27600
27660
|
} else if (options.yes) {
|
|
27601
|
-
|
|
27661
|
+
p25.log.error("Railway bucket provisioning did not complete.");
|
|
27602
27662
|
process.exit(1);
|
|
27603
27663
|
}
|
|
27604
27664
|
}
|
|
@@ -27617,10 +27677,10 @@ async function runInitCommand(name, options) {
|
|
|
27617
27677
|
});
|
|
27618
27678
|
collectedIntegrationConfig.overwriteKeys.add("BLOB_READ_WRITE_TOKEN");
|
|
27619
27679
|
} else if (options.yes) {
|
|
27620
|
-
|
|
27680
|
+
p25.log.error("Vercel Blob provisioning did not complete.");
|
|
27621
27681
|
process.exit(1);
|
|
27622
27682
|
} else {
|
|
27623
|
-
|
|
27683
|
+
p25.log.warn(
|
|
27624
27684
|
"Continuing without a Blob token \u2014 add BLOB_READ_WRITE_TOKEN to .env.local from the store on vercel.com/dashboard/stores."
|
|
27625
27685
|
);
|
|
27626
27686
|
collectedIntegrationConfig.sections.push({
|
|
@@ -27694,7 +27754,7 @@ async function runInitCommand(name, options) {
|
|
|
27694
27754
|
const nextConfigResult = scaffoldNextConfig({ cwd, nextMajorVersion });
|
|
27695
27755
|
s.clear();
|
|
27696
27756
|
if (nextConfigResult.status === "unsupported") {
|
|
27697
|
-
|
|
27757
|
+
p25.log.warn("The Next.js config could not be updated automatically \u2014 review it manually.");
|
|
27698
27758
|
}
|
|
27699
27759
|
const drizzleConfigPath = path52.join(cwd, "drizzle.config.ts");
|
|
27700
27760
|
if (!dbFiles.includes("drizzle.config.ts") && fs41.existsSync(drizzleConfigPath)) {
|
|
@@ -27705,20 +27765,20 @@ async function runInitCommand(name, options) {
|
|
|
27705
27765
|
readNamespacedTemplate("drizzle.config.ts", namespace),
|
|
27706
27766
|
"utf-8"
|
|
27707
27767
|
);
|
|
27708
|
-
|
|
27768
|
+
p25.log.success("Updated drizzle.config.ts");
|
|
27709
27769
|
} else if (!options.yes) {
|
|
27710
|
-
const overwrite = await
|
|
27770
|
+
const overwrite = await p25.confirm({
|
|
27711
27771
|
message: "drizzle.config.ts already exists. Overwrite with latest version?",
|
|
27712
27772
|
initialValue: true
|
|
27713
27773
|
});
|
|
27714
|
-
if (!
|
|
27774
|
+
if (!p25.isCancel(overwrite) && overwrite) {
|
|
27715
27775
|
const { readNamespacedTemplate } = await import("./template-reader-X6KFP7B3.js");
|
|
27716
27776
|
fs41.writeFileSync(
|
|
27717
27777
|
drizzleConfigPath,
|
|
27718
27778
|
readNamespacedTemplate("drizzle.config.ts", namespace),
|
|
27719
27779
|
"utf-8"
|
|
27720
27780
|
);
|
|
27721
|
-
|
|
27781
|
+
p25.log.success("Updated drizzle.config.ts");
|
|
27722
27782
|
}
|
|
27723
27783
|
}
|
|
27724
27784
|
}
|
|
@@ -27743,8 +27803,8 @@ async function runInitCommand(name, options) {
|
|
|
27743
27803
|
s.stop("");
|
|
27744
27804
|
} else {
|
|
27745
27805
|
s.stop("Failed to install dependencies");
|
|
27746
|
-
|
|
27747
|
-
|
|
27806
|
+
p25.log.warn(depsResult.error ?? "Unknown error");
|
|
27807
|
+
p25.log.info(
|
|
27748
27808
|
`You can install them manually:
|
|
27749
27809
|
${pc10.cyan(`${pm} add ${depsResult.dependencies.join(" ")}`)}
|
|
27750
27810
|
${pc10.cyan(`${pm} add -D ${depsResult.devDeps.join(" ")}`)}`
|
|
@@ -27800,22 +27860,22 @@ async function runInitCommand(name, options) {
|
|
|
27800
27860
|
writeConfigFile(cwd, resolvedIntegrationInstallResult.config);
|
|
27801
27861
|
const usesLocalStorage = resolvedIntegrationInstallResult.config.storage.provider === "local";
|
|
27802
27862
|
for (const err of coreSchemasResult.errors) {
|
|
27803
|
-
|
|
27863
|
+
p25.log.warn(`Core schemas: ${err}`);
|
|
27804
27864
|
}
|
|
27805
27865
|
for (const warning of resolvedPresetInstallResult.warnings) {
|
|
27806
|
-
|
|
27866
|
+
p25.log.warn(warning);
|
|
27807
27867
|
}
|
|
27808
27868
|
for (const warning of resolvedIntegrationInstallResult.warnings) {
|
|
27809
|
-
|
|
27869
|
+
p25.log.warn(warning);
|
|
27810
27870
|
}
|
|
27811
27871
|
if (usesLocalStorage) {
|
|
27812
|
-
|
|
27872
|
+
p25.log.warn(
|
|
27813
27873
|
"Local filesystem storage is only for development or self-hosted persistent-disk deployments. Use Vercel Blob, Railway Bucket, or Cloudflare R2 for hosted production."
|
|
27814
27874
|
);
|
|
27815
27875
|
}
|
|
27816
27876
|
let dbPushed = false;
|
|
27817
27877
|
if (depsResult.success && options.skipMigration && hasDbUrl(cwd)) {
|
|
27818
|
-
|
|
27878
|
+
p25.log.info(`Skipping database schema push ${pc10.dim("(--skip-migration)")}`);
|
|
27819
27879
|
} else if (depsResult.success && hasDbUrl(cwd)) {
|
|
27820
27880
|
let driverReady = hasDrizzleKitPostgresDriverDependency(cwd);
|
|
27821
27881
|
if (!driverReady) {
|
|
@@ -27830,8 +27890,8 @@ async function runInitCommand(name, options) {
|
|
|
27830
27890
|
});
|
|
27831
27891
|
if (!driverResult.success) {
|
|
27832
27892
|
s.stop("Database push failed");
|
|
27833
|
-
|
|
27834
|
-
|
|
27893
|
+
p25.log.warn(driverResult.error ?? `Failed to install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP}`);
|
|
27894
|
+
p25.log.info(
|
|
27835
27895
|
`Install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP} manually, then run: ${pc10.cyan(drizzlePushCommand(pm))}`
|
|
27836
27896
|
);
|
|
27837
27897
|
} else {
|
|
@@ -27859,8 +27919,8 @@ async function runInitCommand(name, options) {
|
|
|
27859
27919
|
const verification = await verifyDatabaseReachable(cwd);
|
|
27860
27920
|
clearDbSpinner();
|
|
27861
27921
|
if (!verification.success) {
|
|
27862
|
-
|
|
27863
|
-
|
|
27922
|
+
p25.log.warn(verification.error);
|
|
27923
|
+
p25.log.error("Database was not reachable. Aborting setup.");
|
|
27864
27924
|
process.exit(1);
|
|
27865
27925
|
}
|
|
27866
27926
|
} else {
|
|
@@ -27873,20 +27933,21 @@ async function runInitCommand(name, options) {
|
|
|
27873
27933
|
s.stop("Database push failed");
|
|
27874
27934
|
}
|
|
27875
27935
|
const pushError = pushResult.error ?? "Unknown error";
|
|
27876
|
-
|
|
27936
|
+
p25.log.warn(pushError);
|
|
27877
27937
|
if (isDatabaseReachabilityError(pushError)) {
|
|
27878
|
-
|
|
27938
|
+
p25.log.error("Database was not reachable. Aborting setup.");
|
|
27879
27939
|
process.exit(1);
|
|
27880
27940
|
}
|
|
27881
|
-
|
|
27941
|
+
p25.log.info(`You can run it manually: ${pc10.cyan(drizzlePushCommand(pm))}`);
|
|
27882
27942
|
}
|
|
27883
27943
|
}
|
|
27884
27944
|
}
|
|
27885
27945
|
let seedEmail;
|
|
27946
|
+
let seedPassword;
|
|
27886
27947
|
let seedSuccess = false;
|
|
27887
27948
|
let adminAccountReady = false;
|
|
27888
27949
|
if (dbPushed && options.skipAdminCreation) {
|
|
27889
|
-
|
|
27950
|
+
p25.log.info(
|
|
27890
27951
|
`Skipping admin user creation ${pc10.dim(`(use ${betterstartExecCommand(pm, "seed")} later)`)}`
|
|
27891
27952
|
);
|
|
27892
27953
|
}
|
|
@@ -27898,14 +27959,14 @@ async function runInitCommand(name, options) {
|
|
|
27898
27959
|
const adminCheck = await checkExistingAdmin(cwd, adminDir, authBasePath);
|
|
27899
27960
|
s.clear();
|
|
27900
27961
|
if (adminCheck.error) {
|
|
27901
|
-
|
|
27962
|
+
p25.log.warn(`Could not verify existing admin account ${pc10.dim(`(${adminCheck.error})`)}`);
|
|
27902
27963
|
if (isDatabaseReachabilityError(adminCheck.error)) {
|
|
27903
|
-
|
|
27964
|
+
p25.log.error("Database was not reachable. Aborting setup.");
|
|
27904
27965
|
process.exit(1);
|
|
27905
27966
|
}
|
|
27906
27967
|
} else if (adminCheck.existingAdmin) {
|
|
27907
27968
|
const existingAdminLabel = formatAdminIdentity(adminCheck.existingAdmin);
|
|
27908
|
-
const adminAction = await
|
|
27969
|
+
const adminAction = await p25.select({
|
|
27909
27970
|
message: "Found an already existing admin account. Do you want to replace it or skip?",
|
|
27910
27971
|
options: [
|
|
27911
27972
|
{
|
|
@@ -27919,28 +27980,28 @@ async function runInitCommand(name, options) {
|
|
|
27919
27980
|
}
|
|
27920
27981
|
]
|
|
27921
27982
|
});
|
|
27922
|
-
if (
|
|
27923
|
-
|
|
27983
|
+
if (p25.isCancel(adminAction)) {
|
|
27984
|
+
p25.cancel("Setup cancelled.");
|
|
27924
27985
|
process.exit(0);
|
|
27925
27986
|
}
|
|
27926
27987
|
if (adminAction === "skip") {
|
|
27927
27988
|
adminAccountReady = true;
|
|
27928
|
-
|
|
27989
|
+
p25.log.info(`Keeping existing admin account ${pc10.dim(`(${existingAdminLabel})`)}`);
|
|
27929
27990
|
} else {
|
|
27930
27991
|
replaceExistingAdmin = true;
|
|
27931
27992
|
}
|
|
27932
27993
|
}
|
|
27933
27994
|
if (!adminAccountReady) {
|
|
27934
|
-
const credentials = await
|
|
27995
|
+
const credentials = await p25.group(
|
|
27935
27996
|
{
|
|
27936
|
-
email: () =>
|
|
27997
|
+
email: () => p25.text({
|
|
27937
27998
|
message: "Admin email",
|
|
27938
27999
|
placeholder: "admin@example.com",
|
|
27939
28000
|
validate: (v) => {
|
|
27940
28001
|
if (!v || !v.includes("@")) return "Please enter a valid email";
|
|
27941
28002
|
}
|
|
27942
28003
|
}),
|
|
27943
|
-
password: () =>
|
|
28004
|
+
password: () => p25.password({
|
|
27944
28005
|
message: "Admin password",
|
|
27945
28006
|
validate: (v) => {
|
|
27946
28007
|
if (!v || v.length < 8) return "Password must be at least 8 characters";
|
|
@@ -27949,13 +28010,14 @@ async function runInitCommand(name, options) {
|
|
|
27949
28010
|
},
|
|
27950
28011
|
{
|
|
27951
28012
|
onCancel: () => {
|
|
27952
|
-
|
|
28013
|
+
p25.cancel("Setup cancelled.");
|
|
27953
28014
|
process.exit(0);
|
|
27954
28015
|
}
|
|
27955
28016
|
}
|
|
27956
28017
|
);
|
|
27957
28018
|
seedEmail = credentials.email;
|
|
27958
|
-
|
|
28019
|
+
seedPassword = credentials.password;
|
|
28020
|
+
const credentialPromptRows = clackPromptRows("Admin email", credentials.email) + clackPromptRows("Admin password", p25.S_PASSWORD_MASK.repeat(credentials.password.length));
|
|
27959
28021
|
let rowsBelowCredentialPrompts = 0;
|
|
27960
28022
|
let seedOverwriteMode = replaceExistingAdmin ? "admin" : void 0;
|
|
27961
28023
|
s.start(replaceExistingAdmin ? "Replacing admin user" : "Creating admin user");
|
|
@@ -27972,7 +28034,7 @@ async function runInitCommand(name, options) {
|
|
|
27972
28034
|
s.stop(existingAccountMessage);
|
|
27973
28035
|
rowsBelowCredentialPrompts += clackLogRows(existingAccountMessage);
|
|
27974
28036
|
const replaceAccountMessage = "Replace the existing account with this email?";
|
|
27975
|
-
const replace = await
|
|
28037
|
+
const replace = await p25.confirm({
|
|
27976
28038
|
message: replaceAccountMessage,
|
|
27977
28039
|
initialValue: false
|
|
27978
28040
|
});
|
|
@@ -27980,7 +28042,7 @@ async function runInitCommand(name, options) {
|
|
|
27980
28042
|
replaceAccountMessage,
|
|
27981
28043
|
replace === true ? "Yes" : "No"
|
|
27982
28044
|
);
|
|
27983
|
-
if (!
|
|
28045
|
+
if (!p25.isCancel(replace) && replace) {
|
|
27984
28046
|
seedOverwriteMode = "email";
|
|
27985
28047
|
s.start("Replacing admin user");
|
|
27986
28048
|
seedResult = await runSeed(
|
|
@@ -28002,14 +28064,14 @@ async function runInitCommand(name, options) {
|
|
|
28002
28064
|
adminAccountReady = true;
|
|
28003
28065
|
} else if (seedResult.error) {
|
|
28004
28066
|
s.stop(`Failed to create admin user`);
|
|
28005
|
-
|
|
28067
|
+
p25.note(
|
|
28006
28068
|
`${pc10.red(seedResult.error)}
|
|
28007
28069
|
|
|
28008
28070
|
Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
28009
28071
|
pc10.red("Seed failed")
|
|
28010
28072
|
);
|
|
28011
28073
|
if (isDatabaseReachabilityError(seedResult.error)) {
|
|
28012
|
-
|
|
28074
|
+
p25.log.error("Database was not reachable. Aborting setup.");
|
|
28013
28075
|
process.exit(1);
|
|
28014
28076
|
}
|
|
28015
28077
|
}
|
|
@@ -28051,10 +28113,10 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
|
28051
28113
|
deployedUrl = deployFlow.url;
|
|
28052
28114
|
if (!deployFlow.ok) {
|
|
28053
28115
|
if (options.yes) {
|
|
28054
|
-
|
|
28116
|
+
p25.log.error("Vercel deploy did not complete.");
|
|
28055
28117
|
process.exit(1);
|
|
28056
28118
|
}
|
|
28057
|
-
|
|
28119
|
+
p25.log.warn("Vercel deploy did not complete; continuing.");
|
|
28058
28120
|
}
|
|
28059
28121
|
} else if (deployProvider === "railway") {
|
|
28060
28122
|
try {
|
|
@@ -28072,36 +28134,34 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
|
28072
28134
|
});
|
|
28073
28135
|
deployedUrl = deployFlow.url;
|
|
28074
28136
|
if (!deployFlow.ok) {
|
|
28075
|
-
if (deployFlow.detail)
|
|
28137
|
+
if (deployFlow.detail) p25.log.message(pc10.dim(redactSecrets(deployFlow.detail)));
|
|
28076
28138
|
if (options.yes) {
|
|
28077
|
-
|
|
28139
|
+
p25.log.error("Railway deploy did not complete.");
|
|
28078
28140
|
process.exit(1);
|
|
28079
28141
|
}
|
|
28080
|
-
|
|
28142
|
+
p25.log.warn("Railway deploy did not complete; continuing.");
|
|
28081
28143
|
}
|
|
28082
28144
|
} catch (error) {
|
|
28083
28145
|
const message = error instanceof Error ? error.message : String(error);
|
|
28084
28146
|
if (options.yes) {
|
|
28085
|
-
|
|
28147
|
+
p25.log.error(`Railway deploy failed: ${message}`);
|
|
28086
28148
|
process.exit(1);
|
|
28087
28149
|
}
|
|
28088
|
-
|
|
28150
|
+
p25.log.warn(`Railway deploy failed: ${message}`);
|
|
28089
28151
|
}
|
|
28090
28152
|
}
|
|
28091
28153
|
if (!options.yes && !options.skipDevServerStart) {
|
|
28092
28154
|
const devCmd = runCommand(pm, "dev");
|
|
28093
|
-
const startDev = await
|
|
28155
|
+
const startDev = await p25.confirm({
|
|
28094
28156
|
message: "Start the development server?",
|
|
28095
28157
|
initialValue: true
|
|
28096
28158
|
});
|
|
28097
|
-
if (!
|
|
28159
|
+
if (!p25.isCancel(startDev) && startDev) {
|
|
28098
28160
|
disposeCancelGuard();
|
|
28099
|
-
await startManagedDevServer(
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
seedSuccess && seedEmail ? seedEmail : void 0
|
|
28104
|
-
);
|
|
28161
|
+
await startManagedDevServer(cwd, devCmd, adminLoginUrl, {
|
|
28162
|
+
email: seedSuccess && seedEmail ? seedEmail : void 0,
|
|
28163
|
+
password: seedSuccess && seedPassword ? seedPassword : void 0
|
|
28164
|
+
});
|
|
28105
28165
|
return;
|
|
28106
28166
|
}
|
|
28107
28167
|
}
|
|
@@ -28128,7 +28188,7 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
|
28128
28188
|
);
|
|
28129
28189
|
return;
|
|
28130
28190
|
}
|
|
28131
|
-
|
|
28191
|
+
p25.outro(`Admin ready at ${adminNamespace.routePath}`);
|
|
28132
28192
|
}
|
|
28133
28193
|
function isValidDbUrl(url) {
|
|
28134
28194
|
return url.startsWith("postgres://") || url.startsWith("postgresql://");
|
|
@@ -28515,10 +28575,13 @@ function stripAnsi2(value) {
|
|
|
28515
28575
|
}
|
|
28516
28576
|
function printAdminReadyNote(state) {
|
|
28517
28577
|
const lines = [`Admin: ${pc10.cyan(state.adminLoginUrl)}`];
|
|
28518
|
-
if (state.adminEmail) {
|
|
28578
|
+
if (state.adminEmail && state.adminPassword) {
|
|
28579
|
+
lines.unshift(`Password: ${pc10.cyan(state.adminPassword)}`);
|
|
28580
|
+
lines.unshift(`Admin user: ${pc10.cyan(state.adminEmail)}`);
|
|
28581
|
+
} else if (state.adminEmail) {
|
|
28519
28582
|
lines.unshift(`Admin user: ${pc10.cyan(state.adminEmail)}`);
|
|
28520
28583
|
}
|
|
28521
|
-
|
|
28584
|
+
p25.note(lines.join("\n"), "Admin ready");
|
|
28522
28585
|
}
|
|
28523
28586
|
function shouldSuppressDevServerStartupLine(line) {
|
|
28524
28587
|
const plain = stripAnsi2(line).trim();
|
|
@@ -28581,7 +28644,7 @@ function pipeManagedDevServerStream(stream, target, state) {
|
|
|
28581
28644
|
flushBuffer(true);
|
|
28582
28645
|
});
|
|
28583
28646
|
}
|
|
28584
|
-
function startManagedDevServer(cwd, devCmd, adminLoginUrl,
|
|
28647
|
+
function startManagedDevServer(cwd, devCmd, adminLoginUrl, adminCredentials) {
|
|
28585
28648
|
return new Promise((resolve, reject) => {
|
|
28586
28649
|
const [bin, ...args] = devCmd.split(" ");
|
|
28587
28650
|
const child = spawn6(bin, args, {
|
|
@@ -28592,7 +28655,8 @@ function startManagedDevServer(cwd, devCmd, adminLoginUrl, adminEmail) {
|
|
|
28592
28655
|
suppressStartup: true,
|
|
28593
28656
|
readyLogged: false,
|
|
28594
28657
|
adminLoginUrl,
|
|
28595
|
-
adminEmail
|
|
28658
|
+
adminEmail: adminCredentials?.email,
|
|
28659
|
+
adminPassword: adminCredentials?.password
|
|
28596
28660
|
};
|
|
28597
28661
|
const forwardSignal = (signal) => {
|
|
28598
28662
|
if (!child.killed) {
|
|
@@ -28629,7 +28693,7 @@ function startManagedDevServer(cwd, devCmd, adminLoginUrl, adminEmail) {
|
|
|
28629
28693
|
|
|
28630
28694
|
// adapters/next/commands/list-integrations.ts
|
|
28631
28695
|
import path53 from "path";
|
|
28632
|
-
import * as
|
|
28696
|
+
import * as p26 from "@clack/prompts";
|
|
28633
28697
|
|
|
28634
28698
|
// core-engine/utils/table.ts
|
|
28635
28699
|
function renderTableRows(rows) {
|
|
@@ -28676,15 +28740,15 @@ async function runListIntegrationsCommand(options) {
|
|
|
28676
28740
|
integration.kind,
|
|
28677
28741
|
integration.description
|
|
28678
28742
|
]);
|
|
28679
|
-
|
|
28680
|
-
|
|
28743
|
+
p26.note(renderTableRows(rows).join("\n"), "BetterStart integrations");
|
|
28744
|
+
p26.outro(
|
|
28681
28745
|
`${installedIntegrations.size} installed, ${rows.length - installedIntegrations.size} available`
|
|
28682
28746
|
);
|
|
28683
28747
|
}
|
|
28684
28748
|
|
|
28685
28749
|
// adapters/next/commands/list-presets.ts
|
|
28686
28750
|
import path54 from "path";
|
|
28687
|
-
import * as
|
|
28751
|
+
import * as p27 from "@clack/prompts";
|
|
28688
28752
|
async function runListPresetsCommand(options) {
|
|
28689
28753
|
const cwd = options.cwd ? path54.resolve(options.cwd) : process.cwd();
|
|
28690
28754
|
if (options.json) {
|
|
@@ -28714,34 +28778,34 @@ async function runListPresetsCommand(options) {
|
|
|
28714
28778
|
preset.kind,
|
|
28715
28779
|
preset.description
|
|
28716
28780
|
]);
|
|
28717
|
-
|
|
28718
|
-
|
|
28781
|
+
p27.note(renderTableRows(rows).join("\n"), "BetterStart presets");
|
|
28782
|
+
p27.outro(`${installedPresets.size} installed, ${rows.length - installedPresets.size} available`);
|
|
28719
28783
|
}
|
|
28720
28784
|
|
|
28721
28785
|
// adapters/next/commands/remove.ts
|
|
28722
28786
|
import path55 from "path";
|
|
28723
|
-
import * as
|
|
28787
|
+
import * as p28 from "@clack/prompts";
|
|
28724
28788
|
async function runRemoveCommand(items, options) {
|
|
28725
28789
|
const removeIntegrationsMode = Boolean(options.integration);
|
|
28726
28790
|
if (!removeIntegrationsMode && items.includes("core")) {
|
|
28727
|
-
|
|
28791
|
+
p28.log.error("The core Admin cannot be removed.");
|
|
28728
28792
|
process.exit(1);
|
|
28729
28793
|
}
|
|
28730
28794
|
const presetIds = items.filter(isPresetId);
|
|
28731
28795
|
const integrationIds = items.filter(isIntegrationId);
|
|
28732
28796
|
if (!removeIntegrationsMode && integrationIds.length > 0) {
|
|
28733
|
-
|
|
28797
|
+
p28.log.error(
|
|
28734
28798
|
`Integration IDs require --integration. Run \`betterstart remove --integration ${integrationIds.join(" ")}\`.`
|
|
28735
28799
|
);
|
|
28736
28800
|
process.exit(1);
|
|
28737
28801
|
}
|
|
28738
28802
|
if (removeIntegrationsMode && presetIds.length > 0) {
|
|
28739
|
-
|
|
28803
|
+
p28.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
|
|
28740
28804
|
process.exit(1);
|
|
28741
28805
|
}
|
|
28742
28806
|
const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
|
|
28743
28807
|
if (invalidItems.length > 0) {
|
|
28744
|
-
|
|
28808
|
+
p28.log.error(
|
|
28745
28809
|
removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
|
|
28746
28810
|
);
|
|
28747
28811
|
process.exit(1);
|
|
@@ -28750,12 +28814,12 @@ async function runRemoveCommand(items, options) {
|
|
|
28750
28814
|
const config = await resolveConfigOrExit(cwd);
|
|
28751
28815
|
const pm = detectPackageManager(cwd);
|
|
28752
28816
|
if (!options.force) {
|
|
28753
|
-
const confirmed = await
|
|
28817
|
+
const confirmed = await p28.confirm({
|
|
28754
28818
|
message: `Remove ${removeIntegrationsMode ? "integration" : "preset"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
|
|
28755
28819
|
initialValue: false
|
|
28756
28820
|
});
|
|
28757
|
-
if (
|
|
28758
|
-
|
|
28821
|
+
if (p28.isCancel(confirmed) || !confirmed) {
|
|
28822
|
+
p28.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
|
|
28759
28823
|
process.exit(0);
|
|
28760
28824
|
}
|
|
28761
28825
|
}
|
|
@@ -28768,13 +28832,13 @@ async function runRemoveCommand(items, options) {
|
|
|
28768
28832
|
});
|
|
28769
28833
|
writeConfigFile(cwd, result2.config);
|
|
28770
28834
|
if (result2.removed.length === 0) {
|
|
28771
|
-
|
|
28835
|
+
p28.outro("No integrations were removed.");
|
|
28772
28836
|
return;
|
|
28773
28837
|
}
|
|
28774
28838
|
if (result2.warnings.length > 0) {
|
|
28775
|
-
|
|
28839
|
+
p28.note(result2.warnings.join("\n"), "Warnings");
|
|
28776
28840
|
}
|
|
28777
|
-
|
|
28841
|
+
p28.outro(
|
|
28778
28842
|
`Removed integration${result2.removed.length === 1 ? "" : "s"}: ${result2.removed.join(", ")}`
|
|
28779
28843
|
);
|
|
28780
28844
|
return;
|
|
@@ -28787,13 +28851,13 @@ async function runRemoveCommand(items, options) {
|
|
|
28787
28851
|
});
|
|
28788
28852
|
writeConfigFile(cwd, result.config);
|
|
28789
28853
|
if (result.removed.length === 0) {
|
|
28790
|
-
|
|
28854
|
+
p28.outro("No presets were removed.");
|
|
28791
28855
|
return;
|
|
28792
28856
|
}
|
|
28793
28857
|
if (result.warnings.length > 0) {
|
|
28794
|
-
|
|
28858
|
+
p28.note(result.warnings.join("\n"), "Warnings");
|
|
28795
28859
|
}
|
|
28796
|
-
|
|
28860
|
+
p28.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
|
|
28797
28861
|
}
|
|
28798
28862
|
|
|
28799
28863
|
// adapters/next/commands/remove-schema.ts
|
|
@@ -28936,7 +29000,7 @@ Schema JSON preserved.`
|
|
|
28936
29000
|
// adapters/next/commands/uninstall.ts
|
|
28937
29001
|
import fs44 from "fs";
|
|
28938
29002
|
import path57 from "path";
|
|
28939
|
-
import * as
|
|
29003
|
+
import * as p29 from "@clack/prompts";
|
|
28940
29004
|
import pc11 from "picocolors";
|
|
28941
29005
|
|
|
28942
29006
|
// adapters/next/commands/uninstall-cleaners.ts
|
|
@@ -29158,8 +29222,8 @@ function buildUninstallPlan(cwd, namespaceValue) {
|
|
|
29158
29222
|
count: configFiles.length,
|
|
29159
29223
|
unit: configFiles.length === 1 ? "file" : "files",
|
|
29160
29224
|
execute() {
|
|
29161
|
-
for (const
|
|
29162
|
-
if (fs44.existsSync(
|
|
29225
|
+
for (const p31 of configPaths) {
|
|
29226
|
+
if (fs44.existsSync(p31)) fs44.unlinkSync(p31);
|
|
29163
29227
|
}
|
|
29164
29228
|
}
|
|
29165
29229
|
});
|
|
@@ -29223,7 +29287,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
|
|
|
29223
29287
|
}
|
|
29224
29288
|
async function runUninstallCommand(options) {
|
|
29225
29289
|
const cwd = options.cwd ? path57.resolve(options.cwd) : process.cwd();
|
|
29226
|
-
|
|
29290
|
+
p29.intro(pc11.bgRed(pc11.white(" BetterStart Uninstall ")));
|
|
29227
29291
|
let namespace = DEFAULT_ADMIN_NAMESPACE;
|
|
29228
29292
|
try {
|
|
29229
29293
|
const config = await resolveConfig(cwd);
|
|
@@ -29232,8 +29296,8 @@ async function runUninstallCommand(options) {
|
|
|
29232
29296
|
}
|
|
29233
29297
|
const steps = buildUninstallPlan(cwd, namespace);
|
|
29234
29298
|
if (steps.length === 0) {
|
|
29235
|
-
|
|
29236
|
-
|
|
29299
|
+
p29.log.success(`${pc11.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
|
|
29300
|
+
p29.outro("Project already clean");
|
|
29237
29301
|
return;
|
|
29238
29302
|
}
|
|
29239
29303
|
const planLines = steps.map((step) => {
|
|
@@ -29241,14 +29305,14 @@ async function runUninstallCommand(options) {
|
|
|
29241
29305
|
const countLabel = pc11.dim(`${step.count} ${step.unit}`);
|
|
29242
29306
|
return `${pc11.red("\u2717")} ${names} ${countLabel}`;
|
|
29243
29307
|
});
|
|
29244
|
-
|
|
29308
|
+
p29.note(planLines.join("\n"), "Uninstall plan");
|
|
29245
29309
|
if (!options.force) {
|
|
29246
|
-
const confirmed = await
|
|
29310
|
+
const confirmed = await p29.confirm({
|
|
29247
29311
|
message: "Proceed with uninstall?",
|
|
29248
29312
|
initialValue: false
|
|
29249
29313
|
});
|
|
29250
|
-
if (
|
|
29251
|
-
|
|
29314
|
+
if (p29.isCancel(confirmed) || !confirmed) {
|
|
29315
|
+
p29.cancel("Uninstall cancelled.");
|
|
29252
29316
|
process.exit(0);
|
|
29253
29317
|
}
|
|
29254
29318
|
}
|
|
@@ -29260,8 +29324,8 @@ async function runUninstallCommand(options) {
|
|
|
29260
29324
|
}
|
|
29261
29325
|
const parts = steps.map((step) => `${step.count} ${step.unit}`);
|
|
29262
29326
|
s.stop(`Removed ${parts.join(", ")}`);
|
|
29263
|
-
|
|
29264
|
-
|
|
29327
|
+
p29.note(pc11.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
|
|
29328
|
+
p29.outro("Uninstall complete");
|
|
29265
29329
|
}
|
|
29266
29330
|
|
|
29267
29331
|
// adapters/next/commands/update-component.ts
|
|
@@ -31741,8 +31805,8 @@ try {
|
|
|
31741
31805
|
console.error(error);
|
|
31742
31806
|
} else {
|
|
31743
31807
|
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
31744
|
-
|
|
31745
|
-
|
|
31808
|
+
p30.log.error(message);
|
|
31809
|
+
p30.log.message(pc12.dim("Re-run with BETTERSTART_DEBUG=1 for the full stack trace."));
|
|
31746
31810
|
}
|
|
31747
31811
|
process.exit(1);
|
|
31748
31812
|
}
|