gencow 0.1.126 → 0.1.128
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 +172 -12
- package/dashboard/assets/{index-D3c-3Tbj.js → index-C1WhUSu8.js} +74 -73
- package/dashboard/assets/index-DoG4z4Kv.css +1 -0
- package/dashboard/index.html +2 -2
- package/lib/__tests__/readme-codegen.test.ts +4 -3
- package/lib/readme-codegen.mjs +8 -7
- package/package.json +1 -1
- package/dashboard/assets/index-treFoOsZ.css +0 -1
package/bin/gencow.mjs
CHANGED
|
@@ -425,6 +425,40 @@ function spawnInServer(cmd, args, env = process.env) {
|
|
|
425
425
|
return spawn(cmd, args, { cwd: serverRoot, stdio: "inherit", shell: true, env });
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
+
// ─── Core Import Resolution ───────────────────────────────
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @gencow/core import 경로 해석 — 3단계 fallback
|
|
432
|
+
*
|
|
433
|
+
* 1. CLI 패키지 내 번들된 core (../core/index.js relative to server/)
|
|
434
|
+
* 2. 사용자 프로젝트 node_modules/@gencow/core/dist/index.js (절대 경로)
|
|
435
|
+
* 3. bare specifier "@gencow/core" (모노레포 등 이미 resolve 가능한 경우)
|
|
436
|
+
*
|
|
437
|
+
* Bun ESM은 NODE_PATH를 무시하므로, bare specifier fallback은
|
|
438
|
+
* .gencow-extract.ts 파일 위치(CLI server 디렉토리) 기준으로만 해석됨.
|
|
439
|
+
* 따라서 2단계에서 프로젝트 node_modules의 절대 경로를 명시적으로 시도하여
|
|
440
|
+
* 글로벌/npx 설치 환경에서도 안정적으로 resolve.
|
|
441
|
+
*
|
|
442
|
+
* @param {string} serverRoot - findServerRoot()가 반환한 서버 루트 경로
|
|
443
|
+
* @returns {string} import 경로 (절대 경로 또는 bare specifier)
|
|
444
|
+
*/
|
|
445
|
+
function resolveCoreImport(serverRoot) {
|
|
446
|
+
// 1차: CLI 패키지 내 번들된 core
|
|
447
|
+
const bundledCorePath = resolve(serverRoot, "../core/index.js");
|
|
448
|
+
if (existsSync(bundledCorePath)) return bundledCorePath.replace(/\\/g, "/");
|
|
449
|
+
|
|
450
|
+
// 2차: 사용자 프로젝트 node_modules (절대 경로 — Bun ESM에서 확실히 resolve)
|
|
451
|
+
const cwdCoreDist = resolve(process.cwd(), "node_modules/@gencow/core/dist/index.js");
|
|
452
|
+
if (existsSync(cwdCoreDist)) return cwdCoreDist.replace(/\\/g, "/");
|
|
453
|
+
|
|
454
|
+
// 2차-b: src/ 직접 참조 (모노레포 workspace 등에서 dist 미빌드 시)
|
|
455
|
+
const cwdCoreSrc = resolve(process.cwd(), "node_modules/@gencow/core/src/index.ts");
|
|
456
|
+
if (existsSync(cwdCoreSrc)) return cwdCoreSrc.replace(/\\/g, "/");
|
|
457
|
+
|
|
458
|
+
// 3차: bare specifier — 모노레포 또는 이미 resolve 가능한 환경
|
|
459
|
+
return "@gencow/core";
|
|
460
|
+
}
|
|
461
|
+
|
|
428
462
|
// ─── API Codegen ──────────────────────────────────────────
|
|
429
463
|
|
|
430
464
|
function generateApiTs(config) {
|
|
@@ -433,11 +467,8 @@ function generateApiTs(config) {
|
|
|
433
467
|
const apiTsPath = resolve(absoluteFunctions, "api.ts");
|
|
434
468
|
const extractTsPath = resolve(serverRoot, ".gencow-extract.ts");
|
|
435
469
|
|
|
436
|
-
// Resolve @gencow/core — bundled
|
|
437
|
-
const
|
|
438
|
-
const coreImport = existsSync(bundledCorePath)
|
|
439
|
-
? bundledCorePath.replace(/\\/g, "/") // Windows 호환
|
|
440
|
-
: "@gencow/core"; // 모노레포 등 이미 resolve 가능한 경우
|
|
470
|
+
// Resolve @gencow/core — 3단계 fallback (bundled → CWD node_modules → bare specifier)
|
|
471
|
+
const coreImport = resolveCoreImport(serverRoot);
|
|
441
472
|
|
|
442
473
|
const script = `
|
|
443
474
|
import { getRegisteredQueries, getRegisteredMutations } from "${coreImport}";
|
|
@@ -696,6 +727,21 @@ const commands = {
|
|
|
696
727
|
|
|
697
728
|
// ── init ─────────────────────────────────────────────
|
|
698
729
|
async init(...initArgs) {
|
|
730
|
+
// --help handler
|
|
731
|
+
if (initArgs.includes("--help") || initArgs.includes("-h")) {
|
|
732
|
+
log(`\n${BOLD}${CYAN}gencow init${RESET} — Create a new Gencow project\n`);
|
|
733
|
+
log(` ${BOLD}Usage:${RESET} gencow init [name] [options]\n`);
|
|
734
|
+
log(` ${BOLD}Arguments:${RESET}`);
|
|
735
|
+
log(` ${CYAN}name${RESET} Project name (creates directory) or "." for current dir\n`);
|
|
736
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
737
|
+
log(` ${DIM}--template, -t${RESET} Select template (default, task-app, fullstack, ai-chat)`);
|
|
738
|
+
log(` ${DIM}--force, -f${RESET} Initialize in non-empty directory\n`);
|
|
739
|
+
log(` ${BOLD}Examples:${RESET}`);
|
|
740
|
+
log(` gencow init my-app`);
|
|
741
|
+
log(` gencow init . --force`);
|
|
742
|
+
log(` gencow init my-app --template fullstack\n`);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
699
745
|
// Parse --template / -t flag, --force / -f flag, and project name from args
|
|
700
746
|
let name = null;
|
|
701
747
|
let templateId = null;
|
|
@@ -1135,6 +1181,16 @@ ${hasPrompt ? `
|
|
|
1135
1181
|
// seed.ts 실행 (TRUNCATE 없이). 서버가 실행 중이어야 함.
|
|
1136
1182
|
// Cloud-first: 기본=Cloud, --local=로컬
|
|
1137
1183
|
async "db:seed"(...args) {
|
|
1184
|
+
// --help handler
|
|
1185
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
1186
|
+
log(`\n${BOLD}${CYAN}gencow db:seed${RESET} — Run seed.ts on cloud app\n`);
|
|
1187
|
+
log(` ${BOLD}Usage:${RESET} gencow db:seed [options]\n`);
|
|
1188
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
1189
|
+
log(` ${DIM}--prod${RESET} Seed production app`);
|
|
1190
|
+
log(` ${DIM}--local${RESET} Seed local dev server`);
|
|
1191
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1138
1194
|
const config = loadConfig();
|
|
1139
1195
|
const isLocal = isLocalDbTarget(args);
|
|
1140
1196
|
|
|
@@ -1531,6 +1587,16 @@ ${hasPrompt ? `
|
|
|
1531
1587
|
// ── db:push ──────────────────────────────────────────
|
|
1532
1588
|
// Cloud-first: 기본=Cloud, --local=로컬
|
|
1533
1589
|
async "db:push"(...args) {
|
|
1590
|
+
// --help handler
|
|
1591
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
1592
|
+
log(`\n${BOLD}${CYAN}gencow db:push${RESET} — Sync schema.ts → database\n`);
|
|
1593
|
+
log(` ${BOLD}Usage:${RESET} gencow db:push [options]\n`);
|
|
1594
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
1595
|
+
log(` ${DIM}--prod${RESET} Push to production DB (confirmation required)`);
|
|
1596
|
+
log(` ${DIM}--local${RESET} Push to local dev DB`);
|
|
1597
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1534
1600
|
const config = loadConfig();
|
|
1535
1601
|
const isLocal = isLocalDbTarget(args);
|
|
1536
1602
|
|
|
@@ -1677,7 +1743,14 @@ ${hasPrompt ? `
|
|
|
1677
1743
|
},
|
|
1678
1744
|
|
|
1679
1745
|
// ── db:generate ──────────────────────────────────────
|
|
1680
|
-
async "db:generate"() {
|
|
1746
|
+
async "db:generate"(...args) {
|
|
1747
|
+
// --help handler
|
|
1748
|
+
if (args?.includes?.("--help") || args?.includes?.("-h")) {
|
|
1749
|
+
log(`\n${BOLD}${CYAN}gencow db:generate${RESET} — Generate SQL migration files\n`);
|
|
1750
|
+
log(` ${BOLD}Usage:${RESET} gencow db:generate\n`);
|
|
1751
|
+
log(` Generates migration files from schema.ts using drizzle-kit.\n`);
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1681
1754
|
const config = loadConfig();
|
|
1682
1755
|
log(`\n${BOLD}${CYAN}Gencow DB Generate${RESET}\n`);
|
|
1683
1756
|
info("Generating migration files from schema.ts...");
|
|
@@ -1936,6 +2009,23 @@ ${BOLD}Examples:${RESET}
|
|
|
1936
2009
|
|
|
1937
2010
|
// ── static — 정적 파일 배포 (dev 기본, --prod 로 프로덕션) ──
|
|
1938
2011
|
async static(...staticArgs) {
|
|
2012
|
+
// --help handler
|
|
2013
|
+
if (staticArgs.includes("--help") || staticArgs.includes("-h")) {
|
|
2014
|
+
log(`\n${BOLD}${CYAN}gencow static${RESET} — Deploy static files\n`);
|
|
2015
|
+
log(` ${BOLD}Usage:${RESET} gencow static [dir] [options]\n`);
|
|
2016
|
+
log(` ${BOLD}Arguments:${RESET}`);
|
|
2017
|
+
log(` ${CYAN}dir${RESET} Static directory (auto-detects dist/, out/, build/)\n`);
|
|
2018
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
2019
|
+
log(` ${DIM}--prod${RESET} Deploy to production app`);
|
|
2020
|
+
log(` ${DIM}--no-backend${RESET} Skip backend deployment`);
|
|
2021
|
+
log(` ${DIM}--force, -f${RESET} Skip dependency audit`);
|
|
2022
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
2023
|
+
log(` ${BOLD}Examples:${RESET}`);
|
|
2024
|
+
log(` gencow static dist/`);
|
|
2025
|
+
log(` gencow static --prod dist/`);
|
|
2026
|
+
log(` gencow static --no-backend dist/\n`);
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
1939
2029
|
const creds = requireCreds();
|
|
1940
2030
|
|
|
1941
2031
|
let staticDir = null;
|
|
@@ -1989,6 +2079,21 @@ ${BOLD}Examples:${RESET}
|
|
|
1989
2079
|
|
|
1990
2080
|
// ── deploy — 클라우드 배포 (dev 기본, --prod로 프로덕션) ──
|
|
1991
2081
|
async deploy(...deployArgs) {
|
|
2082
|
+
// --help handler
|
|
2083
|
+
if (deployArgs.includes("--help") || deployArgs.includes("-h")) {
|
|
2084
|
+
log(`\n${BOLD}${CYAN}gencow deploy${RESET} — Deploy backend to cloud\n`);
|
|
2085
|
+
log(` ${BOLD}Usage:${RESET} gencow deploy [options]\n`);
|
|
2086
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
2087
|
+
log(` ${DIM}--prod${RESET} Deploy to production (Pro+ only)`);
|
|
2088
|
+
log(` ${DIM}--rollback${RESET} Rollback to previous deployment`);
|
|
2089
|
+
log(` ${DIM}--force, -f${RESET} Skip dependency audit`);
|
|
2090
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
2091
|
+
log(` ${BOLD}Examples:${RESET}`);
|
|
2092
|
+
log(` gencow deploy`);
|
|
2093
|
+
log(` gencow deploy --prod`);
|
|
2094
|
+
log(` gencow deploy --rollback\n`);
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
1992
2097
|
const creds = requireCreds();
|
|
1993
2098
|
|
|
1994
2099
|
// gencow.json에서 앱 ID 확인 (자동 생성된 유니크 ID)
|
|
@@ -3049,6 +3154,20 @@ ${BOLD}Examples:${RESET}
|
|
|
3049
3154
|
|
|
3050
3155
|
// ── env ───────────────────────────────────────────────
|
|
3051
3156
|
async env(...envArgs) {
|
|
3157
|
+
// --help handler
|
|
3158
|
+
if (envArgs.includes("--help") || envArgs.includes("-h")) {
|
|
3159
|
+
log(`\n${BOLD}${CYAN}gencow env${RESET} — Environment variable management\n`);
|
|
3160
|
+
log(` ${BOLD}Usage:${RESET} gencow env <command> [options]\n`);
|
|
3161
|
+
log(` ${BOLD}Commands:${RESET}`);
|
|
3162
|
+
log(` ${CYAN}list${RESET} List cloud env vars`);
|
|
3163
|
+
log(` ${CYAN}set${RESET} KEY=VALUE Set cloud env var (hot-reload)`);
|
|
3164
|
+
log(` ${CYAN}unset${RESET} KEY Remove cloud env var`);
|
|
3165
|
+
log(` ${CYAN}push${RESET} Push .env to cloud\n`);
|
|
3166
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
3167
|
+
log(` ${DIM}--prod${RESET} Target production app`);
|
|
3168
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3052
3171
|
const creds = requireCreds();
|
|
3053
3172
|
const subCmd = envArgs[0] || "list";
|
|
3054
3173
|
const restArgs = envArgs.slice(1);
|
|
@@ -3216,6 +3335,19 @@ ${BOLD}Examples:${RESET}
|
|
|
3216
3335
|
|
|
3217
3336
|
// ── config ────────────────────────────────────────────
|
|
3218
3337
|
async config(...configArgs) {
|
|
3338
|
+
// --help handler
|
|
3339
|
+
if (configArgs.includes("--help") || configArgs.includes("-h")) {
|
|
3340
|
+
log(`\n${BOLD}${CYAN}gencow config${RESET} — App configuration\n`);
|
|
3341
|
+
log(` ${BOLD}Usage:${RESET} gencow config <command> [options]\n`);
|
|
3342
|
+
log(` ${BOLD}Commands:${RESET}`);
|
|
3343
|
+
log(` ${CYAN}set${RESET} <key> <value> Set config (e.g. image.maxWidth 1920)`);
|
|
3344
|
+
log(` ${CYAN}get${RESET} Show current config`);
|
|
3345
|
+
log(` ${CYAN}reset${RESET} Reset to tier defaults\n`);
|
|
3346
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
3347
|
+
log(` ${DIM}--prod${RESET} Target production app`);
|
|
3348
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
3349
|
+
return;
|
|
3350
|
+
}
|
|
3219
3351
|
const creds = requireCreds();
|
|
3220
3352
|
const subCmd = configArgs[0] || "help";
|
|
3221
3353
|
const restArgs = configArgs.slice(1);
|
|
@@ -3828,6 +3960,18 @@ ${BOLD}Examples:${RESET}
|
|
|
3828
3960
|
|
|
3829
3961
|
// ── domain ─────────────────────────────────────────────
|
|
3830
3962
|
async domain(...domainArgs) {
|
|
3963
|
+
// --help handler
|
|
3964
|
+
if (domainArgs.includes("--help") || domainArgs.includes("-h")) {
|
|
3965
|
+
log(`\n${BOLD}${CYAN}gencow domain${RESET} — Custom domain management\n`);
|
|
3966
|
+
log(` ${BOLD}Usage:${RESET} gencow domain <command> [options]\n`);
|
|
3967
|
+
log(` ${BOLD}Commands:${RESET}`);
|
|
3968
|
+
log(` ${CYAN}set${RESET} <domain> Connect custom domain (e.g. myapp.com)`);
|
|
3969
|
+
log(` ${CYAN}status${RESET} Check domain DNS/TLS status`);
|
|
3970
|
+
log(` ${CYAN}remove${RESET} Disconnect custom domain\n`);
|
|
3971
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
3972
|
+
log(` ${DIM}--app, -a${RESET} Target specific app\n`);
|
|
3973
|
+
return;
|
|
3974
|
+
}
|
|
3831
3975
|
const creds = requireCreds();
|
|
3832
3976
|
const subCmd = domainArgs[0] || "status";
|
|
3833
3977
|
const restArgs = domainArgs.slice(1);
|
|
@@ -3966,6 +4110,15 @@ ${BOLD}Examples:${RESET}
|
|
|
3966
4110
|
|
|
3967
4111
|
// ── codegen — 프론트엔드 전용 api.ts 생성 ─────────
|
|
3968
4112
|
async codegen(...codegenArgs) {
|
|
4113
|
+
// --help handler
|
|
4114
|
+
if (codegenArgs.includes("--help") || codegenArgs.includes("-h")) {
|
|
4115
|
+
log(`\n${BOLD}${CYAN}gencow codegen${RESET} — Generate frontend api.ts from schema\n`);
|
|
4116
|
+
log(` ${BOLD}Usage:${RESET} gencow codegen [options]\n`);
|
|
4117
|
+
log(` ${BOLD}Options:${RESET}`);
|
|
4118
|
+
log(` ${DIM}--outdir, -o${RESET} Output directory (default: src/gencow/)\n`);
|
|
4119
|
+
log(` Generates api.ts from gencow/ folder for frontend use.\n`);
|
|
4120
|
+
return;
|
|
4121
|
+
}
|
|
3969
4122
|
const config = loadConfig();
|
|
3970
4123
|
const absoluteFunctions = resolve(process.cwd(), config.functionsDir);
|
|
3971
4124
|
|
|
@@ -3994,12 +4147,8 @@ ${BOLD}Examples:${RESET}
|
|
|
3994
4147
|
try { runtimeRoot = findServerRoot(); } catch { runtimeRoot = process.cwd(); }
|
|
3995
4148
|
const extractTsPath = resolve(runtimeRoot, ".gencow-extract.ts");
|
|
3996
4149
|
|
|
3997
|
-
// @gencow/core —
|
|
3998
|
-
|
|
3999
|
-
const bundledCorePath = resolve(runtimeRoot, "../core/index.js");
|
|
4000
|
-
const coreImport = existsSync(bundledCorePath)
|
|
4001
|
-
? bundledCorePath.replace(/\\/g, "/")
|
|
4002
|
-
: "@gencow/core";
|
|
4150
|
+
// @gencow/core — 3단계 fallback (bundled → CWD node_modules → bare specifier)
|
|
4151
|
+
const coreImport = resolveCoreImport(runtimeRoot);
|
|
4003
4152
|
|
|
4004
4153
|
const script = `
|
|
4005
4154
|
import { getRegisteredQueries, getRegisteredMutations } from "${coreImport}";
|
|
@@ -4094,6 +4243,17 @@ process.exit(0);
|
|
|
4094
4243
|
|
|
4095
4244
|
// ── app (subcommands: create, list, delete) ────────
|
|
4096
4245
|
async app(subcmd, ...rest) {
|
|
4246
|
+
// --help handler
|
|
4247
|
+
if (subcmd === "--help" || subcmd === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
4248
|
+
log(`\n${BOLD}${CYAN}gencow app${RESET} — App management\n`);
|
|
4249
|
+
log(` ${BOLD}Usage:${RESET} gencow app <command>\n`);
|
|
4250
|
+
log(` ${BOLD}Commands:${RESET}`);
|
|
4251
|
+
log(` ${CYAN}list${RESET} List your apps`);
|
|
4252
|
+
log(` ${CYAN}create${RESET} Create a new app`);
|
|
4253
|
+
log(` ${CYAN}delete${RESET} Delete an app (confirmation required)`);
|
|
4254
|
+
log(` ${CYAN}status${RESET} Show app status\n`);
|
|
4255
|
+
return;
|
|
4256
|
+
}
|
|
4097
4257
|
const creds = requireCreds();
|
|
4098
4258
|
|
|
4099
4259
|
if (!subcmd || subcmd === "list") {
|