create-better-t-stack 3.37.0 → 3.38.1
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.d.mts +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +86 -91
- package/dist/index.mjs +1 -1
- package/dist/{src-IZv104V2.mjs → src-ihjK9T9S.mjs} +524 -168
- package/package.json +14 -14
- /package/dist/{chunk-BtN16TXe.mjs → rolldown-runtime-yhw22V8Z.mjs} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as __reExport, t as __exportAll } from "./
|
|
2
|
+
import { n as __reExport, t as __exportAll } from "./rolldown-runtime-yhw22V8Z.mjs";
|
|
3
3
|
import { getAllJsonSchemas } from "@better-t-stack/types/json-schema";
|
|
4
4
|
import { initTRPC } from "@trpc/server";
|
|
5
5
|
import { Result, Result as Result$1, TaggedError } from "better-result";
|
|
@@ -336,7 +336,7 @@ const cliConsola = {
|
|
|
336
336
|
/**
|
|
337
337
|
* User cancelled the operation (e.g., Ctrl+C in prompts)
|
|
338
338
|
*/
|
|
339
|
-
var UserCancelledError = class extends TaggedError("UserCancelledError")
|
|
339
|
+
var UserCancelledError = class extends TaggedError("UserCancelledError") {
|
|
340
340
|
constructor(args) {
|
|
341
341
|
super({ message: args?.message ?? "Operation cancelled" });
|
|
342
342
|
}
|
|
@@ -344,11 +344,11 @@ var UserCancelledError = class extends TaggedError("UserCancelledError")() {
|
|
|
344
344
|
/**
|
|
345
345
|
* General CLI error for validation failures, invalid flags, etc.
|
|
346
346
|
*/
|
|
347
|
-
var CLIError = class extends TaggedError("CLIError")
|
|
347
|
+
var CLIError = class extends TaggedError("CLIError") {};
|
|
348
348
|
/**
|
|
349
349
|
* Validation error for config/flag validation failures
|
|
350
350
|
*/
|
|
351
|
-
var ValidationError = class extends TaggedError("ValidationError")
|
|
351
|
+
var ValidationError = class extends TaggedError("ValidationError") {
|
|
352
352
|
constructor(args) {
|
|
353
353
|
super(args);
|
|
354
354
|
}
|
|
@@ -356,7 +356,7 @@ var ValidationError = class extends TaggedError("ValidationError")() {
|
|
|
356
356
|
/**
|
|
357
357
|
* Compatibility error for incompatible option combinations
|
|
358
358
|
*/
|
|
359
|
-
var CompatibilityError = class extends TaggedError("CompatibilityError")
|
|
359
|
+
var CompatibilityError = class extends TaggedError("CompatibilityError") {
|
|
360
360
|
constructor(args) {
|
|
361
361
|
super(args);
|
|
362
362
|
}
|
|
@@ -364,7 +364,7 @@ var CompatibilityError = class extends TaggedError("CompatibilityError")() {
|
|
|
364
364
|
/**
|
|
365
365
|
* Directory conflict error when target directory exists and is not empty
|
|
366
366
|
*/
|
|
367
|
-
var DirectoryConflictError = class extends TaggedError("DirectoryConflictError")
|
|
367
|
+
var DirectoryConflictError = class extends TaggedError("DirectoryConflictError") {
|
|
368
368
|
constructor(args) {
|
|
369
369
|
super({
|
|
370
370
|
directory: args.directory,
|
|
@@ -375,7 +375,7 @@ var DirectoryConflictError = class extends TaggedError("DirectoryConflictError")
|
|
|
375
375
|
/**
|
|
376
376
|
* Project creation error for failures during scaffolding
|
|
377
377
|
*/
|
|
378
|
-
var ProjectCreationError = class extends TaggedError("ProjectCreationError")
|
|
378
|
+
var ProjectCreationError = class extends TaggedError("ProjectCreationError") {
|
|
379
379
|
constructor(args) {
|
|
380
380
|
super(args);
|
|
381
381
|
}
|
|
@@ -383,7 +383,7 @@ var ProjectCreationError = class extends TaggedError("ProjectCreationError")() {
|
|
|
383
383
|
/**
|
|
384
384
|
* Database setup error for failures during database configuration
|
|
385
385
|
*/
|
|
386
|
-
var DatabaseSetupError = class extends TaggedError("DatabaseSetupError")
|
|
386
|
+
var DatabaseSetupError = class extends TaggedError("DatabaseSetupError") {
|
|
387
387
|
constructor(args) {
|
|
388
388
|
super(args);
|
|
389
389
|
}
|
|
@@ -391,7 +391,7 @@ var DatabaseSetupError = class extends TaggedError("DatabaseSetupError")() {
|
|
|
391
391
|
/**
|
|
392
392
|
* Addon setup error for failures during addon configuration
|
|
393
393
|
*/
|
|
394
|
-
var AddonSetupError = class extends TaggedError("AddonSetupError")
|
|
394
|
+
var AddonSetupError = class extends TaggedError("AddonSetupError") {
|
|
395
395
|
constructor(args) {
|
|
396
396
|
super(args);
|
|
397
397
|
}
|
|
@@ -441,7 +441,7 @@ function getLatestCLIVersion() {
|
|
|
441
441
|
//#region src/utils/project-history.ts
|
|
442
442
|
const paths = envPaths("better-t-stack", { suffix: "" });
|
|
443
443
|
const HISTORY_FILE = "history.json";
|
|
444
|
-
var HistoryError = class extends TaggedError("HistoryError")
|
|
444
|
+
var HistoryError = class extends TaggedError("HistoryError") {};
|
|
445
445
|
function getHistoryDir() {
|
|
446
446
|
return paths.data;
|
|
447
447
|
}
|
|
@@ -1701,15 +1701,37 @@ const evlogWebFrontends = [
|
|
|
1701
1701
|
"tanstack-start",
|
|
1702
1702
|
"astro"
|
|
1703
1703
|
];
|
|
1704
|
+
const NODE_DEV_FS_DRAIN_EXPRESSION = "process.env.NODE_ENV === \"production\" ? undefined : createFsDrain()";
|
|
1705
|
+
const SVELTE_DEV_FS_DRAIN_EXPRESSION = "dev ? createFsDrain() : undefined";
|
|
1706
|
+
const ASTRO_DEV_FS_DRAIN_EXPRESSION = "import.meta.env.DEV ? createFsDrain() : undefined";
|
|
1704
1707
|
function isEvlogBackend(backend) {
|
|
1705
1708
|
return evlogBackends.includes(backend);
|
|
1706
1709
|
}
|
|
1707
1710
|
function getEvlogWebFrontend(frontends) {
|
|
1708
1711
|
return frontends.find((frontend) => evlogWebFrontends.includes(frontend));
|
|
1709
1712
|
}
|
|
1713
|
+
function shouldWireEvlogServerFsDrain(config) {
|
|
1714
|
+
return isEvlogBackend(config.backend) && config.runtime !== "workers" && config.serverDeploy !== "cloudflare";
|
|
1715
|
+
}
|
|
1716
|
+
function shouldWireEvlogWebFsDrain(config) {
|
|
1717
|
+
return getEvlogWebFrontend(config.frontend) !== void 0 && config.webDeploy !== "cloudflare";
|
|
1718
|
+
}
|
|
1719
|
+
function supportsEvlogLocalLogs(config) {
|
|
1720
|
+
return shouldWireEvlogServerFsDrain(config) || shouldWireEvlogWebFsDrain(config);
|
|
1721
|
+
}
|
|
1710
1722
|
function shouldIdentifyWebAuth(config) {
|
|
1711
1723
|
return config.auth === "better-auth" && config.backend === "self";
|
|
1712
1724
|
}
|
|
1725
|
+
function getEvlogServerMiddlewareMarker(backend, fsDrain) {
|
|
1726
|
+
const options = fsDrain ? `{ drain: ${NODE_DEV_FS_DRAIN_EXPRESSION} }` : "";
|
|
1727
|
+
if (backend === "hono" || backend === "express") return `app.use(evlog(${options}));`;
|
|
1728
|
+
if (backend === "fastify") return `fastify.register(evlog${options ? `, ${options}` : ""});`;
|
|
1729
|
+
return `.use(evlog(${options}))`;
|
|
1730
|
+
}
|
|
1731
|
+
function findEvlogServerMiddlewareMarker(content, backend) {
|
|
1732
|
+
const fsDrainMarker = getEvlogServerMiddlewareMarker(backend, true);
|
|
1733
|
+
return content.includes(fsDrainMarker) ? fsDrainMarker : getEvlogServerMiddlewareMarker(backend, false);
|
|
1734
|
+
}
|
|
1713
1735
|
function prependMissingImports(content, imports) {
|
|
1714
1736
|
const missingImports = imports.filter((line) => !content.includes(line));
|
|
1715
1737
|
if (missingImports.length === 0) return content;
|
|
@@ -1771,46 +1793,72 @@ function addEvlogBetterAuthServerSetup(content, backend, authExpression) {
|
|
|
1771
1793
|
const identifySnippet = usesAuthFactory ? "" : `const identifyUser = createAuthMiddleware(${evlogAuthExpression}, ${authOptions});\n\n`;
|
|
1772
1794
|
const identifyUserSetup = usesAuthFactory ? `\n\tconst identifyUser = createAuthMiddleware(${evlogAuthExpression}, ${authOptions});` : "";
|
|
1773
1795
|
if (backend === "hono") {
|
|
1796
|
+
const evlogMarker = findEvlogServerMiddlewareMarker(nextContent, backend);
|
|
1774
1797
|
nextContent = insertBeforeOnce(nextContent, "const app = new Hono", identifySnippet, "createAuthMiddleware(");
|
|
1775
|
-
return insertAfterOnce(nextContent,
|
|
1798
|
+
return insertAfterOnce(nextContent, evlogMarker, `\napp.use("*", async (c, next) => {${identifyUserSetup}\n\tawait identifyUser(c.get("log"), c.req.raw.headers, c.req.path);\n\tawait next();\n});`, "identifyUser(c.get(\"log\")");
|
|
1776
1799
|
}
|
|
1777
1800
|
if (backend === "express") {
|
|
1801
|
+
const evlogMarker = findEvlogServerMiddlewareMarker(nextContent, backend);
|
|
1778
1802
|
nextContent = addNamedImport(nextContent, "evlog/express", ["useLogger"]);
|
|
1779
1803
|
nextContent = insertBeforeOnce(nextContent, "const app = express();", identifySnippet, "createAuthMiddleware(");
|
|
1780
|
-
return insertAfterOnce(nextContent,
|
|
1804
|
+
return insertAfterOnce(nextContent, evlogMarker, `\napp.use(async (req, _res, next) => {${identifyUserSetup}\n\tawait identifyUser(useLogger(), req.headers, req.path);\n\tnext();\n});`, "identifyUser(useLogger()");
|
|
1781
1805
|
}
|
|
1782
1806
|
if (backend === "fastify") {
|
|
1807
|
+
const evlogMarker = findEvlogServerMiddlewareMarker(nextContent, backend);
|
|
1783
1808
|
nextContent = addNamedImport(nextContent, "evlog/fastify", ["useLogger"]);
|
|
1784
1809
|
nextContent = insertBeforeOnce(nextContent, "const fastify = Fastify", identifySnippet, "createAuthMiddleware(");
|
|
1785
|
-
return insertAfterOnce(nextContent,
|
|
1810
|
+
return insertAfterOnce(nextContent, evlogMarker, `\nfastify.addHook("preHandler", async (request) => {${identifyUserSetup}\n\tawait identifyUser(useLogger(), request.headers, request.url);\n});`, "identifyUser(useLogger()");
|
|
1786
1811
|
}
|
|
1787
1812
|
const elysiaMarker = nextContent.includes("const app = new Elysia") ? "const app = new Elysia" : "new Elysia";
|
|
1788
1813
|
nextContent = insertBeforeOnce(nextContent, elysiaMarker, identifySnippet, "createAuthMiddleware(");
|
|
1789
|
-
|
|
1814
|
+
const evlogMarker = findEvlogServerMiddlewareMarker(nextContent, backend);
|
|
1815
|
+
return insertAfterOnce(nextContent, evlogMarker, `\n\t.derive(async ({ request, log }) => {${identifyUserSetup.replace(/\n\t/g, "\n ")}\n\t\tawait identifyUser(log, request.headers, new URL(request.url).pathname);\n\t\treturn {};\n\t})`, "identifyUser(log");
|
|
1790
1816
|
}
|
|
1791
|
-
function addEvlogServerSetup(content, backend, serviceName) {
|
|
1817
|
+
function addEvlogServerSetup(content, backend, serviceName, fsDrain) {
|
|
1792
1818
|
const initSnippet = `initLogger({\n\tenv: { service: "${serviceName}" },\n});\n\n`;
|
|
1819
|
+
const evlogMarker = getEvlogServerMiddlewareMarker(backend, fsDrain);
|
|
1820
|
+
const legacyEvlogMarker = getEvlogServerMiddlewareMarker(backend, false);
|
|
1793
1821
|
if (backend === "hono") {
|
|
1794
|
-
let nextContent = prependMissingImports(content, [
|
|
1822
|
+
let nextContent = prependMissingImports(content, [
|
|
1823
|
+
"import { initLogger } from \"evlog\";",
|
|
1824
|
+
"import { evlog, type EvlogVariables } from \"evlog/hono\";",
|
|
1825
|
+
...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []
|
|
1826
|
+
]);
|
|
1795
1827
|
nextContent = insertBeforeOnce(nextContent, "const app = new Hono", initSnippet, "initLogger({");
|
|
1796
1828
|
nextContent = nextContent.replace("const app = new Hono();", "const app = new Hono<EvlogVariables>();");
|
|
1797
1829
|
nextContent = nextContent.replace("import { logger } from \"hono/logger\";\n", "").replace(/\napp\.use\(logger\(\)\);/, "");
|
|
1798
|
-
|
|
1830
|
+
if (fsDrain) nextContent = nextContent.replace(legacyEvlogMarker, evlogMarker);
|
|
1831
|
+
return insertAfterOnce(nextContent, "const app = new Hono<EvlogVariables>();", `\n\n${evlogMarker}`, evlogMarker);
|
|
1799
1832
|
}
|
|
1800
1833
|
if (backend === "express") {
|
|
1801
|
-
let nextContent = prependMissingImports(content, [
|
|
1834
|
+
let nextContent = prependMissingImports(content, [
|
|
1835
|
+
"import { initLogger } from \"evlog\";",
|
|
1836
|
+
"import { evlog } from \"evlog/express\";",
|
|
1837
|
+
...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []
|
|
1838
|
+
]);
|
|
1802
1839
|
nextContent = insertBeforeOnce(nextContent, "const app = express();", initSnippet, "initLogger({");
|
|
1803
|
-
|
|
1840
|
+
if (fsDrain) nextContent = nextContent.replace(legacyEvlogMarker, evlogMarker);
|
|
1841
|
+
return insertAfterOnce(nextContent, "const app = express();", `\n\n${evlogMarker}`, evlogMarker);
|
|
1804
1842
|
}
|
|
1805
1843
|
if (backend === "fastify") {
|
|
1806
|
-
let nextContent = prependMissingImports(content, [
|
|
1844
|
+
let nextContent = prependMissingImports(content, [
|
|
1845
|
+
"import { initLogger } from \"evlog\";",
|
|
1846
|
+
"import { evlog } from \"evlog/fastify\";",
|
|
1847
|
+
...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []
|
|
1848
|
+
]);
|
|
1807
1849
|
nextContent = insertBeforeOnce(nextContent, "const fastify = Fastify", initSnippet, "initLogger({");
|
|
1808
|
-
|
|
1850
|
+
if (fsDrain) nextContent = nextContent.replace(legacyEvlogMarker, evlogMarker);
|
|
1851
|
+
return insertBeforeOnce(nextContent, "fastify.register(fastifyCors", `${evlogMarker}\n`, evlogMarker);
|
|
1809
1852
|
}
|
|
1810
|
-
let nextContent = prependMissingImports(content, [
|
|
1853
|
+
let nextContent = prependMissingImports(content, [
|
|
1854
|
+
"import { initLogger } from \"evlog\";",
|
|
1855
|
+
"import { evlog } from \"evlog/elysia\";",
|
|
1856
|
+
...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []
|
|
1857
|
+
]);
|
|
1811
1858
|
const elysiaMarker = nextContent.includes("const app = new Elysia") ? "const app = new Elysia" : "new Elysia";
|
|
1812
1859
|
nextContent = insertBeforeOnce(nextContent, elysiaMarker, initSnippet, "initLogger({");
|
|
1813
|
-
|
|
1860
|
+
if (fsDrain) nextContent = nextContent.replace(legacyEvlogMarker, evlogMarker);
|
|
1861
|
+
for (const marker of ["new Elysia({ adapter: node() })", "new Elysia()"]) nextContent = insertAfterOnce(nextContent, marker, `\n\t${evlogMarker}`, evlogMarker);
|
|
1814
1862
|
return nextContent;
|
|
1815
1863
|
}
|
|
1816
1864
|
function addNuxtEvlogSetup(content, serviceName) {
|
|
@@ -1827,14 +1875,20 @@ function addSvelteViteEvlogSetup(content, serviceName) {
|
|
|
1827
1875
|
if (nextContent.includes("evlog({")) return nextContent;
|
|
1828
1876
|
return nextContent.replace("plugins: [tailwindcss(), sveltekit()],", `plugins: [\n tailwindcss(),\n sveltekit(),\n evlog({ service: "${serviceName}" }),\n ],`);
|
|
1829
1877
|
}
|
|
1830
|
-
function
|
|
1831
|
-
|
|
1878
|
+
function getSvelteEvlogHooksCall(fsDrain) {
|
|
1879
|
+
return fsDrain ? `createEvlogHooks({ drain: ${SVELTE_DEV_FS_DRAIN_EXPRESSION} })` : "createEvlogHooks()";
|
|
1880
|
+
}
|
|
1881
|
+
function addSvelteHooksEvlogSetup(content, fsDrain) {
|
|
1882
|
+
let nextContent = prependMissingImports(content, ["import { createEvlogHooks } from \"evlog/sveltekit\";", ...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []]);
|
|
1883
|
+
if (fsDrain) nextContent = addNamedImport(nextContent, "$app/environment", ["dev"]);
|
|
1884
|
+
const hooksCall = getSvelteEvlogHooksCall(fsDrain);
|
|
1885
|
+
if (fsDrain) nextContent = nextContent.replaceAll("createEvlogHooks()", hooksCall);
|
|
1832
1886
|
if (!nextContent.includes("export const handle") && !nextContent.includes("const authHandle")) {
|
|
1833
|
-
if (!nextContent.includes("createEvlogHooks(
|
|
1887
|
+
if (!nextContent.includes("createEvlogHooks(")) nextContent = `${nextContent.trimEnd()}\n\nexport const { handle, handleError } = ${hooksCall};\n`;
|
|
1834
1888
|
return nextContent;
|
|
1835
1889
|
}
|
|
1836
1890
|
nextContent = prependMissingImports(nextContent, ["import { sequence } from \"@sveltejs/kit/hooks\";"]);
|
|
1837
|
-
if (!nextContent.includes("const { handle: evlogHandle, handleError }")) nextContent = nextContent.replace(/((?:import .+\n)+)/, `$1\nconst { handle: evlogHandle, handleError } =
|
|
1891
|
+
if (!nextContent.includes("const { handle: evlogHandle, handleError }")) nextContent = nextContent.replace(/((?:import .+\n)+)/, `$1\nconst { handle: evlogHandle, handleError } = ${hooksCall};\n\n`);
|
|
1838
1892
|
nextContent = nextContent.replace(/export const handle(:\s*Handle)?\s*=\s*async/, (_match, typeAnnotation) => `const authHandle${typeAnnotation ?? ""} = async`);
|
|
1839
1893
|
if (!nextContent.includes("sequence(evlogHandle, authHandle)")) nextContent = `${nextContent.trimEnd()}\n\nexport const handle = sequence(evlogHandle as Handle, authHandle);\nexport { handleError };\n`;
|
|
1840
1894
|
return nextContent;
|
|
@@ -1853,10 +1907,14 @@ function addTanstackStartRootEvlogSetup(content) {
|
|
|
1853
1907
|
if (/server:\s*{/.test(nextContent)) return nextContent.replace(/server:\s*{\n/, `server: {\n middleware: [${middlewareEntry}],\n`);
|
|
1854
1908
|
return nextContent.replace("head: () => ({", `server: {\n middleware: [${middlewareEntry}],\n },\n\n head: () => ({`);
|
|
1855
1909
|
}
|
|
1856
|
-
function
|
|
1857
|
-
|
|
1858
|
-
|
|
1910
|
+
function getInitLoggerSnippet(serviceName, fsDrain, indent) {
|
|
1911
|
+
return `initLogger({\n${indent}env: { service: "${serviceName}" },${fsDrain ? `\n${indent}drain: ${ASTRO_DEV_FS_DRAIN_EXPRESSION},` : ""}\n});\n\n`;
|
|
1912
|
+
}
|
|
1913
|
+
function addAstroMiddlewareEvlogSetup(content, serviceName, fsDrain) {
|
|
1914
|
+
let nextContent = prependMissingImports(content, ["import { createRequestLogger, initLogger } from \"evlog\";", ...fsDrain ? ["import { createFsDrain } from \"evlog/fs\";"] : []]);
|
|
1915
|
+
const initSnippet = getInitLoggerSnippet(serviceName, fsDrain, " ");
|
|
1859
1916
|
nextContent = insertBeforeOnce(nextContent, "export const onRequest", initSnippet, "initLogger({");
|
|
1917
|
+
if (fsDrain && !nextContent.includes("drain:")) nextContent = nextContent.replace(/initLogger\(\{\n(\s+env: \{ service: "[^"]+" \},)/, `initLogger({\n$1\n drain: ${ASTRO_DEV_FS_DRAIN_EXPRESSION},`);
|
|
1860
1918
|
if (nextContent.includes("createRequestLogger({")) return nextContent;
|
|
1861
1919
|
const contextMarker = "export const onRequest = defineMiddleware(async (context, next) => {";
|
|
1862
1920
|
if (nextContent.includes(contextMarker)) {
|
|
@@ -1931,7 +1989,8 @@ function addSvelteBetterAuthEvlogSetup(content, config) {
|
|
|
1931
1989
|
const authExpression = getAuthExpression(config);
|
|
1932
1990
|
const authOptions = "{ exclude: [\"/api/auth/**\"], maskEmail: true }";
|
|
1933
1991
|
const authHandleSnippet = usesCreateAuthFactory(config) && config.webDeploy === "cloudflare" ? `const evlogAuthHandle: Handle = async ({ event, resolve }) => {\n\tif (building) {\n\t\treturn resolve(event);\n\t}\n\n\tconst authEnv = event.platform?.env ?? localEnv;\n\tconst identifyUser = createAuthMiddleware(createAuth(authEnv) as BetterAuthInstance, ${authOptions});\n\tawait identifyUser(event.locals.log, event.request.headers, event.url.pathname);\n\treturn resolve(event);\n};\n\n` : `const identifyUser = createAuthMiddleware(${authExpression} as BetterAuthInstance, ${authOptions});\n\nconst evlogAuthHandle: Handle = async ({ event, resolve }) => {\n\tawait identifyUser(event.locals.log, event.request.headers, event.url.pathname);\n\treturn resolve(event);\n};\n\n`;
|
|
1934
|
-
|
|
1992
|
+
const evlogHandleDeclaration = nextContent.match(/const \{ handle: evlogHandle, handleError \} = createEvlogHooks\([\s\S]*?\);\n\n/)?.[0];
|
|
1993
|
+
if (evlogHandleDeclaration) nextContent = insertAfterOnce(nextContent, evlogHandleDeclaration, authHandleSnippet, "evlogAuthHandle");
|
|
1935
1994
|
return nextContent.replace("sequence(evlogHandle as Handle, authHandle)", "sequence(evlogHandle as Handle, evlogAuthHandle, authHandle)").replace("sequence(evlogHandle, authHandle)", "sequence(evlogHandle as Handle, evlogAuthHandle, authHandle)");
|
|
1936
1995
|
}
|
|
1937
1996
|
function addAstroBetterAuthEvlogSetup(content, config) {
|
|
@@ -1950,19 +2009,29 @@ function addAstroBetterAuthEvlogSetup(content, config) {
|
|
|
1950
2009
|
}
|
|
1951
2010
|
return nextContent;
|
|
1952
2011
|
}
|
|
1953
|
-
function getNextEvlogFile(serviceName) {
|
|
2012
|
+
function getNextEvlogFile(serviceName, fsDrain) {
|
|
1954
2013
|
return `import { createEvlog } from "evlog/next";
|
|
1955
2014
|
import { createInstrumentation } from "evlog/next/instrumentation/create";
|
|
2015
|
+
${fsDrain ? "import { createFsDrain } from \"evlog/fs\";\n" : ""}
|
|
1956
2016
|
|
|
1957
2017
|
export const { withEvlog, useLogger, log, createError } = createEvlog({
|
|
1958
2018
|
service: "${serviceName}",
|
|
1959
|
-
});
|
|
2019
|
+
${fsDrain ? ` drain: ${NODE_DEV_FS_DRAIN_EXPRESSION},\n` : ""}});
|
|
1960
2020
|
|
|
1961
2021
|
export const { register, onRequestError } = createInstrumentation({
|
|
1962
2022
|
service: "${serviceName}",
|
|
1963
2023
|
});
|
|
1964
2024
|
`;
|
|
1965
2025
|
}
|
|
2026
|
+
function getNitroEvlogDrainFile() {
|
|
2027
|
+
return `import { createFsDrain } from "evlog/fs";
|
|
2028
|
+
|
|
2029
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
2030
|
+
if (!import.meta.dev) return;
|
|
2031
|
+
nitroApp.hooks.hook("evlog:drain", createFsDrain());
|
|
2032
|
+
});
|
|
2033
|
+
`;
|
|
2034
|
+
}
|
|
1966
2035
|
function getNextInstrumentationFile() {
|
|
1967
2036
|
return `import { defineNodeInstrumentation } from "evlog/next/instrumentation";
|
|
1968
2037
|
|
|
@@ -2077,13 +2146,12 @@ export default defineConfig({
|
|
|
2077
2146
|
});
|
|
2078
2147
|
`;
|
|
2079
2148
|
}
|
|
2080
|
-
function getAstroMiddlewareFile(serviceName) {
|
|
2149
|
+
function getAstroMiddlewareFile(serviceName, fsDrain) {
|
|
2081
2150
|
return `import { defineMiddleware } from "astro:middleware";
|
|
2082
2151
|
import { createRequestLogger, initLogger } from "evlog";
|
|
2152
|
+
${fsDrain ? "import { createFsDrain } from \"evlog/fs\";\n" : ""}
|
|
2083
2153
|
|
|
2084
|
-
|
|
2085
|
-
env: { service: "${serviceName}" },
|
|
2086
|
-
});
|
|
2154
|
+
${getInitLoggerSnippet(serviceName, fsDrain, " ").trimEnd()}
|
|
2087
2155
|
|
|
2088
2156
|
export const onRequest = defineMiddleware(async ({ request, locals }, next) => {
|
|
2089
2157
|
const url = new URL(request.url);
|
|
@@ -2120,8 +2188,9 @@ declare namespace App {
|
|
|
2120
2188
|
}
|
|
2121
2189
|
async function setupNextEvlog(config, serviceName) {
|
|
2122
2190
|
const webDir = path.join(config.projectDir, "apps/web");
|
|
2191
|
+
const fsDrain = shouldWireEvlogWebFsDrain(config);
|
|
2123
2192
|
const evlogPath = path.join(webDir, "src/lib/evlog.ts");
|
|
2124
|
-
if (!await fs.pathExists(evlogPath)) await writeFileIfChanged(evlogPath, getNextEvlogFile(serviceName));
|
|
2193
|
+
if (!await fs.pathExists(evlogPath)) await writeFileIfChanged(evlogPath, getNextEvlogFile(serviceName, fsDrain));
|
|
2125
2194
|
const identifyWebAuth = shouldIdentifyWebAuth(config);
|
|
2126
2195
|
if (identifyWebAuth) {
|
|
2127
2196
|
const evlogAuthPath = path.join(webDir, "src/lib/evlog-auth.ts");
|
|
@@ -2147,7 +2216,12 @@ async function setupNextEvlog(config, serviceName) {
|
|
|
2147
2216
|
}
|
|
2148
2217
|
async function setupNuxtEvlog(config, serviceName) {
|
|
2149
2218
|
const webDir = path.join(config.projectDir, "apps/web");
|
|
2219
|
+
const fsDrain = shouldWireEvlogWebFsDrain(config);
|
|
2150
2220
|
await updateFileIfExists(path.join(webDir, "nuxt.config.ts"), (content) => addNuxtEvlogSetup(content, serviceName));
|
|
2221
|
+
if (fsDrain) {
|
|
2222
|
+
const drainPath = path.join(webDir, "server/plugins/evlog-drain.ts");
|
|
2223
|
+
if (!await fs.pathExists(drainPath)) await writeFileIfChanged(drainPath, getNitroEvlogDrainFile());
|
|
2224
|
+
}
|
|
2151
2225
|
if (shouldIdentifyWebAuth(config)) {
|
|
2152
2226
|
const oldAuthPluginPath = path.join(webDir, "server/plugins/evlog-auth.ts");
|
|
2153
2227
|
if (await fs.pathExists(oldAuthPluginPath)) {
|
|
@@ -2160,12 +2234,15 @@ async function setupNuxtEvlog(config, serviceName) {
|
|
|
2160
2234
|
}
|
|
2161
2235
|
async function setupSvelteEvlog(config, serviceName) {
|
|
2162
2236
|
const webDir = path.join(config.projectDir, "apps/web");
|
|
2237
|
+
const fsDrain = shouldWireEvlogWebFsDrain(config);
|
|
2163
2238
|
await updateFileIfExists(path.join(webDir, "vite.config.ts"), (content) => addSvelteViteEvlogSetup(content, serviceName));
|
|
2164
2239
|
const hooksPath = path.join(webDir, "src/hooks.server.ts");
|
|
2165
|
-
if (await fs.pathExists(hooksPath)) await updateFileIfExists(hooksPath, addSvelteHooksEvlogSetup);
|
|
2240
|
+
if (await fs.pathExists(hooksPath)) await updateFileIfExists(hooksPath, (content) => addSvelteHooksEvlogSetup(content, fsDrain));
|
|
2166
2241
|
else await writeFileIfChanged(hooksPath, `import { createEvlogHooks } from "evlog/sveltekit";
|
|
2242
|
+
${fsDrain ? "import { createFsDrain } from \"evlog/fs\";\n" : ""}
|
|
2243
|
+
${fsDrain ? "import { dev } from \"$app/environment\";\n" : ""}
|
|
2167
2244
|
|
|
2168
|
-
export const { handle, handleError } =
|
|
2245
|
+
export const { handle, handleError } = ${getSvelteEvlogHooksCall(fsDrain)};
|
|
2169
2246
|
`);
|
|
2170
2247
|
await updateFileIfExists(path.join(webDir, "src/app.d.ts"), addSvelteLocalsType);
|
|
2171
2248
|
if (shouldIdentifyWebAuth(config)) await updateFileIfExists(path.join(webDir, "src/hooks.server.ts"), (content) => addSvelteBetterAuthEvlogSetup(content, config));
|
|
@@ -2173,9 +2250,14 @@ export const { handle, handleError } = createEvlogHooks();
|
|
|
2173
2250
|
}
|
|
2174
2251
|
async function setupTanstackStartEvlog(config, serviceName) {
|
|
2175
2252
|
const webDir = path.join(config.projectDir, "apps/web");
|
|
2253
|
+
const fsDrain = shouldWireEvlogWebFsDrain(config);
|
|
2176
2254
|
const nitroConfigPath = path.join(webDir, "nitro.config.ts");
|
|
2177
2255
|
if (!await fs.pathExists(nitroConfigPath)) await writeFileIfChanged(nitroConfigPath, getTanstackNitroConfigFile(serviceName));
|
|
2178
2256
|
await updateFileIfExists(path.join(webDir, "src/routes/__root.tsx"), addTanstackStartRootEvlogSetup);
|
|
2257
|
+
if (fsDrain) {
|
|
2258
|
+
const drainPath = path.join(webDir, "server/plugins/evlog-drain.ts");
|
|
2259
|
+
if (!await fs.pathExists(drainPath)) await writeFileIfChanged(drainPath, getNitroEvlogDrainFile());
|
|
2260
|
+
}
|
|
2179
2261
|
if (shouldIdentifyWebAuth(config)) {
|
|
2180
2262
|
const authPluginPath = path.join(webDir, "server/plugins/evlog-auth.ts");
|
|
2181
2263
|
if (!await fs.pathExists(authPluginPath)) await writeFileIfChanged(authPluginPath, getNitroEvlogAuthPluginFile(config));
|
|
@@ -2184,9 +2266,10 @@ async function setupTanstackStartEvlog(config, serviceName) {
|
|
|
2184
2266
|
}
|
|
2185
2267
|
async function setupAstroEvlog(config, serviceName) {
|
|
2186
2268
|
const webDir = path.join(config.projectDir, "apps/web");
|
|
2269
|
+
const fsDrain = shouldWireEvlogWebFsDrain(config);
|
|
2187
2270
|
const middlewarePath = path.join(webDir, "src/middleware.ts");
|
|
2188
|
-
if (!await fs.pathExists(middlewarePath)) await writeFileIfChanged(middlewarePath, getAstroMiddlewareFile(serviceName));
|
|
2189
|
-
else await updateFileIfExists(middlewarePath, (content) => addAstroMiddlewareEvlogSetup(content, serviceName));
|
|
2271
|
+
if (!await fs.pathExists(middlewarePath)) await writeFileIfChanged(middlewarePath, getAstroMiddlewareFile(serviceName, fsDrain));
|
|
2272
|
+
else await updateFileIfExists(middlewarePath, (content) => addAstroMiddlewareEvlogSetup(content, serviceName, fsDrain));
|
|
2190
2273
|
const envPath = path.join(webDir, "src/env.d.ts");
|
|
2191
2274
|
if (!await fs.pathExists(envPath)) await writeFileIfChanged(envPath, getAstroEnvFile());
|
|
2192
2275
|
else await updateFileIfExists(envPath, addAstroLocalsType);
|
|
@@ -2209,7 +2292,7 @@ async function setupEvlog(config) {
|
|
|
2209
2292
|
const serverIndexPath = path.join(config.projectDir, "apps/server/src/index.ts");
|
|
2210
2293
|
if (await fs.pathExists(serverIndexPath)) {
|
|
2211
2294
|
const content = await fs.readFile(serverIndexPath, "utf-8");
|
|
2212
|
-
let nextContent = addEvlogServerSetup(content, config.backend, `${config.projectName}-server
|
|
2295
|
+
let nextContent = addEvlogServerSetup(content, config.backend, `${config.projectName}-server`, shouldWireEvlogServerFsDrain(config));
|
|
2213
2296
|
if (config.auth === "better-auth") nextContent = addEvlogBetterAuthServerSetup(nextContent, config.backend, getAuthExpression(config));
|
|
2214
2297
|
if (config.examples.includes("ai")) nextContent = addBackendAiEvlogSetup(nextContent, config.backend);
|
|
2215
2298
|
if (nextContent !== content) await fs.writeFile(serverIndexPath, nextContent);
|
|
@@ -2431,6 +2514,10 @@ const TEMPLATES$2 = {
|
|
|
2431
2514
|
label: "Tanstack Start SPA: Fumadocs MDX (not RSC)",
|
|
2432
2515
|
hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
|
|
2433
2516
|
value: "tanstack-start-spa"
|
|
2517
|
+
},
|
|
2518
|
+
astro: {
|
|
2519
|
+
label: "Astro: Fumadocs MDX",
|
|
2520
|
+
value: "astro"
|
|
2434
2521
|
}
|
|
2435
2522
|
};
|
|
2436
2523
|
const DEFAULT_TEMPLATE$2 = "next-mdx";
|
|
@@ -2444,7 +2531,7 @@ function getFumadocsLinter(addons) {
|
|
|
2444
2531
|
if (addons.includes("vite-plus")) return "oxlint";
|
|
2445
2532
|
}
|
|
2446
2533
|
function getFumadocsAddonContext(currentAddons, persistedAddons) {
|
|
2447
|
-
return Array.from(new Set([...persistedAddons ?? [], ...currentAddons]));
|
|
2534
|
+
return Array.from(/* @__PURE__ */ new Set([...persistedAddons ?? [], ...currentAddons]));
|
|
2448
2535
|
}
|
|
2449
2536
|
async function setupFumadocs(config) {
|
|
2450
2537
|
if (shouldSkipExternalCommands()) return Result.ok(void 0);
|
|
@@ -2646,6 +2733,11 @@ const MCP_AGENTS = [
|
|
|
2646
2733
|
label: "GitHub Copilot CLI",
|
|
2647
2734
|
scope: "both"
|
|
2648
2735
|
},
|
|
2736
|
+
{
|
|
2737
|
+
value: "grok-build",
|
|
2738
|
+
label: "Grok Build",
|
|
2739
|
+
scope: "both"
|
|
2740
|
+
},
|
|
2649
2741
|
{
|
|
2650
2742
|
value: "mcporter",
|
|
2651
2743
|
label: "MCPorter",
|
|
@@ -2656,6 +2748,11 @@ const MCP_AGENTS = [
|
|
|
2656
2748
|
label: "VS Code (GitHub Copilot)",
|
|
2657
2749
|
scope: "both"
|
|
2658
2750
|
},
|
|
2751
|
+
{
|
|
2752
|
+
value: "windsurf",
|
|
2753
|
+
label: "Windsurf",
|
|
2754
|
+
scope: "global"
|
|
2755
|
+
},
|
|
2659
2756
|
{
|
|
2660
2757
|
value: "zed",
|
|
2661
2758
|
label: "Zed",
|
|
@@ -3029,10 +3126,42 @@ const SKILL_SOURCES = {
|
|
|
3029
3126
|
"haydenbleasel/ultracite": { label: "Ultracite" },
|
|
3030
3127
|
"https://www.evlog.dev": { label: "evlog" }
|
|
3031
3128
|
};
|
|
3032
|
-
const
|
|
3129
|
+
const SKILLS_CLI_AGENT_OPTIONS = [
|
|
3033
3130
|
{
|
|
3034
|
-
value: "
|
|
3035
|
-
label: "
|
|
3131
|
+
value: "adal",
|
|
3132
|
+
label: "AdaL"
|
|
3133
|
+
},
|
|
3134
|
+
{
|
|
3135
|
+
value: "aider-desk",
|
|
3136
|
+
label: "AiderDesk"
|
|
3137
|
+
},
|
|
3138
|
+
{
|
|
3139
|
+
value: "amp",
|
|
3140
|
+
label: "Amp"
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
value: "antigravity",
|
|
3144
|
+
label: "Antigravity"
|
|
3145
|
+
},
|
|
3146
|
+
{
|
|
3147
|
+
value: "antigravity-cli",
|
|
3148
|
+
label: "Antigravity CLI"
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
value: "astrbot",
|
|
3152
|
+
label: "AstrBot"
|
|
3153
|
+
},
|
|
3154
|
+
{
|
|
3155
|
+
value: "augment",
|
|
3156
|
+
label: "Augment"
|
|
3157
|
+
},
|
|
3158
|
+
{
|
|
3159
|
+
value: "autohand-code",
|
|
3160
|
+
label: "Autohand Code CLI"
|
|
3161
|
+
},
|
|
3162
|
+
{
|
|
3163
|
+
value: "bob",
|
|
3164
|
+
label: "IBM Bob"
|
|
3036
3165
|
},
|
|
3037
3166
|
{
|
|
3038
3167
|
value: "claude-code",
|
|
@@ -3043,100 +3172,306 @@ const AVAILABLE_AGENTS = [
|
|
|
3043
3172
|
label: "Cline"
|
|
3044
3173
|
},
|
|
3045
3174
|
{
|
|
3046
|
-
value: "
|
|
3047
|
-
label: "
|
|
3175
|
+
value: "codearts-agent",
|
|
3176
|
+
label: "CodeArts Agent"
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
value: "codebuddy",
|
|
3180
|
+
label: "CodeBuddy"
|
|
3181
|
+
},
|
|
3182
|
+
{
|
|
3183
|
+
value: "codemaker",
|
|
3184
|
+
label: "Codemaker"
|
|
3185
|
+
},
|
|
3186
|
+
{
|
|
3187
|
+
value: "codestudio",
|
|
3188
|
+
label: "Code Studio"
|
|
3048
3189
|
},
|
|
3049
3190
|
{
|
|
3050
3191
|
value: "codex",
|
|
3051
3192
|
label: "Codex"
|
|
3052
3193
|
},
|
|
3053
3194
|
{
|
|
3054
|
-
value: "
|
|
3055
|
-
label: "
|
|
3195
|
+
value: "command-code",
|
|
3196
|
+
label: "Command Code"
|
|
3056
3197
|
},
|
|
3057
3198
|
{
|
|
3058
|
-
value: "
|
|
3059
|
-
label: "
|
|
3199
|
+
value: "continue",
|
|
3200
|
+
label: "Continue"
|
|
3201
|
+
},
|
|
3202
|
+
{
|
|
3203
|
+
value: "cortex",
|
|
3204
|
+
label: "Cortex Code"
|
|
3205
|
+
},
|
|
3206
|
+
{
|
|
3207
|
+
value: "crush",
|
|
3208
|
+
label: "Crush"
|
|
3209
|
+
},
|
|
3210
|
+
{
|
|
3211
|
+
value: "cursor",
|
|
3212
|
+
label: "Cursor"
|
|
3213
|
+
},
|
|
3214
|
+
{
|
|
3215
|
+
value: "deepagents",
|
|
3216
|
+
label: "Deep Agents"
|
|
3217
|
+
},
|
|
3218
|
+
{
|
|
3219
|
+
value: "devin",
|
|
3220
|
+
label: "Devin for Terminal"
|
|
3221
|
+
},
|
|
3222
|
+
{
|
|
3223
|
+
value: "dexto",
|
|
3224
|
+
label: "Dexto"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
value: "droid",
|
|
3228
|
+
label: "Droid"
|
|
3229
|
+
},
|
|
3230
|
+
{
|
|
3231
|
+
value: "eve",
|
|
3232
|
+
label: "Eve"
|
|
3233
|
+
},
|
|
3234
|
+
{
|
|
3235
|
+
value: "firebender",
|
|
3236
|
+
label: "Firebender"
|
|
3237
|
+
},
|
|
3238
|
+
{
|
|
3239
|
+
value: "forgecode",
|
|
3240
|
+
label: "ForgeCode"
|
|
3241
|
+
},
|
|
3242
|
+
{
|
|
3243
|
+
value: "gemini-cli",
|
|
3244
|
+
label: "Gemini CLI"
|
|
3245
|
+
},
|
|
3246
|
+
{
|
|
3247
|
+
value: "github-copilot",
|
|
3248
|
+
label: "GitHub Copilot"
|
|
3060
3249
|
},
|
|
3061
3250
|
{
|
|
3062
3251
|
value: "goose",
|
|
3063
3252
|
label: "Goose"
|
|
3064
3253
|
},
|
|
3065
3254
|
{
|
|
3066
|
-
value: "
|
|
3067
|
-
label: "
|
|
3255
|
+
value: "grok",
|
|
3256
|
+
label: "Grok Build"
|
|
3257
|
+
},
|
|
3258
|
+
{
|
|
3259
|
+
value: "hermes-agent",
|
|
3260
|
+
label: "Hermes Agent"
|
|
3261
|
+
},
|
|
3262
|
+
{
|
|
3263
|
+
value: "iflow-cli",
|
|
3264
|
+
label: "iFlow CLI"
|
|
3265
|
+
},
|
|
3266
|
+
{
|
|
3267
|
+
value: "inference-sh",
|
|
3268
|
+
label: "inference.sh"
|
|
3269
|
+
},
|
|
3270
|
+
{
|
|
3271
|
+
value: "jazz",
|
|
3272
|
+
label: "Jazz"
|
|
3273
|
+
},
|
|
3274
|
+
{
|
|
3275
|
+
value: "junie",
|
|
3276
|
+
label: "Junie"
|
|
3068
3277
|
},
|
|
3069
3278
|
{
|
|
3070
3279
|
value: "kilo",
|
|
3071
3280
|
label: "Kilo Code"
|
|
3072
3281
|
},
|
|
3073
3282
|
{
|
|
3074
|
-
value: "
|
|
3075
|
-
label: "
|
|
3283
|
+
value: "kimchi",
|
|
3284
|
+
label: "Kimchi"
|
|
3076
3285
|
},
|
|
3077
3286
|
{
|
|
3078
|
-
value: "
|
|
3079
|
-
label: "
|
|
3287
|
+
value: "kimi-code-cli",
|
|
3288
|
+
label: "Kimi Code CLI"
|
|
3080
3289
|
},
|
|
3081
3290
|
{
|
|
3082
|
-
value: "
|
|
3083
|
-
label: "
|
|
3291
|
+
value: "kiro-cli",
|
|
3292
|
+
label: "Kiro CLI"
|
|
3084
3293
|
},
|
|
3085
3294
|
{
|
|
3086
|
-
value: "
|
|
3087
|
-
label: "
|
|
3295
|
+
value: "kode",
|
|
3296
|
+
label: "Kode"
|
|
3088
3297
|
},
|
|
3089
3298
|
{
|
|
3090
|
-
value: "
|
|
3091
|
-
label: "
|
|
3299
|
+
value: "lingma",
|
|
3300
|
+
label: "Lingma"
|
|
3301
|
+
},
|
|
3302
|
+
{
|
|
3303
|
+
value: "loaf",
|
|
3304
|
+
label: "Loaf"
|
|
3305
|
+
},
|
|
3306
|
+
{
|
|
3307
|
+
value: "mcpjam",
|
|
3308
|
+
label: "MCPJam"
|
|
3309
|
+
},
|
|
3310
|
+
{
|
|
3311
|
+
value: "mistral-vibe",
|
|
3312
|
+
label: "Mistral Vibe"
|
|
3313
|
+
},
|
|
3314
|
+
{
|
|
3315
|
+
value: "moxby",
|
|
3316
|
+
label: "Moxby"
|
|
3317
|
+
},
|
|
3318
|
+
{
|
|
3319
|
+
value: "mux",
|
|
3320
|
+
label: "Mux"
|
|
3321
|
+
},
|
|
3322
|
+
{
|
|
3323
|
+
value: "neovate",
|
|
3324
|
+
label: "Neovate"
|
|
3325
|
+
},
|
|
3326
|
+
{
|
|
3327
|
+
value: "ona",
|
|
3328
|
+
label: "Ona"
|
|
3329
|
+
},
|
|
3330
|
+
{
|
|
3331
|
+
value: "openclaw",
|
|
3332
|
+
label: "OpenClaw"
|
|
3333
|
+
},
|
|
3334
|
+
{
|
|
3335
|
+
value: "opencode",
|
|
3336
|
+
label: "OpenCode"
|
|
3337
|
+
},
|
|
3338
|
+
{
|
|
3339
|
+
value: "openhands",
|
|
3340
|
+
label: "OpenHands"
|
|
3092
3341
|
},
|
|
3093
3342
|
{
|
|
3094
3343
|
value: "pi",
|
|
3095
3344
|
label: "Pi"
|
|
3096
3345
|
},
|
|
3346
|
+
{
|
|
3347
|
+
value: "pochi",
|
|
3348
|
+
label: "Pochi"
|
|
3349
|
+
},
|
|
3350
|
+
{
|
|
3351
|
+
value: "promptscript",
|
|
3352
|
+
label: "PromptScript"
|
|
3353
|
+
},
|
|
3097
3354
|
{
|
|
3098
3355
|
value: "qoder",
|
|
3099
3356
|
label: "Qoder"
|
|
3100
3357
|
},
|
|
3358
|
+
{
|
|
3359
|
+
value: "qoder-cn",
|
|
3360
|
+
label: "Qoder CN"
|
|
3361
|
+
},
|
|
3101
3362
|
{
|
|
3102
3363
|
value: "qwen-code",
|
|
3103
3364
|
label: "Qwen Code"
|
|
3104
3365
|
},
|
|
3105
3366
|
{
|
|
3106
|
-
value: "
|
|
3107
|
-
label: "
|
|
3367
|
+
value: "reasonix",
|
|
3368
|
+
label: "Reasonix"
|
|
3108
3369
|
},
|
|
3109
3370
|
{
|
|
3110
|
-
value: "
|
|
3111
|
-
label: "
|
|
3371
|
+
value: "replit",
|
|
3372
|
+
label: "Replit"
|
|
3112
3373
|
},
|
|
3113
3374
|
{
|
|
3114
|
-
value: "
|
|
3115
|
-
label: "
|
|
3375
|
+
value: "roo",
|
|
3376
|
+
label: "Roo Code"
|
|
3116
3377
|
},
|
|
3117
3378
|
{
|
|
3118
|
-
value: "
|
|
3119
|
-
label: "
|
|
3379
|
+
value: "rovodev",
|
|
3380
|
+
label: "Rovo Dev"
|
|
3120
3381
|
},
|
|
3121
3382
|
{
|
|
3122
|
-
value: "
|
|
3123
|
-
label: "
|
|
3383
|
+
value: "tabnine-cli",
|
|
3384
|
+
label: "Tabnine CLI"
|
|
3124
3385
|
},
|
|
3125
3386
|
{
|
|
3126
|
-
value: "
|
|
3127
|
-
label: "
|
|
3387
|
+
value: "terramind",
|
|
3388
|
+
label: "Terramind"
|
|
3128
3389
|
},
|
|
3129
3390
|
{
|
|
3130
|
-
value: "
|
|
3131
|
-
label: "
|
|
3391
|
+
value: "tinycloud",
|
|
3392
|
+
label: "Tinycloud"
|
|
3393
|
+
},
|
|
3394
|
+
{
|
|
3395
|
+
value: "trae",
|
|
3396
|
+
label: "Trae"
|
|
3397
|
+
},
|
|
3398
|
+
{
|
|
3399
|
+
value: "trae-cn",
|
|
3400
|
+
label: "Trae CN"
|
|
3401
|
+
},
|
|
3402
|
+
{
|
|
3403
|
+
value: "universal",
|
|
3404
|
+
label: "Universal"
|
|
3405
|
+
},
|
|
3406
|
+
{
|
|
3407
|
+
value: "warp",
|
|
3408
|
+
label: "Warp"
|
|
3409
|
+
},
|
|
3410
|
+
{
|
|
3411
|
+
value: "windsurf",
|
|
3412
|
+
label: "Windsurf"
|
|
3413
|
+
},
|
|
3414
|
+
{
|
|
3415
|
+
value: "zcode",
|
|
3416
|
+
label: "ZCode"
|
|
3417
|
+
},
|
|
3418
|
+
{
|
|
3419
|
+
value: "zed",
|
|
3420
|
+
label: "Zed"
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
value: "zencoder",
|
|
3424
|
+
label: "Zencoder"
|
|
3425
|
+
},
|
|
3426
|
+
{
|
|
3427
|
+
value: "zenflow",
|
|
3428
|
+
label: "Zenflow"
|
|
3132
3429
|
}
|
|
3133
3430
|
];
|
|
3134
|
-
const
|
|
3135
|
-
|
|
3431
|
+
const UNIVERSAL_SKILLS_AGENTS = [
|
|
3432
|
+
"amp",
|
|
3433
|
+
"antigravity",
|
|
3434
|
+
"antigravity-cli",
|
|
3435
|
+
"cline",
|
|
3436
|
+
"codex",
|
|
3136
3437
|
"cursor",
|
|
3137
|
-
"
|
|
3138
|
-
"
|
|
3438
|
+
"deepagents",
|
|
3439
|
+
"dexto",
|
|
3440
|
+
"firebender",
|
|
3441
|
+
"gemini-cli",
|
|
3442
|
+
"github-copilot",
|
|
3443
|
+
"kimi-code-cli",
|
|
3444
|
+
"loaf",
|
|
3445
|
+
"opencode",
|
|
3446
|
+
"promptscript",
|
|
3447
|
+
"warp",
|
|
3448
|
+
"zed"
|
|
3449
|
+
];
|
|
3450
|
+
const PROMPT_HIDDEN_AGENTS = /* @__PURE__ */ new Set([
|
|
3451
|
+
...UNIVERSAL_SKILLS_AGENTS,
|
|
3452
|
+
"universal",
|
|
3453
|
+
"eve",
|
|
3454
|
+
"replit"
|
|
3455
|
+
]);
|
|
3456
|
+
const SKILLS_AGENT_PROMPT_OPTIONS = [
|
|
3457
|
+
{
|
|
3458
|
+
value: "universal",
|
|
3459
|
+
label: "Universal (.agents/skills)",
|
|
3460
|
+
hint: "17 agents including Amp, Antigravity, Cline, Codex, Cursor, Gemini CLI, Copilot, OpenCode, Warp, and Zed"
|
|
3461
|
+
},
|
|
3462
|
+
...SKILLS_CLI_AGENT_OPTIONS.filter(({ value }) => value === "claude-code"),
|
|
3463
|
+
...SKILLS_CLI_AGENT_OPTIONS.filter(({ value }) => value !== "claude-code" && !PROMPT_HIDDEN_AGENTS.has(value))
|
|
3139
3464
|
];
|
|
3465
|
+
function expandSkillsAgentTargets(agents) {
|
|
3466
|
+
const expanded = agents.flatMap((agent) => {
|
|
3467
|
+
if (agent === "universal") return [...UNIVERSAL_SKILLS_AGENTS];
|
|
3468
|
+
if (agent === "clawdbot") return ["openclaw"];
|
|
3469
|
+
return [agent];
|
|
3470
|
+
});
|
|
3471
|
+
return Array.from(new Set(expanded));
|
|
3472
|
+
}
|
|
3473
|
+
const DEFAULT_SCOPE = "project";
|
|
3474
|
+
const DEFAULT_AGENTS$1 = ["universal", "claude-code"];
|
|
3140
3475
|
function hasReactBasedFrontend(frontend) {
|
|
3141
3476
|
return frontend.includes("react-router") || frontend.includes("tanstack-router") || frontend.includes("tanstack-start") || frontend.includes("next");
|
|
3142
3477
|
}
|
|
@@ -3238,7 +3573,11 @@ const CURATED_SKILLS_BY_SOURCE = {
|
|
|
3238
3573
|
],
|
|
3239
3574
|
"msmps/opentui-skill": () => ["opentui"],
|
|
3240
3575
|
"haydenbleasel/ultracite": () => ["ultracite"],
|
|
3241
|
-
"https://www.evlog.dev": () => [
|
|
3576
|
+
"https://www.evlog.dev": (config) => [
|
|
3577
|
+
"review-logging-patterns",
|
|
3578
|
+
"build-audit-logs",
|
|
3579
|
+
...supportsEvlogLocalLogs(config) ? ["analyze-logs"] : []
|
|
3580
|
+
]
|
|
3242
3581
|
};
|
|
3243
3582
|
function getCuratedSkillNamesForSourceKey(sourceKey, config) {
|
|
3244
3583
|
return CURATED_SKILLS_BY_SOURCE[sourceKey](config);
|
|
@@ -3315,9 +3654,10 @@ async function setupSkills(config) {
|
|
|
3315
3654
|
if (configuredAgents !== void 0) return [...configuredAgents];
|
|
3316
3655
|
return navigableMultiselect({
|
|
3317
3656
|
message: "Select agents to install skills to",
|
|
3318
|
-
options:
|
|
3657
|
+
options: SKILLS_AGENT_PROMPT_OPTIONS,
|
|
3319
3658
|
required: false,
|
|
3320
|
-
initialValues: [...DEFAULT_AGENTS$1]
|
|
3659
|
+
initialValues: [...DEFAULT_AGENTS$1],
|
|
3660
|
+
maxItems: 10
|
|
3321
3661
|
});
|
|
3322
3662
|
}
|
|
3323
3663
|
});
|
|
@@ -3337,6 +3677,7 @@ async function setupSkills(config) {
|
|
|
3337
3677
|
installSpinner.start("Installing skills...");
|
|
3338
3678
|
const runner = getPackageRunnerPrefix(packageManager);
|
|
3339
3679
|
const globalFlags = scope === "global" ? ["-g"] : [];
|
|
3680
|
+
const agentTargets = expandSkillsAgentTargets(selectedAgents);
|
|
3340
3681
|
for (const [source, skills] of Object.entries(skillsBySource)) if ((await Result.tryPromise({
|
|
3341
3682
|
try: async () => {
|
|
3342
3683
|
const args = [
|
|
@@ -3348,7 +3689,7 @@ async function setupSkills(config) {
|
|
|
3348
3689
|
"--skill",
|
|
3349
3690
|
...skills,
|
|
3350
3691
|
"--agent",
|
|
3351
|
-
...
|
|
3692
|
+
...agentTargets,
|
|
3352
3693
|
"-y"
|
|
3353
3694
|
];
|
|
3354
3695
|
await $({
|
|
@@ -3660,7 +4001,7 @@ const HOOKS = {
|
|
|
3660
4001
|
claude: { label: "Claude Code" },
|
|
3661
4002
|
copilot: { label: "GitHub Copilot" }
|
|
3662
4003
|
};
|
|
3663
|
-
const ULTRACITE_VERSION = "7.9.
|
|
4004
|
+
const ULTRACITE_VERSION = "7.9.4";
|
|
3664
4005
|
const DEFAULT_LINTER = "biome";
|
|
3665
4006
|
const DEFAULT_EDITORS = ["vscode"];
|
|
3666
4007
|
const DEFAULT_AGENTS = ["universal"];
|
|
@@ -5387,9 +5728,7 @@ async function getProjectName(initialName) {
|
|
|
5387
5728
|
*/
|
|
5388
5729
|
function isTelemetryEnabled() {
|
|
5389
5730
|
const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
|
|
5390
|
-
const BTS_TELEMETRY = "1";
|
|
5391
5731
|
if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
|
|
5392
|
-
if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
|
|
5393
5732
|
return true;
|
|
5394
5733
|
}
|
|
5395
5734
|
//#endregion
|
|
@@ -5509,16 +5848,15 @@ async function handleDirectoryConflict(currentPathInput) {
|
|
|
5509
5848
|
}
|
|
5510
5849
|
}
|
|
5511
5850
|
}
|
|
5851
|
+
function resolveProjectDirectoryPath(finalPathInput) {
|
|
5852
|
+
const finalResolvedPath = finalPathInput === "." ? process.cwd() : path.resolve(process.cwd(), finalPathInput);
|
|
5853
|
+
return {
|
|
5854
|
+
finalResolvedPath,
|
|
5855
|
+
finalBaseName: path.basename(finalResolvedPath)
|
|
5856
|
+
};
|
|
5857
|
+
}
|
|
5512
5858
|
async function setupProjectDirectory(finalPathInput, shouldClearDirectory) {
|
|
5513
|
-
|
|
5514
|
-
let finalBaseName;
|
|
5515
|
-
if (finalPathInput === ".") {
|
|
5516
|
-
finalResolvedPath = process.cwd();
|
|
5517
|
-
finalBaseName = path.basename(finalResolvedPath);
|
|
5518
|
-
} else {
|
|
5519
|
-
finalResolvedPath = path.resolve(process.cwd(), finalPathInput);
|
|
5520
|
-
finalBaseName = path.basename(finalResolvedPath);
|
|
5521
|
-
}
|
|
5859
|
+
const { finalResolvedPath, finalBaseName } = resolveProjectDirectoryPath(finalPathInput);
|
|
5522
5860
|
const pathSafetyResult = await validateSafeProjectDirectoryPath(finalPathInput);
|
|
5523
5861
|
if (pathSafetyResult.isErr()) throw pathSafetyResult.error;
|
|
5524
5862
|
if (shouldClearDirectory) {
|
|
@@ -5767,7 +6105,7 @@ function validateArrayOptions(options) {
|
|
|
5767
6105
|
}
|
|
5768
6106
|
//#endregion
|
|
5769
6107
|
//#region src/validation.ts
|
|
5770
|
-
const
|
|
6108
|
+
const coreStackFlags = /* @__PURE__ */ new Set([
|
|
5771
6109
|
"database",
|
|
5772
6110
|
"orm",
|
|
5773
6111
|
"backend",
|
|
@@ -5785,7 +6123,7 @@ const CORE_STACK_FLAGS = new Set([
|
|
|
5785
6123
|
function validateYesFlagCombination(options, providedFlags) {
|
|
5786
6124
|
if (!options.yes) return Result.ok(void 0);
|
|
5787
6125
|
if (options.template && options.template !== "none") return Result.ok(void 0);
|
|
5788
|
-
const coreStackFlagsProvided = Array.from(providedFlags).filter((flag) =>
|
|
6126
|
+
const coreStackFlagsProvided = Array.from(providedFlags).filter((flag) => coreStackFlags.has(flag));
|
|
5789
6127
|
if (coreStackFlagsProvided.length > 0) return Result.err(new ValidationError({ message: `Cannot combine --yes with core stack configuration flags: ${coreStackFlagsProvided.map((f) => `--${f}`).join(", ")}. The --yes flag uses default configuration. Remove these flags or use --yes without them.` }));
|
|
5790
6128
|
return Result.ok(void 0);
|
|
5791
6129
|
}
|
|
@@ -5824,6 +6162,9 @@ function validateConfigCompatibility(config, providedFlags, options) {
|
|
|
5824
6162
|
if (options && providedFlags) return validateFullConfig(config, providedFlags, options);
|
|
5825
6163
|
else return validateConfigForProgrammaticUse(config);
|
|
5826
6164
|
}
|
|
6165
|
+
function validateResolvedConfigCompatibility(config) {
|
|
6166
|
+
return validateFullConfig(config, coreStackFlags, config);
|
|
6167
|
+
}
|
|
5827
6168
|
//#endregion
|
|
5828
6169
|
//#region src/utils/file-formatter.ts
|
|
5829
6170
|
const formatOptions = {
|
|
@@ -6017,7 +6358,7 @@ async function initMongoDBAtlas(serverDir) {
|
|
|
6017
6358
|
await $({
|
|
6018
6359
|
cwd: serverDir,
|
|
6019
6360
|
stdio: "inherit"
|
|
6020
|
-
})`atlas
|
|
6361
|
+
})`atlas setup`;
|
|
6021
6362
|
cliLog.success("MongoDB Atlas deployment ready");
|
|
6022
6363
|
},
|
|
6023
6364
|
catch: (e) => new DatabaseSetupError({
|
|
@@ -6066,7 +6407,7 @@ ${pc.green("MongoDB Atlas Manual Setup Instructions:")}
|
|
|
6066
6407
|
${pc.blue("https://www.mongodb.com/docs/atlas/cli/stable/install-atlas-cli/")}
|
|
6067
6408
|
|
|
6068
6409
|
2. Run the following command and follow the prompts:
|
|
6069
|
-
${pc.blue("atlas
|
|
6410
|
+
${pc.blue("atlas setup")}
|
|
6070
6411
|
|
|
6071
6412
|
3. Get your connection string from the Atlas dashboard:
|
|
6072
6413
|
Format: ${pc.dim("mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE_NAME")}
|
|
@@ -6167,10 +6508,6 @@ const NEON_REGIONS = [
|
|
|
6167
6508
|
label: "AWS Asia Pacific (Singapore)",
|
|
6168
6509
|
value: "aws-ap-southeast-1"
|
|
6169
6510
|
},
|
|
6170
|
-
{
|
|
6171
|
-
label: "AWS South America East 1 (São Paulo)",
|
|
6172
|
-
value: "aws-sa-east-1"
|
|
6173
|
-
},
|
|
6174
6511
|
{
|
|
6175
6512
|
label: "AWS Asia Pacific (Sydney)",
|
|
6176
6513
|
value: "aws-ap-southeast-2"
|
|
@@ -6180,13 +6517,12 @@ const NEON_REGIONS = [
|
|
|
6180
6517
|
value: "azure-eastus2"
|
|
6181
6518
|
}
|
|
6182
6519
|
];
|
|
6183
|
-
async function executeNeonCommand(
|
|
6520
|
+
async function executeNeonCommand(commandArgs, spinnerText) {
|
|
6184
6521
|
const s = createSpinner();
|
|
6185
|
-
const args = getPackageExecutionArgs(packageManager, commandArgsString);
|
|
6186
6522
|
if (spinnerText) s.start(spinnerText);
|
|
6187
6523
|
return Result.tryPromise({
|
|
6188
6524
|
try: async () => {
|
|
6189
|
-
const result = await $`${
|
|
6525
|
+
const result = await $`${commandArgs}`;
|
|
6190
6526
|
if (spinnerText) s.stop(pc.green(spinnerText.replace("...", "").replace("ing ", "ed ").trim()));
|
|
6191
6527
|
return result;
|
|
6192
6528
|
},
|
|
@@ -6200,8 +6536,22 @@ async function executeNeonCommand(packageManager, commandArgsString, spinnerText
|
|
|
6200
6536
|
}
|
|
6201
6537
|
});
|
|
6202
6538
|
}
|
|
6539
|
+
function getNeonProjectCreateArgs(packageManager, projectName, regionId) {
|
|
6540
|
+
return [
|
|
6541
|
+
...getPackageRunnerPrefix(packageManager),
|
|
6542
|
+
"neon@latest",
|
|
6543
|
+
"projects",
|
|
6544
|
+
"create",
|
|
6545
|
+
"--name",
|
|
6546
|
+
projectName,
|
|
6547
|
+
"--region-id",
|
|
6548
|
+
regionId,
|
|
6549
|
+
"--output",
|
|
6550
|
+
"json"
|
|
6551
|
+
];
|
|
6552
|
+
}
|
|
6203
6553
|
async function createNeonProject(projectName, regionId, packageManager) {
|
|
6204
|
-
const execResult = await executeNeonCommand(packageManager,
|
|
6554
|
+
const execResult = await executeNeonCommand(getNeonProjectCreateArgs(packageManager, projectName, regionId), `Creating Neon project "${projectName}"...`);
|
|
6205
6555
|
if (execResult.isErr()) return Result.err(execResult.error);
|
|
6206
6556
|
const parseResult = Result.try({
|
|
6207
6557
|
try: () => JSON.parse(execResult.value.stdout),
|
|
@@ -6245,7 +6595,7 @@ async function writeEnvFile$2(projectDir, backend, config) {
|
|
|
6245
6595
|
}
|
|
6246
6596
|
async function setupWithNeonDb(projectDir, packageManager, backend) {
|
|
6247
6597
|
const s = createSpinner();
|
|
6248
|
-
s.start("Creating Neon database using
|
|
6598
|
+
s.start("Creating Neon database using neon-new...");
|
|
6249
6599
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
6250
6600
|
const targetDir = path.join(projectDir, targetApp);
|
|
6251
6601
|
const ensureDirResult = await Result.tryPromise({
|
|
@@ -6260,17 +6610,17 @@ async function setupWithNeonDb(projectDir, packageManager, backend) {
|
|
|
6260
6610
|
s.stop(pc.red("Failed to create directory"));
|
|
6261
6611
|
return ensureDirResult;
|
|
6262
6612
|
}
|
|
6263
|
-
const packageArgs = getPackageExecutionArgs(packageManager, `
|
|
6613
|
+
const packageArgs = getPackageExecutionArgs(packageManager, `neon-new@latest --yes --ref "sbA3tIe"`);
|
|
6264
6614
|
return Result.tryPromise({
|
|
6265
6615
|
try: async () => {
|
|
6266
6616
|
await $({ cwd: targetDir })`${packageArgs}`;
|
|
6267
6617
|
s.stop(pc.green("Neon database created successfully!"));
|
|
6268
6618
|
},
|
|
6269
6619
|
catch: (e) => {
|
|
6270
|
-
s.stop(pc.red("Failed to create database with
|
|
6620
|
+
s.stop(pc.red("Failed to create database with neon-new"));
|
|
6271
6621
|
return new DatabaseSetupError({
|
|
6272
6622
|
provider: "neon",
|
|
6273
|
-
message: `Failed to create database with
|
|
6623
|
+
message: `Failed to create database with neon-new: ${e instanceof Error ? e.message : String(e)}`,
|
|
6274
6624
|
cause: e
|
|
6275
6625
|
});
|
|
6276
6626
|
}
|
|
@@ -6331,25 +6681,25 @@ async function setupNeonPostgres(config, cliInput) {
|
|
|
6331
6681
|
return Result.ok(void 0);
|
|
6332
6682
|
}
|
|
6333
6683
|
let setupMethod = cliInput?.dbSetupOptions?.neon?.method ?? config.dbSetupOptions?.neon?.method;
|
|
6334
|
-
if (!setupMethod) if (isSilent()) setupMethod = "
|
|
6684
|
+
if (!setupMethod) if (isSilent()) setupMethod = "neon-new";
|
|
6335
6685
|
else {
|
|
6336
6686
|
const promptedSetupMethod = await select({
|
|
6337
6687
|
message: "Choose your Neon setup method:",
|
|
6338
6688
|
options: [{
|
|
6339
|
-
label: "Quick setup with
|
|
6340
|
-
value: "
|
|
6689
|
+
label: "Quick setup with neon-new",
|
|
6690
|
+
value: "neon-new",
|
|
6341
6691
|
hint: "fastest, no auth required"
|
|
6342
6692
|
}, {
|
|
6343
|
-
label: "Custom setup with
|
|
6344
|
-
value: "
|
|
6693
|
+
label: "Custom setup with Neon CLI",
|
|
6694
|
+
value: "neon",
|
|
6345
6695
|
hint: "More control - choose project name and region"
|
|
6346
6696
|
}],
|
|
6347
|
-
initialValue: "
|
|
6697
|
+
initialValue: "neon-new"
|
|
6348
6698
|
});
|
|
6349
6699
|
if (isCancel(promptedSetupMethod)) return userCancelled("Operation cancelled");
|
|
6350
6700
|
setupMethod = promptedSetupMethod;
|
|
6351
6701
|
}
|
|
6352
|
-
if (setupMethod === "neondb") {
|
|
6702
|
+
if (setupMethod === "neon-new" || setupMethod === "neondb") {
|
|
6353
6703
|
const neonDbResult = await setupWithNeonDb(projectDir, packageManager, backend);
|
|
6354
6704
|
if (neonDbResult.isErr()) {
|
|
6355
6705
|
cliLog.error(pc.red(neonDbResult.error.message));
|
|
@@ -7269,7 +7619,7 @@ async function getDockerStatus(database) {
|
|
|
7269
7619
|
//#endregion
|
|
7270
7620
|
//#region src/helpers/core/post-installation.ts
|
|
7271
7621
|
function getDesktopStaticBuildNote(frontend) {
|
|
7272
|
-
const staticBuildFrontends = new Map([
|
|
7622
|
+
const staticBuildFrontends = /* @__PURE__ */ new Map([
|
|
7273
7623
|
["tanstack-start", "TanStack Start"],
|
|
7274
7624
|
["next", "Next.js"],
|
|
7275
7625
|
["nuxt", "Nuxt"],
|
|
@@ -7739,24 +8089,35 @@ function createEmptyResult(timeScaffolded, elapsedTimeMs, error) {
|
|
|
7739
8089
|
error
|
|
7740
8090
|
};
|
|
7741
8091
|
}
|
|
7742
|
-
async function
|
|
8092
|
+
async function executeCreateProjectHandler(input, options) {
|
|
7743
8093
|
const { silent = false } = options;
|
|
7744
8094
|
return runWithContextAsync({ silent }, async () => {
|
|
7745
8095
|
const startTime = Date.now();
|
|
7746
8096
|
const timeScaffolded = (/* @__PURE__ */ new Date()).toISOString();
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
if (isSilent()) return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
|
|
7753
|
-
return;
|
|
7754
|
-
}
|
|
7755
|
-
if (isSilent()) return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
|
|
7756
|
-
displayError(error);
|
|
7757
|
-
process.exit(1);
|
|
8097
|
+
return {
|
|
8098
|
+
result: await createProjectHandlerInternal(input, startTime, timeScaffolded),
|
|
8099
|
+
startTime,
|
|
8100
|
+
timeScaffolded
|
|
8101
|
+
};
|
|
7758
8102
|
});
|
|
7759
8103
|
}
|
|
8104
|
+
async function createProjectHandlerResult(input, options = {}) {
|
|
8105
|
+
return (await executeCreateProjectHandler(input, options)).result;
|
|
8106
|
+
}
|
|
8107
|
+
async function createProjectHandler(input, options = {}) {
|
|
8108
|
+
const { silent = false } = options;
|
|
8109
|
+
const { result, startTime, timeScaffolded } = await executeCreateProjectHandler(input, options);
|
|
8110
|
+
if (result.isOk()) return result.value;
|
|
8111
|
+
const error = result.error;
|
|
8112
|
+
const elapsedTimeMs = Date.now() - startTime;
|
|
8113
|
+
if (UserCancelledError.is(error)) {
|
|
8114
|
+
if (silent) return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
|
|
8115
|
+
return;
|
|
8116
|
+
}
|
|
8117
|
+
if (silent) return createEmptyResult(timeScaffolded, elapsedTimeMs, error.message);
|
|
8118
|
+
displayError(error);
|
|
8119
|
+
process.exit(1);
|
|
8120
|
+
}
|
|
7760
8121
|
async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
|
|
7761
8122
|
return Result.gen(async function* () {
|
|
7762
8123
|
if (!isSilent() && input.renderTitle !== false) renderTitle();
|
|
@@ -7789,25 +8150,7 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
|
|
|
7789
8150
|
shouldClearDirectory = conflictResult.shouldClearDirectory;
|
|
7790
8151
|
yield* validateResolvedProjectPathInput(finalPathInput);
|
|
7791
8152
|
yield* Result.await(validateSafeProjectDirectoryPath(finalPathInput));
|
|
7792
|
-
|
|
7793
|
-
let finalBaseName;
|
|
7794
|
-
if (input.dryRun) {
|
|
7795
|
-
finalResolvedPath = finalPathInput === "." ? process.cwd() : path.resolve(process.cwd(), finalPathInput);
|
|
7796
|
-
finalBaseName = path.basename(finalResolvedPath);
|
|
7797
|
-
} else {
|
|
7798
|
-
const setupResult = yield* Result.await(Result.tryPromise({
|
|
7799
|
-
try: async () => setupProjectDirectory(finalPathInput, shouldClearDirectory),
|
|
7800
|
-
catch: (e) => {
|
|
7801
|
-
if (e instanceof UserCancelledError) return e;
|
|
7802
|
-
return new CLIError({
|
|
7803
|
-
message: e instanceof Error ? e.message : String(e),
|
|
7804
|
-
cause: e
|
|
7805
|
-
});
|
|
7806
|
-
}
|
|
7807
|
-
}));
|
|
7808
|
-
finalResolvedPath = setupResult.finalResolvedPath;
|
|
7809
|
-
finalBaseName = setupResult.finalBaseName;
|
|
7810
|
-
}
|
|
8153
|
+
const { finalResolvedPath, finalBaseName } = resolveProjectDirectoryPath(finalPathInput);
|
|
7811
8154
|
const originalInput = {
|
|
7812
8155
|
...input,
|
|
7813
8156
|
projectDirectory: input.projectName
|
|
@@ -7846,10 +8189,10 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
|
|
|
7846
8189
|
relativePath: finalPathInput
|
|
7847
8190
|
};
|
|
7848
8191
|
const validationResult = validateConfigCompatibility(config, providedFlags, cliInput);
|
|
7849
|
-
if (validationResult.isErr())
|
|
8192
|
+
if (validationResult.isErr()) yield* new CLIError({
|
|
7850
8193
|
message: validationResult.error.message,
|
|
7851
8194
|
cause: validationResult.error
|
|
7852
|
-
})
|
|
8195
|
+
});
|
|
7853
8196
|
if (!isSilent()) log.info(pc.dim("Quick setup selected — using defaults and provided flags."));
|
|
7854
8197
|
} else {
|
|
7855
8198
|
const flagConfigResult = processAndValidateFlags(cliInput, providedFlags, finalBaseName);
|
|
@@ -7881,9 +8224,22 @@ async function createProjectHandlerInternal(input, startTime, timeScaffolded) {
|
|
|
7881
8224
|
dbSetupOptions: effectiveDbSetupOptions
|
|
7882
8225
|
};
|
|
7883
8226
|
if (!input.yolo) {
|
|
7884
|
-
const
|
|
7885
|
-
if (
|
|
8227
|
+
const resolvedConfigValidationResult = validateResolvedConfigCompatibility(config);
|
|
8228
|
+
if (resolvedConfigValidationResult.isErr()) yield* new CLIError({
|
|
8229
|
+
message: resolvedConfigValidationResult.error.message,
|
|
8230
|
+
cause: resolvedConfigValidationResult.error
|
|
8231
|
+
});
|
|
7886
8232
|
}
|
|
8233
|
+
if (!input.dryRun) yield* Result.await(Result.tryPromise({
|
|
8234
|
+
try: async () => setupProjectDirectory(finalPathInput, shouldClearDirectory),
|
|
8235
|
+
catch: (e) => {
|
|
8236
|
+
if (e instanceof UserCancelledError) return e;
|
|
8237
|
+
return new CLIError({
|
|
8238
|
+
message: e instanceof Error ? e.message : String(e),
|
|
8239
|
+
cause: e
|
|
8240
|
+
});
|
|
8241
|
+
}
|
|
8242
|
+
}));
|
|
7887
8243
|
if (!isSilent()) {
|
|
7888
8244
|
log.info(pc.magenta(pc.bold("Stack ready")));
|
|
7889
8245
|
log.message(displayConfig(config));
|
|
@@ -8100,7 +8456,7 @@ const router = t.router({
|
|
|
8100
8456
|
}),
|
|
8101
8457
|
createJson: t.procedure.meta({
|
|
8102
8458
|
description: "Create a project from a raw JSON payload (agent-friendly)",
|
|
8103
|
-
jsonInput:
|
|
8459
|
+
jsonInput: "always"
|
|
8104
8460
|
}).input(types_exports.CreateInputSchema).mutation(async ({ input }) => {
|
|
8105
8461
|
const result = await createProjectHandler(input, { silent: true });
|
|
8106
8462
|
if (!result) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
@@ -8122,7 +8478,7 @@ const router = t.router({
|
|
|
8122
8478
|
}),
|
|
8123
8479
|
addJson: t.procedure.meta({
|
|
8124
8480
|
description: "Add addons from a raw JSON payload (agent-friendly)",
|
|
8125
|
-
jsonInput:
|
|
8481
|
+
jsonInput: "always"
|
|
8126
8482
|
}).input(types_exports.AddInputSchema).mutation(async ({ input }) => {
|
|
8127
8483
|
const result = await addHandler(input, { silent: true });
|
|
8128
8484
|
if (!result) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
@@ -8194,15 +8550,15 @@ async function create(projectName, options) {
|
|
|
8194
8550
|
};
|
|
8195
8551
|
return Result.tryPromise({
|
|
8196
8552
|
try: async () => {
|
|
8197
|
-
const result = await
|
|
8198
|
-
if (
|
|
8199
|
-
|
|
8200
|
-
return result;
|
|
8553
|
+
const result = await createProjectHandlerResult(input, { silent: true });
|
|
8554
|
+
if (result.isErr()) throw result.error;
|
|
8555
|
+
return result.value;
|
|
8201
8556
|
},
|
|
8202
8557
|
catch: (e) => {
|
|
8203
|
-
if (e
|
|
8204
|
-
if (e
|
|
8205
|
-
if (e
|
|
8558
|
+
if (UserCancelledError.is(e)) return e;
|
|
8559
|
+
if (CLIError.is(e)) return e;
|
|
8560
|
+
if (DirectoryConflictError.is(e)) return e;
|
|
8561
|
+
if (ProjectCreationError.is(e)) return e;
|
|
8206
8562
|
return new CLIError({
|
|
8207
8563
|
message: e instanceof Error ? e.message : String(e),
|
|
8208
8564
|
cause: e
|
|
@@ -8273,7 +8629,7 @@ async function createVirtual(options) {
|
|
|
8273
8629
|
webDeploy: virtualOptions.webDeploy || "none",
|
|
8274
8630
|
serverDeploy: virtualOptions.serverDeploy || "none"
|
|
8275
8631
|
};
|
|
8276
|
-
const validationResult = validateConfigCompatibility(config, new Set([
|
|
8632
|
+
const validationResult = validateConfigCompatibility(config, /* @__PURE__ */ new Set([
|
|
8277
8633
|
"database",
|
|
8278
8634
|
"orm",
|
|
8279
8635
|
"backend",
|