gencow 0.1.122 → 0.1.123

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 CHANGED
@@ -1049,88 +1049,9 @@ ${hasPrompt ? `
1049
1049
  },
1050
1050
 
1051
1051
  // ── db:reset ─────────────────────────────────────────
1052
- // TRUNCATE all user tables + seed.ts 실행.
1053
- // 로컬 전용: Cloud DB reset 위험하므로 CLI에서 미지원 (Dashboard에서만 가능)
1054
- // 사용: gencow db:reset --local
1055
- async "db:reset"(...args) {
1056
- const config = loadConfig();
1057
- const cwd = process.cwd();
1058
- const isLocal = args.includes("--local");
1059
-
1060
- if (!isLocal) {
1061
- // Cloud reset은 미지원 — 안내 메시지
1062
- error("db:reset requires --local flag.");
1063
- info(`${DIM}Cloud DB reset is only available via Dashboard (data protection).${RESET}`);
1064
- info(`${DIM}To reset local DB: gencow db:reset --local${RESET}`);
1065
- log("");
1066
- return;
1067
- }
1068
-
1069
- const port = process.env.PORT || config.port || 5456;
1070
-
1071
- log(`\n${BOLD}${CYAN}Gencow DB Reset${RESET}\n`);
1072
-
1073
- // 서버가 실행 중인지 확인
1074
- let serverAlive = false;
1075
- try {
1076
- const res = await fetch(`http://localhost:${port}/_admin/status`, { signal: AbortSignal.timeout(2000) });
1077
- serverAlive = res.ok;
1078
- } catch { /* 서버 꺼져있음 */ }
1079
-
1080
- if (serverAlive) {
1081
- // ── 서버 실행 중: API 기반 TRUNCATE + seed ──
1082
- info(`Server detected on :${port} — using API reset (TRUNCATE + seed)`);
1083
- log("");
1084
-
1085
- try {
1086
- const res = await fetch(`http://localhost:${port}/_admin/reset`, {
1087
- method: "POST",
1088
- headers: { "Content-Type": "application/json" },
1089
- body: JSON.stringify({ confirm: "delete all data" }),
1090
- });
1091
- const data = await res.json();
1092
-
1093
- if (!res.ok) {
1094
- error(`Reset failed: ${data.error || "Unknown error"}`);
1095
- log("");
1096
- return;
1097
- }
1098
-
1099
- success(`TRUNCATE done: ${data.truncated?.length || 0} tables`);
1100
- if (data.truncated?.length > 0) {
1101
- info(` ${DIM}${data.truncated.join(", ")}${RESET}`);
1102
- }
1103
- if (data.seeded) {
1104
- success(`Seed completed ✓`);
1105
- } else {
1106
- info(`${DIM}No seed.ts found — skipping${RESET}`);
1107
- }
1108
- } catch (e) {
1109
- error(`Server connection failed: ${e.message}`);
1110
- }
1111
- } else {
1112
- // ── 서버 꺼짐: 기존 PGlite 파일 삭제 ──
1113
- const dbPath = resolve(cwd, config.db.url);
1114
- if (existsSync(dbPath)) {
1115
- // 1. Backup first
1116
- const backupDir = resolve(cwd, ".gencow", "backups");
1117
- const ts = new Date().toISOString().replace(/[:.]/g, "-");
1118
- const backupPath = resolve(backupDir, ts);
1119
- mkdirSync(backupPath, { recursive: true });
1120
- cpSync(dbPath, backupPath, { recursive: true });
1121
- success(`Backup created: .gencow/backups/${ts}`);
1122
-
1123
- // 2. Cleanup old backups (keep last 3)
1124
- cleanupOldBackups(backupDir, 3);
1125
-
1126
- // 3. Delete DB
1127
- rmSync(dbPath, { recursive: true, force: true });
1128
- success("DB deleted — restart with gencow dev to create a new one");
1129
- } else {
1130
- info("DB does not exist yet. Run gencow dev to get started.");
1131
- }
1132
- }
1133
- log("");
1052
+ async "db:reset"() {
1053
+ info(`db:reset is ${BOLD}coming soon${RESET}.`);
1054
+ info(`${DIM}Use Gencow Dashboard for cloud DB management.${RESET}\n`);
1134
1055
  },
1135
1056
 
1136
1057
  // ── db:seed ──────────────────────────────────────────
@@ -1141,47 +1062,8 @@ ${hasPrompt ? `
1141
1062
  const isLocal = args.includes("--local");
1142
1063
 
1143
1064
  if (isLocal) {
1144
- // ── 로컬 모드: localhost 서버에 seed ──
1145
- const port = process.env.PORT || config.port || 5456;
1146
-
1147
- log(`\n${BOLD}${CYAN}Gencow DB Seed${RESET} ${DIM}(local)${RESET}\n`);
1148
-
1149
- // 서버가 실행 중인지 확인
1150
- try {
1151
- const statusRes = await fetch(`http://localhost:${port}/_admin/status`, { signal: AbortSignal.timeout(2000) });
1152
- if (!statusRes.ok) throw new Error("Server not ready");
1153
- } catch {
1154
- error(`Server not running on :${port}`);
1155
- info(`${DIM}Start server first: gencow dev --local${RESET}`);
1156
- log("");
1157
- return;
1158
- }
1159
-
1160
- try {
1161
- const res = await fetch(`http://localhost:${port}/_admin/seed`, {
1162
- method: "POST",
1163
- headers: { "Content-Type": "application/json" },
1164
- });
1165
- const data = await res.json();
1166
-
1167
- if (res.status === 404) {
1168
- warn("gencow/seed.ts not found");
1169
- info(`\n ${DIM}Create gencow/seed.ts:${RESET}\n`);
1170
- log(` ${DIM}import { tasks } from "./schema";${RESET}`);
1171
- log(` ${DIM}export default async function seed(ctx) {${RESET}`);
1172
- log(` ${DIM} await ctx.db.insert(tasks).values([${RESET}`);
1173
- log(` ${DIM} { title: "Hello World" },${RESET}`);
1174
- log(` ${DIM} ]);${RESET}`);
1175
- log(` ${DIM}};${RESET}`);
1176
- } else if (!res.ok) {
1177
- error(`Seed failed: ${data.error || "Unknown error"}`);
1178
- } else {
1179
- success("Seed completed ✓");
1180
- }
1181
- } catch (e) {
1182
- error(`Server connection failed: ${e.message}`);
1183
- }
1184
- log("");
1065
+ info(`Local db:seed is ${BOLD}coming soon${RESET}.`);
1066
+ info(`${DIM}Use cloud mode (default): gencow db:seed${RESET}\n`);
1185
1067
  return;
1186
1068
  }
1187
1069
 
@@ -1210,7 +1092,6 @@ ${hasPrompt ? `
1210
1092
  if (!appId) {
1211
1093
  error("Cloud app not found. Make sure gencow.json exists with an appId.");
1212
1094
  info(`${DIM}Run 'gencow dev' first to create your app.${RESET}`);
1213
- info(`${DIM}To seed local DB: gencow db:seed --local${RESET}`);
1214
1095
  log("");
1215
1096
  return;
1216
1097
  }
@@ -1317,9 +1198,12 @@ ${hasPrompt ? `
1317
1198
  if (devArgs.includes("--verbose")) {
1318
1199
  process.env.GENCOW_VERBOSE = "true";
1319
1200
  }
1320
- // --local 플래그: 로컬 PGlite 모드
1201
+ // --local 플래그: coming soon
1321
1202
  if (devArgs.includes("--local")) {
1322
- return commands["dev:local"](...devArgs);
1203
+ log(`\n${BOLD}${CYAN}Gencow Dev${RESET} ${DIM}(local)${RESET}\n`);
1204
+ info(`Local development mode is ${BOLD}coming soon${RESET}.`);
1205
+ info(`${DIM}Use cloud mode (default): gencow dev${RESET}\n`);
1206
+ return;
1323
1207
  }
1324
1208
  // --cloud 하위 호환 (이미 기본이므로 그대로 진행)
1325
1209
  // 기본 = 클라우드 모드
@@ -1541,18 +1425,8 @@ ${hasPrompt ? `
1541
1425
  const isLocal = args.includes("--local");
1542
1426
 
1543
1427
  if (isLocal) {
1544
- // ── 로컬 모드: 기존 동작 유지 ──
1545
- let hasDb = !!process.env.DATABASE_URL;
1546
- if (!hasDb) {
1547
- const envPath = resolve(process.cwd(), ".env");
1548
- if (existsSync(envPath)) hasDb = readFileSync(envPath, "utf8").includes("DATABASE_URL=");
1549
- }
1550
- const targetDb = hasDb ? "local PG" : "local fallback: PGlite";
1551
- log(`\n${BOLD}${CYAN}Gencow DB Push${RESET} ${DIM}(${targetDb})${RESET}\n`);
1552
- info("Pushing schema.ts → database (no migration files)...");
1553
- runInServer("pnpm db:push --force", buildEnv(config));
1554
- success("Schema pushed!");
1555
- log(` ${DIM}Tables are in sync with schema.ts${RESET}\n`);
1428
+ info(`Local db:push is ${BOLD}coming soon${RESET}.`);
1429
+ info(`${DIM}Use cloud mode (default): gencow db:push${RESET}\n`);
1556
1430
  return;
1557
1431
  }
1558
1432
 
@@ -1634,7 +1508,7 @@ ${hasPrompt ? `
1634
1508
  } catch (e) {
1635
1509
  const msg = e.stderr?.toString() || e.message || "";
1636
1510
  if (msg.includes("No schema changes") || msg.includes("nothing to migrate") || msg.includes("No changes detected")) {
1637
- log(`${DIM} No schema changesusing existing migrations${RESET}`);
1511
+ log(`${DIM} Migrations up-to-dateno new schema changes detected${RESET}`);
1638
1512
  } else {
1639
1513
  warn(`Migration generation failed: ${msg.split("\n")[0]}`);
1640
1514
  info("Will attempt schema push via server.");
@@ -1715,21 +1589,14 @@ ${hasPrompt ? `
1715
1589
 
1716
1590
  // ── db:studio ────────────────────────────────────────
1717
1591
  async "db:studio"() {
1718
- const config = loadConfig();
1719
- log(`\n${BOLD}${CYAN}Gencow DB Studio${RESET}\n`);
1720
- info("Opening Drizzle Studio...");
1721
- runInServer("pnpm db:studio", buildEnv(config));
1592
+ info(`Drizzle Studio is ${BOLD}coming soon${RESET}.`);
1593
+ info(`${DIM}Use Gencow Dashboard at https://gencow.app instead.${RESET}\n`);
1722
1594
  },
1723
1595
 
1724
1596
  // ── dashboard ────────────────────────────────────────
1725
1597
  async dashboard() {
1726
- const config = loadConfig();
1727
- const port = process.env.PORT || config.port;
1728
- const url = `http://localhost:${port}/_admin`;
1729
- log(`\n${BOLD}${CYAN}Gencow Dashboard${RESET}\n`);
1730
- info(`Opening ${url}`);
1731
- const { default: open } = await import("open");
1732
- await open(url);
1598
+ info(`Local dashboard is ${BOLD}coming soon${RESET}.`);
1599
+ info(`${DIM}Use Gencow Dashboard at https://gencow.app${RESET}\n`);
1733
1600
  },
1734
1601
 
1735
1602
 
@@ -1745,36 +1612,25 @@ ${BOLD}Quick Start:${RESET}
1745
1612
  ${GREEN}init <name>${RESET} Create a new Gencow project
1746
1613
  ${DIM}--template, -t Select template (default, task-app, fullstack, ai-chat)${RESET}
1747
1614
  ${DIM}--force, -f Initialize in non-empty directory (preserves existing files)${RESET}
1748
-
1749
- ${BOLD}Dev commands:${RESET}
1750
- ${GREEN}dev${RESET} Watch + auto-deploy to cloud + live logs ${DIM}(default)${RESET}
1751
- ${DIM}--local Use local PGlite instead of cloud${RESET}
1752
- ${DIM}--verbose Show all HTTP logs (including admin/ws)${RESET}
1753
- ${GREEN}dashboard${RESET} Open the Gencow admin dashboard in browser
1754
- ${GREEN}db:push${RESET} Sync schema.ts → cloud DB ${DIM}(default: cloud)${RESET}
1755
- ${DIM}--local Push to local DB instead of cloud${RESET}
1756
- ${DIM}--prod Push to production DB (confirmation required)${RESET}
1757
- ${GREEN}db:generate${RESET} Generate SQL migration files from schema.ts
1758
- ${GREEN}db:seed${RESET} Run gencow/seed.ts on cloud app ${DIM}(default: cloud)${RESET}
1759
- ${DIM}--local Seed local DB instead of cloud${RESET}
1760
- ${DIM}--prod Seed production app${RESET}
1761
- ${GREEN}db:reset${RESET} TRUNCATE all data + run seed.ts ${DIM}(local only)${RESET}
1762
- ${DIM}--local Required — local DB reset only (cloud: use Dashboard)${RESET}
1763
- ${GREEN}db:studio${RESET} Open Drizzle Studio ${DIM}(visual DB browser)${RESET}
1764
- ${GREEN}add <comp...>${RESET} Add components ${DIM}(AI RAG Tools Memory Analytics)${RESET}
1765
- ${GREEN}mcp${RESET} Start MCP server for AI agent integration ${DIM}(stdio)${RESET}
1766
- ${GREEN}codegen${RESET} Generate frontend-independent api.ts
1615
+ ${GREEN}add <comp...>${RESET} Add components ${DIM}(AI RAG Tools Memory)${RESET}
1616
+ ${GREEN}codegen${RESET} Generate frontend api.ts from schema
1767
1617
  ${DIM}--outdir, -o Output directory (default: src/gencow/)${RESET}
1768
1618
 
1769
- ${BOLD}BaaS commands (login required):${RESET}
1619
+ ${BOLD}Commands (login required):${RESET}
1770
1620
  ${GREEN}login${RESET} Login to Gencow Platform ${DIM}(browser → token)${RESET}
1771
1621
  ${GREEN}logout${RESET} Clear credentials
1772
1622
  ${GREEN}whoami${RESET} Show current user info
1773
- ${GREEN}static [dir]${RESET} Deploy static files to dev ${DIM}(dist/, out/, build/)${RESET}
1774
- ${DIM}--no-backend Skip backend auto-deploy${RESET}
1623
+ ${GREEN}dev${RESET} Watch + auto-deploy to cloud + live logs
1624
+ ${DIM}--verbose Show all HTTP logs (including admin/ws)${RESET}
1625
+ ${GREEN}db:push${RESET} Sync schema.ts → cloud DB
1626
+ ${DIM}--prod Push to production DB (confirmation required)${RESET}
1627
+ ${GREEN}db:generate${RESET} Generate SQL migration files from schema.ts
1628
+ ${GREEN}db:seed${RESET} Run gencow/seed.ts on cloud app
1629
+ ${DIM}--prod Seed production app${RESET}
1630
+ ${GREEN}static [dir]${RESET} Deploy static files ${DIM}(dist/, out/, build/)${RESET}
1631
+ ${DIM}--prod Deploy to production app${RESET}
1775
1632
  ${DIM}--force, -f Skip dependency audit${RESET}
1776
- ${GREEN}deploy${RESET} Deploy to production ${DIM}(Pro+ only)${RESET}
1777
- ${DIM}--static [dir] Deploy static files to production${RESET}
1633
+ ${GREEN}deploy${RESET} Deploy backend to production ${DIM}(Pro+ only)${RESET}
1778
1634
  ${DIM}--rollback Rollback to previous deployment${RESET}
1779
1635
  ${DIM}--force, -f Skip dependency audit${RESET}
1780
1636
  ${GREEN}env list${RESET} List cloud env vars ${DIM}(--prod for production)${RESET}
@@ -1785,9 +1641,10 @@ ${BOLD}BaaS commands (login required):${RESET}
1785
1641
  ${GREEN}files list${RESET} List uploaded files
1786
1642
  ${GREEN}files delete${RESET} Delete uploaded file ${DIM}(--yes to skip confirm)${RESET}
1787
1643
  ${GREEN}files url${RESET} Get serving URL for a file
1788
- ${GREEN}config set${RESET} Set app config ${DIM}(image.maxWidth, image.quality)${RESET}
1789
- ${GREEN}config get${RESET} Show current app config
1790
- ${GREEN}config reset${RESET} Reset app config to tier defaults
1644
+ ${GREEN}config set${RESET} Set image config ${DIM}(config set image.maxWidth 1920)${RESET}
1645
+ ${DIM}Keys: image.maxWidth (0-10000), image.quality (0-100)${RESET}
1646
+ ${GREEN}config get${RESET} Show current image config
1647
+ ${GREEN}config reset${RESET} Reset image config to tier defaults
1791
1648
  ${GREEN}domain set${RESET} Connect custom domain ${DIM}(myapp.com)${RESET}
1792
1649
  ${GREEN}domain status${RESET} Check domain DNS/TLS status
1793
1650
  ${GREEN}domain remove${RESET} Disconnect custom domain
@@ -1955,19 +1812,19 @@ ${BOLD}Examples:${RESET}
1955
1812
  }
1956
1813
  },
1957
1814
 
1958
- // ── static — dev 정적 파일 배포 (독립 명령어) ─────────
1815
+ // ── static — 정적 파일 배포 (dev 기본, --prod 로 프로덕션) ──
1959
1816
  async static(...staticArgs) {
1960
1817
  const creds = requireCreds();
1961
1818
 
1962
1819
  let staticDir = null;
1963
1820
  let forceDeploy = false;
1964
- let noBackend = false;
1965
1821
  let appId = null;
1822
+ let isProd = false;
1966
1823
 
1967
1824
  for (let i = 0; i < staticArgs.length; i++) {
1968
1825
  const a = staticArgs[i];
1969
1826
  if (a === "--force" || a === "-f") forceDeploy = true;
1970
- else if (a === "--no-backend") noBackend = true;
1827
+ else if (a === "--prod") isProd = true;
1971
1828
  else if (a === "--app" || a === "-a") appId = staticArgs[++i];
1972
1829
  else if (!a.startsWith("-")) {
1973
1830
  staticDir = a;
@@ -1976,9 +1833,21 @@ ${BOLD}Examples:${RESET}
1976
1833
 
1977
1834
  // gencow.json에서 appId 로드
1978
1835
  const gencowJsonPath = resolve(process.cwd(), "gencow.json");
1979
- if (!appId && existsSync(gencowJsonPath)) {
1836
+ let prodAppId = null;
1837
+ if (existsSync(gencowJsonPath)) {
1980
1838
  const gencowJson = JSON.parse(readFileSync(gencowJsonPath, "utf8"));
1981
- appId = gencowJson.appId || gencowJson.appName;
1839
+ if (!appId) appId = gencowJson.appId || gencowJson.appName;
1840
+ prodAppId = gencowJson.prodApp || null;
1841
+ }
1842
+
1843
+ // --prod: prod app 대상
1844
+ const deployTarget = isProd ? (prodAppId || appId) : appId;
1845
+ const envTarget = isProd ? "prod" : "dev";
1846
+
1847
+ if (isProd && !prodAppId) {
1848
+ error("No production app found. Run 'gencow deploy' first to create one.");
1849
+ info(`${DIM}For dev static deploy, omit --prod: gencow static [dir]${RESET}\n`);
1850
+ return;
1982
1851
  }
1983
1852
 
1984
1853
  // displayName
@@ -1991,8 +1860,8 @@ ${BOLD}Examples:${RESET}
1991
1860
  }
1992
1861
  if (!displayName) displayName = basename(process.cwd());
1993
1862
 
1994
- return await this._deployStatic(creds, appId, displayName, staticDir, gencowJsonPath, {
1995
- forceDeploy, noBackend, envTarget: "dev",
1863
+ return await this._deployStatic(creds, deployTarget, displayName, staticDir, gencowJsonPath, {
1864
+ forceDeploy, noBackend: true, envTarget,
1996
1865
  });
1997
1866
  },
1998
1867
 
@@ -2004,10 +1873,7 @@ ${BOLD}Examples:${RESET}
2004
1873
  let appId = null;
2005
1874
  let displayName = null;
2006
1875
  let envTarget = "prod"; // v0.1.120: deploy = prod 기본값
2007
- let staticDir = null; // --static 옵션
2008
- let isStatic = false;
2009
1876
  let forceDeploy = false; // --force: skip dependency audit
2010
- let noBackend = false; // --no-backend: skip backend auto-deploy in --static mode
2011
1877
  let isRollback = false; // --rollback: rollback to previous deploy
2012
1878
 
2013
1879
  // ── subcommand 분기 (logs / status) ───────────────────
@@ -2079,33 +1945,30 @@ ${BOLD}Examples:${RESET}
2079
1945
  envTarget = "prod";
2080
1946
  }
2081
1947
  else if (a === "--force" || a === "-f") forceDeploy = true;
2082
- else if (a === "--no-backend") noBackend = true;
2083
1948
  else if (a === "--rollback") isRollback = true;
2084
1949
  else if (a === "--app" || a === "-a") appId = deployArgs[++i];
2085
1950
  else if (a === "--static") {
2086
- isStatic = true;
2087
- // 다음 인자가 옵션이 아니면 디렉토리로 사용
2088
- const next = deployArgs[i + 1];
2089
- if (next && !next.startsWith("-")) {
2090
- staticDir = next;
2091
- i++;
2092
- }
1951
+ // Deprecated: redirect to gencow static --prod
1952
+ warn(`${YELLOW}--static is deprecated. Use: gencow static --prod${RESET}`);
1953
+ return;
1954
+ }
1955
+ else if (a === "--no-backend") {
1956
+ // Deprecated: silently ignore
2093
1957
  }
2094
1958
  else if (!a.startsWith("-")) {
2095
1959
  // 미인식 subcommand — 에러 출력
2096
1960
  error(`Unknown deploy argument: "${a}"`);
2097
1961
  log("");
2098
1962
  info(`Usage: gencow deploy [options]`);
2099
- info(` gencow deploy Production deploy (Pro+)`);
2100
- info(` gencow deploy --static Production static deploy (Pro+)`);
1963
+ info(` gencow deploy Production backend deploy (Pro+)`);
2101
1964
  info(` gencow deploy --rollback Rollback to previous version`);
2102
1965
  info(` gencow deploy logs View server logs`);
2103
1966
  info(` gencow deploy status Check app status`);
2104
1967
  info(` gencow deploy --force Skip dependency audit`);
2105
1968
  log("");
2106
- info(`💡 Dev environment:`);
2107
- info(` gencow dev Real-time backend deploy`);
2108
- info(` gencow static [dir] Static file deploy`);
1969
+ info(`💡 Static files:`);
1970
+ info(` gencow static [dir] Deploy static files (dev)`);
1971
+ info(` gencow static --prod Deploy static files (production)`);
2109
1972
  process.exit(1);
2110
1973
  }
2111
1974
  }
@@ -2180,12 +2043,6 @@ ${BOLD}Examples:${RESET}
2180
2043
  return;
2181
2044
  }
2182
2045
 
2183
- // ── Static Deploy 분기 ────────────────────────────────
2184
- if (isStatic) {
2185
- // prod 모드면 prodApp 대상으로 정적 배포
2186
- const staticTarget = (envTarget === "prod" && prodAppId) ? prodAppId : appId;
2187
- return await this._deployStatic(creds, staticTarget, displayName, staticDir, gencowJsonPath, { forceDeploy, noBackend, envTarget });
2188
- }
2189
2046
 
2190
2047
  // ── Prod 앱 자동 생성 + 배포 대상 전환 (Pro+) ──────────
2191
2048
  if (envTarget === "prod" && appId) {
@@ -2299,7 +2156,7 @@ ${BOLD}Examples:${RESET}
2299
2156
  msg.includes("nothing to migrate") ||
2300
2157
  msg.includes("No changes detected")
2301
2158
  ) {
2302
- log(`${DIM} No schema changeskeeping existing migrations${RESET}`);
2159
+ log(`${DIM} Migrations up-to-dateno new schema changes detected${RESET}`);
2303
2160
  } else {
2304
2161
  warn(`Migration generation warning: ${msg.split("\n")[0] || "unknown"}`);
2305
2162
  warn("gencow/migrations/ missing or outdated — platform may skip schema apply.");
@@ -2822,7 +2679,7 @@ ${BOLD}Examples:${RESET}
2822
2679
  } catch (e) {
2823
2680
  const msg = e.stderr?.toString() || e.message || "";
2824
2681
  if (msg.includes("No schema changes") || msg.includes("nothing to migrate") || msg.includes("No changes detected")) {
2825
- log(`${DIM} No schema changesusing existing migrations${RESET}`);
2682
+ log(`${DIM} Migrations up-to-dateno new schema changes detected${RESET}`);
2826
2683
  } else {
2827
2684
  warn(`Migration generation failed: ${msg.split("\\n")[0]}`);
2828
2685
  info("Will attempt schema push via server.");
@@ -3978,28 +3835,9 @@ ${BOLD}Examples:${RESET}
3978
3835
  }
3979
3836
  },
3980
3837
 
3981
- async mcp(...mcpArgs) {
3982
- let port = "5456";
3983
- for (let i = 0; i < mcpArgs.length; i++) {
3984
- if (mcpArgs[i] === "--port" || mcpArgs[i] === "-p") port = mcpArgs[++i];
3985
- }
3986
-
3987
- const mcpScript = resolve(fileURLToPath(import.meta.url), "..", "gencow-mcp.mjs");
3988
- if (!existsSync(mcpScript)) {
3989
- error("gencow-mcp.mjs not found. Ensure the CLI package is properly installed.");
3990
- process.exit(1);
3991
- }
3992
-
3993
- // MCP stdio 서버를 직접 실행 (stdin/stdout 상속)
3994
- const { execFileSync } = await import("child_process");
3995
- try {
3996
- execFileSync("node", [mcpScript], {
3997
- stdio: "inherit",
3998
- env: { ...process.env, GENCOW_PORT: port },
3999
- });
4000
- } catch {
4001
- // MCP 서버가 종료될 때 정상적으로 종료
4002
- }
3838
+ async mcp() {
3839
+ info(`MCP server is ${BOLD}coming soon${RESET}.`);
3840
+ info(`${DIM}MCP integration requires local dev server (coming soon).${RESET}\n`);
4003
3841
  },
4004
3842
 
4005
3843
 
@@ -4034,8 +3872,16 @@ ${BOLD}Examples:${RESET}
4034
3872
  let runtimeRoot;
4035
3873
  try { runtimeRoot = findServerRoot(); } catch { runtimeRoot = process.cwd(); }
4036
3874
  const extractTsPath = resolve(runtimeRoot, ".gencow-extract.ts");
3875
+
3876
+ // @gencow/core — 번들된 core 절대 경로 우선, 없으면 bare specifier
3877
+ // generateApiTs()와 동일 해석 전략: 글로벌 CLI에서도 resolve 보장
3878
+ const bundledCorePath = resolve(runtimeRoot, "../core/index.js");
3879
+ const coreImport = existsSync(bundledCorePath)
3880
+ ? bundledCorePath.replace(/\\/g, "/")
3881
+ : "@gencow/core";
3882
+
4037
3883
  const script = `
4038
- import { getRegisteredQueries, getRegisteredMutations } from "@gencow/core";
3884
+ import { getRegisteredQueries, getRegisteredMutations } from "${coreImport}";
4039
3885
  import "${absoluteFunctions}/index.ts";
4040
3886
  console.log("GENCOW_API_JSON=" + JSON.stringify({
4041
3887
  queries: getRegisteredQueries(),
@@ -4044,13 +3890,22 @@ console.log("GENCOW_API_JSON=" + JSON.stringify({
4044
3890
  process.exit(0);
4045
3891
  `;
4046
3892
  info("Extracting function list...");
3893
+ // NODE_PATH: 사용자 프로젝트 node_modules + CLI node_modules 포함
3894
+ // generateApiTs()와 동일 — 글로벌 설치 시 사용자 의존성 해석 보장
3895
+ const cwdNodeModules = resolve(process.cwd(), "node_modules");
3896
+ const cliNodeModules = resolve(__dirname, "..", "node_modules");
3897
+ const extractEnv = {
3898
+ ...process.env,
3899
+ NODE_PATH: [cwdNodeModules, cliNodeModules, process.env.NODE_PATH || ""].filter(Boolean).join(":"),
3900
+ };
4047
3901
  try {
4048
3902
  writeFileSync(extractTsPath, script);
4049
3903
  let outStr;
4050
3904
  try {
4051
3905
  outStr = execSync(`bun ${extractTsPath}`, {
4052
3906
  cwd: runtimeRoot,
4053
- stdio: ["pipe", "pipe", "pipe"]
3907
+ stdio: ["pipe", "pipe", "pipe"],
3908
+ env: extractEnv,
4054
3909
  }).toString();
4055
3910
  } catch (execErr) {
4056
3911
  const stderr = execErr.stderr?.toString() || "";
@@ -4941,7 +4796,8 @@ ${BOLD}${CYAN}🚀 Gencow Cloud Dev${RESET}
4941
4796
  log(` ${GREEN}Prompts${RESET} Reusable prompt templates`);
4942
4797
  log(` ${GREEN}Parsers${RESET} PDF/HTML/CSV file parsing`);
4943
4798
  log(` ${GREEN}Memory${RESET} Agent memory ${DIM}(episodic/semantic/procedural)${RESET}`);
4944
- log(` ${GREEN}Analytics${RESET} LLM call tracking ${DIM}(coming soon)${RESET}`);
4799
+ log(`\n${BOLD}Coming soon:${RESET}`);
4800
+ log(` ${DIM}Analytics${RESET} LLM call tracking`);
4945
4801
  log(`\n${BOLD}Examples:${RESET}`);
4946
4802
  log(` ${DIM}gencow add AI${RESET}`);
4947
4803
  log(` ${DIM}gencow add AI RAG Reranker${RESET}`);
@@ -4988,10 +4844,11 @@ ${BOLD}${CYAN}🚀 Gencow Cloud Dev${RESET}
4988
4844
  env: {},
4989
4845
  requires: ["ai"],
4990
4846
  guide: [
4991
- `gencow/rag.ts 에서 rag.ingest(), rag.search() 사용 가능`,
4992
- `mutation: await rag.ingest(ctx, source, text)`,
4993
- `query: const results = await rag.search(ctx, "질문")`,
4994
- `schema-rag.ts schema.ts import 해야 DB 테이블이 생성됩니다`,
4847
+ `gencow/rag.ts rag.ingest(), rag.search(), rag.ask()`,
4848
+ `Shared KB: await rag.ingest(ctx, "manual.pdf", text)`,
4849
+ `Personal: await rag.ingest(ctx, "notes.pdf", text, { userId: user.id })`,
4850
+ `Search: const results = await rag.search(ctx, "query", { userId: user.id })`,
4851
+ `Import schema-rag.ts in your schema.ts to create DB tables`,
4995
4852
  ],
4996
4853
  },
4997
4854
  memory: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.122",
3
+ "version": "0.1.123",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,13 +21,13 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@modelcontextprotocol/sdk": "^1.27.1",
24
+ "esbuild": "^0.27.3",
24
25
  "open": "^10.1.0",
25
26
  "tar": "^7",
26
27
  "ws": "^8.19.0",
27
28
  "zod": "^4.3.6"
28
29
  },
29
30
  "devDependencies": {
30
- "@types/node": "^25",
31
- "esbuild": "^0.27.3"
31
+ "@types/node": "^25"
32
32
  }
33
33
  }
package/server/index.js CHANGED
@@ -62096,7 +62096,16 @@ function createAdminRoutes(db, rawSql, driver, getCtx, storage, functionsPath) {
62096
62096
  async function runSeedFile(functionsPath, getCtx) {
62097
62097
  const seedTs = resolve3(functionsPath, "seed.ts");
62098
62098
  const seedJs = resolve3(functionsPath, "seed.js");
62099
- const seedFile = existsSync2(seedTs) ? seedTs : existsSync2(seedJs) ? seedJs : null;
62099
+ let seedFile = existsSync2(seedTs) ? seedTs : existsSync2(seedJs) ? seedJs : null;
62100
+ if (!seedFile && functionsPath.endsWith("gencow-bc")) {
62101
+ const originalDir = resolve3(functionsPath, "..", "gencow");
62102
+ const origTs = resolve3(originalDir, "seed.ts");
62103
+ const origJs = resolve3(originalDir, "seed.js");
62104
+ seedFile = existsSync2(origTs) ? origTs : existsSync2(origJs) ? origJs : null;
62105
+ if (seedFile) {
62106
+ console.log(`[seed] seed.ts not in bytecode dir \u2014 using original: ${seedFile}`);
62107
+ }
62108
+ }
62100
62109
  if (!seedFile) {
62101
62110
  console.log("[seed] gencow/seed.ts not found \u2014 skipping");
62102
62111
  return false;