gencow 0.1.119 → 0.1.120
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/bin/gencow.mjs +87 -25
- package/dashboard/assets/{index-Bur5ZNpv.js → index-Dv-kFCfN.js} +17 -17
- package/dashboard/assets/index-treFoOsZ.css +1 -0
- package/dashboard/index.html +2 -2
- package/lib/__tests__/readme-codegen.test.ts +2 -1
- package/lib/readme-codegen.mjs +24 -14
- package/package.json +1 -1
- package/dashboard/assets/index-BYHvURCl.css +0 -1
package/bin/gencow.mjs
CHANGED
|
@@ -303,7 +303,8 @@ function _ensureEsbuildConsistency() {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
/**
|
|
306
|
-
* 모노레포 루트의 .
|
|
306
|
+
* 모노레포 루트의 .pnpmrc에 esbuild hoisting 차단 규칙을 추가.
|
|
307
|
+
* (.npmrc가 아닌 .pnpmrc — hoist-pattern은 pnpm 전용이므로 npm 경고 방지)
|
|
307
308
|
* 이미 존재하면 스킵.
|
|
308
309
|
*/
|
|
309
310
|
function _patchNpmrcForEsbuild(cwd) {
|
|
@@ -312,8 +313,9 @@ function _patchNpmrcForEsbuild(cwd) {
|
|
|
312
313
|
let dir = cwd;
|
|
313
314
|
for (let i = 0; i < 10; i++) {
|
|
314
315
|
if (existsSync(resolve(dir, "pnpm-workspace.yaml"))) {
|
|
315
|
-
|
|
316
|
-
const
|
|
316
|
+
// .pnpmrc 대상 (pnpm 전용 설정 → npm "Unknown project config" 경고 방지)
|
|
317
|
+
const pnpmrcPath = resolve(dir, ".pnpmrc");
|
|
318
|
+
const content = existsSync(pnpmrcPath) ? readFileSync(pnpmrcPath, "utf8") : "";
|
|
317
319
|
if (!content.includes("hoist-pattern[]=!@esbuild/*")) {
|
|
318
320
|
const patch = [
|
|
319
321
|
"",
|
|
@@ -323,8 +325,8 @@ function _patchNpmrcForEsbuild(cwd) {
|
|
|
323
325
|
"hoist-pattern[]=!esbuild",
|
|
324
326
|
"",
|
|
325
327
|
].join("\n");
|
|
326
|
-
appendFileSync(
|
|
327
|
-
info(".
|
|
328
|
+
appendFileSync(pnpmrcPath, patch);
|
|
329
|
+
info(".pnpmrc에 esbuild hoisting 차단 규칙을 추가했습니다.");
|
|
328
330
|
info("다음 pnpm install 시 영구 적용됩니다.");
|
|
329
331
|
}
|
|
330
332
|
return;
|
|
@@ -333,7 +335,7 @@ function _patchNpmrcForEsbuild(cwd) {
|
|
|
333
335
|
if (parent === dir) break;
|
|
334
336
|
dir = parent;
|
|
335
337
|
}
|
|
336
|
-
} catch { /* .
|
|
338
|
+
} catch { /* .pnpmrc 수정 실패 — 무시 (즉시 우회로 이번 실행은 문제 없음) */ }
|
|
337
339
|
}
|
|
338
340
|
|
|
339
341
|
function findServerRoot() {
|
|
@@ -1197,7 +1199,7 @@ ${hasPrompt ? `
|
|
|
1197
1199
|
|
|
1198
1200
|
if (!appId) {
|
|
1199
1201
|
error("Cloud app not found — gencow.json이 없거나 appId가 설정되지 않았습니다.");
|
|
1200
|
-
info(`${DIM}먼저 gencow
|
|
1202
|
+
info(`${DIM}먼저 gencow dev 를 실행하세요.${RESET}`);
|
|
1201
1203
|
info(`${DIM}로컬 서버에 seed하려면: gencow db:seed --local${RESET}`);
|
|
1202
1204
|
log("");
|
|
1203
1205
|
return;
|
|
@@ -1218,7 +1220,7 @@ ${hasPrompt ? `
|
|
|
1218
1220
|
if (!statusRes || !statusRes.ok) {
|
|
1219
1221
|
error(`Cloud app "${appId}" is not running`);
|
|
1220
1222
|
info(`${DIM}Dashboard → Apps → ${appId} → Resume 으로 앱을 시작하세요.${RESET}`);
|
|
1221
|
-
info(`${DIM}또는: gencow
|
|
1223
|
+
info(`${DIM}또는: gencow dev 로 앱 생성 후 시도하세요.${RESET}`);
|
|
1222
1224
|
log("");
|
|
1223
1225
|
return;
|
|
1224
1226
|
}
|
|
@@ -1236,7 +1238,7 @@ ${hasPrompt ? `
|
|
|
1236
1238
|
log(` ${DIM}export default async function seed(ctx) {${RESET}`);
|
|
1237
1239
|
log(` ${DIM} await ctx.db.insert(tasks).values([...]);${RESET}`);
|
|
1238
1240
|
log(` ${DIM}};${RESET}\n`);
|
|
1239
|
-
info(`${DIM}After creating seed.ts: gencow
|
|
1241
|
+
info(`${DIM}After creating seed.ts: gencow dev 실행 후 gencow db:seed${RESET}`);
|
|
1240
1242
|
} else if (!res.ok) {
|
|
1241
1243
|
error(`Cloud seed failed: ${data.error || "Unknown error"}`);
|
|
1242
1244
|
} else {
|
|
@@ -1555,7 +1557,7 @@ ${hasPrompt ? `
|
|
|
1555
1557
|
|
|
1556
1558
|
if (!appId) {
|
|
1557
1559
|
error("Cloud app not found — gencow.json이 없거나 appId가 설정되지 않았습니다.");
|
|
1558
|
-
info(`${DIM}먼저 gencow
|
|
1560
|
+
info(`${DIM}먼저 gencow dev 를 실행하세요.${RESET}`);
|
|
1559
1561
|
info(`${DIM}로컬 DB에 push하려면: gencow db:push --local${RESET}`);
|
|
1560
1562
|
log("");
|
|
1561
1563
|
return;
|
|
@@ -1564,7 +1566,7 @@ ${hasPrompt ? `
|
|
|
1564
1566
|
// ── Cloud 모드: Platform API를 통해 Cloud DB에 schema push ──
|
|
1565
1567
|
const creds = requireCreds();
|
|
1566
1568
|
log(`\n${BOLD}${CYAN}Gencow DB Push${RESET} ${DIM}(cloud: ${appId})${RESET}\n`);
|
|
1567
|
-
warn("명령어 실행 전 먼저 gencow
|
|
1569
|
+
warn("명령어 실행 전 먼저 gencow dev 를 통해 최신 코드가 배포되어 있어야 합니다.");
|
|
1568
1570
|
log("");
|
|
1569
1571
|
info("Pushing schema.ts → cloud database...");
|
|
1570
1572
|
|
|
@@ -1805,10 +1807,11 @@ ${BOLD}BaaS commands (login required):${RESET}
|
|
|
1805
1807
|
${GREEN}login${RESET} Login to Gencow Platform ${DIM}(browser → token)${RESET}
|
|
1806
1808
|
${GREEN}logout${RESET} Clear credentials
|
|
1807
1809
|
${GREEN}whoami${RESET} Show current user info
|
|
1808
|
-
${GREEN}
|
|
1809
|
-
${DIM}--
|
|
1810
|
-
${DIM}--
|
|
1811
|
-
|
|
1810
|
+
${GREEN}static [dir]${RESET} Deploy static files to dev ${DIM}(dist/, out/, build/)${RESET}
|
|
1811
|
+
${DIM}--no-backend Skip backend auto-deploy${RESET}
|
|
1812
|
+
${DIM}--force, -f Skip dependency audit${RESET}
|
|
1813
|
+
${GREEN}deploy${RESET} Deploy to production ${DIM}(Pro+ only)${RESET}
|
|
1814
|
+
${DIM}--static [dir] Deploy static files to production${RESET}
|
|
1812
1815
|
${DIM}--rollback Rollback to previous deployment${RESET}
|
|
1813
1816
|
${DIM}--force, -f Skip dependency audit${RESET}
|
|
1814
1817
|
${GREEN}env list${RESET} List cloud env vars ${DIM}(--prod for production)${RESET}
|
|
@@ -1985,14 +1988,55 @@ ${BOLD}Examples:${RESET}
|
|
|
1985
1988
|
}
|
|
1986
1989
|
},
|
|
1987
1990
|
|
|
1988
|
-
// ──
|
|
1991
|
+
// ── static — dev 정적 파일 배포 (독립 명령어) ─────────
|
|
1992
|
+
async static(...staticArgs) {
|
|
1993
|
+
const creds = requireCreds();
|
|
1994
|
+
|
|
1995
|
+
let staticDir = null;
|
|
1996
|
+
let forceDeploy = false;
|
|
1997
|
+
let noBackend = false;
|
|
1998
|
+
let appId = null;
|
|
1999
|
+
|
|
2000
|
+
for (let i = 0; i < staticArgs.length; i++) {
|
|
2001
|
+
const a = staticArgs[i];
|
|
2002
|
+
if (a === "--force" || a === "-f") forceDeploy = true;
|
|
2003
|
+
else if (a === "--no-backend") noBackend = true;
|
|
2004
|
+
else if (a === "--app" || a === "-a") appId = staticArgs[++i];
|
|
2005
|
+
else if (!a.startsWith("-")) {
|
|
2006
|
+
staticDir = a;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
// gencow.json에서 appId 로드
|
|
2011
|
+
const gencowJsonPath = resolve(process.cwd(), "gencow.json");
|
|
2012
|
+
if (!appId && existsSync(gencowJsonPath)) {
|
|
2013
|
+
const gencowJson = JSON.parse(readFileSync(gencowJsonPath, "utf8"));
|
|
2014
|
+
appId = gencowJson.appId || gencowJson.appName;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
// displayName
|
|
2018
|
+
let displayName = null;
|
|
2019
|
+
const configPath = resolve(process.cwd(), "gencow.config.ts");
|
|
2020
|
+
if (existsSync(configPath)) {
|
|
2021
|
+
const content = readFileSync(configPath, "utf8");
|
|
2022
|
+
const match = content.match(/name:\s*["']([^"']+)["']/);
|
|
2023
|
+
if (match) displayName = match[1];
|
|
2024
|
+
}
|
|
2025
|
+
if (!displayName) displayName = basename(process.cwd());
|
|
2026
|
+
|
|
2027
|
+
return await this._deployStatic(creds, appId, displayName, staticDir, gencowJsonPath, {
|
|
2028
|
+
forceDeploy, noBackend, envTarget: "dev",
|
|
2029
|
+
});
|
|
2030
|
+
},
|
|
2031
|
+
|
|
2032
|
+
// ── deploy — 프로덕션 배포 (Pro+ only) ───────────────
|
|
1989
2033
|
async deploy(...deployArgs) {
|
|
1990
2034
|
const creds = requireCreds();
|
|
1991
2035
|
|
|
1992
2036
|
// gencow.json에서 앱 ID 확인 (자동 생성된 유니크 ID)
|
|
1993
2037
|
let appId = null;
|
|
1994
2038
|
let displayName = null;
|
|
1995
|
-
let envTarget = "
|
|
2039
|
+
let envTarget = "prod"; // v0.1.120: deploy = prod 기본값
|
|
1996
2040
|
let staticDir = null; // --static 옵션
|
|
1997
2041
|
let isStatic = false;
|
|
1998
2042
|
let forceDeploy = false; // --force: skip dependency audit
|
|
@@ -2061,7 +2105,12 @@ ${BOLD}Examples:${RESET}
|
|
|
2061
2105
|
|
|
2062
2106
|
for (let i = 0; i < deployArgs.length; i++) {
|
|
2063
2107
|
const a = deployArgs[i];
|
|
2064
|
-
if (a === "--prod")
|
|
2108
|
+
if (a === "--prod") {
|
|
2109
|
+
// deprecated: deploy는 이미 prod 기본값
|
|
2110
|
+
warn(`${YELLOW}--prod 플래그는 더 이상 필요하지 않습니다.${RESET}`);
|
|
2111
|
+
info(`gencow deploy는 기본적으로 프로덕션에 배포합니다.`);
|
|
2112
|
+
envTarget = "prod";
|
|
2113
|
+
}
|
|
2065
2114
|
else if (a === "--force" || a === "-f") forceDeploy = true;
|
|
2066
2115
|
else if (a === "--no-backend") noBackend = true;
|
|
2067
2116
|
else if (a === "--rollback") isRollback = true;
|
|
@@ -2080,13 +2129,16 @@ ${BOLD}Examples:${RESET}
|
|
|
2080
2129
|
error(`알 수 없는 deploy 인자: "${a}"`);
|
|
2081
2130
|
log("");
|
|
2082
2131
|
info(`사용법: gencow deploy [옵션]`);
|
|
2083
|
-
info(` gencow deploy
|
|
2084
|
-
info(` gencow deploy --static 정적
|
|
2132
|
+
info(` gencow deploy 프로덕션 배포 (Pro+)`);
|
|
2133
|
+
info(` gencow deploy --static 프로덕션 정적 배포 (Pro+)`);
|
|
2085
2134
|
info(` gencow deploy --rollback 이전 버전으로 롤백`);
|
|
2086
|
-
info(` gencow deploy --prod 프로덕션 배포`);
|
|
2087
2135
|
info(` gencow deploy logs 서버 로그 조회`);
|
|
2088
2136
|
info(` gencow deploy status 앱 상태 확인`);
|
|
2089
2137
|
info(` gencow deploy --force 의존성 감사 스킵`);
|
|
2138
|
+
log("");
|
|
2139
|
+
info(`💡 개발 환경 배포:`);
|
|
2140
|
+
info(` gencow dev 백엔드 실시간 배포`);
|
|
2141
|
+
info(` gencow static [dir] 정적 파일 배포`);
|
|
2090
2142
|
process.exit(1);
|
|
2091
2143
|
}
|
|
2092
2144
|
}
|
|
@@ -2199,8 +2251,18 @@ ${BOLD}Examples:${RESET}
|
|
|
2199
2251
|
if (!createProdRes.ok) {
|
|
2200
2252
|
const errData = await createProdRes.json().catch(() => ({}));
|
|
2201
2253
|
if (createProdRes.status === 403) {
|
|
2202
|
-
|
|
2203
|
-
|
|
2254
|
+
log("");
|
|
2255
|
+
log(` ${RED}⛔ Production Deploy — Pro 플랜 이상 필요${RESET}`);
|
|
2256
|
+
log("");
|
|
2257
|
+
log(` ${DIM}gencow deploy는 프로덕션 환경에 배포하는 명령어입니다.${RESET}`);
|
|
2258
|
+
log("");
|
|
2259
|
+
log(` ${BOLD}💡 개발 환경 배포:${RESET}`);
|
|
2260
|
+
log(` ${GREEN}gencow dev${RESET} ${DIM}← 백엔드 실시간 배포 + 라이브 로그${RESET}`);
|
|
2261
|
+
log(` ${GREEN}gencow static dist/${RESET} ${DIM}← 정적 파일(dist/) 배포${RESET}`);
|
|
2262
|
+
log("");
|
|
2263
|
+
log(` ${BOLD}🚀 프로덕션 배포 잠금 해제:${RESET}`);
|
|
2264
|
+
log(` ${GREEN}gencow upgrade${RESET} ${DIM}← Pro 플랜으로 업그레이드${RESET}`);
|
|
2265
|
+
log("");
|
|
2204
2266
|
} else {
|
|
2205
2267
|
error(`Prod 앱 생성 실패: ${errData.error || createProdRes.statusText}`);
|
|
2206
2268
|
}
|
|
@@ -2635,7 +2697,7 @@ ${BOLD}Examples:${RESET}
|
|
|
2635
2697
|
if (!targetDir || !existsSync(resolve(process.cwd(), targetDir))) {
|
|
2636
2698
|
error(`정적 파일 폴더를 찾을 수 없습니다.`);
|
|
2637
2699
|
info(`자동 감지 순서: ${AUTO_DETECT.join(", ")}`);
|
|
2638
|
-
info(`수동 지정: gencow
|
|
2700
|
+
info(`수동 지정: gencow static <dir>`);
|
|
2639
2701
|
process.exit(1);
|
|
2640
2702
|
}
|
|
2641
2703
|
|
|
@@ -3069,7 +3131,7 @@ ${BOLD}Examples:${RESET}
|
|
|
3069
3131
|
|
|
3070
3132
|
// --prod인데 prod 앱이 없는 경우
|
|
3071
3133
|
if (envTarget === "prod" && appId && !appId.endsWith("-prod")) {
|
|
3072
|
-
error("Prod 앱이 아직 없습니다. gencow deploy
|
|
3134
|
+
error("Prod 앱이 아직 없습니다. gencow deploy를 먼저 실행하세요.");
|
|
3073
3135
|
return;
|
|
3074
3136
|
}
|
|
3075
3137
|
|