chiwaa 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -22,6 +22,7 @@ npx chiwaa deploy
22
22
  | `chiwaa domains` · `search` · `buy` · `add` · `check` | x-y.net 도메인 찾기·사기(결제는 x-y.net 결제창에서 직접)·붙이기 |
23
23
  | `chiwaa stats` | 방문자 통계(오늘·최근 7일·많이 본 페이지·들어온 곳) |
24
24
  | `chiwaa deploy --preview` | 운영 주소는 두고 `이름--preview.chiwaa.com` 에 미리보기 |
25
+ | `chiwaa env` · `env set 이름` · `env rm 이름` | 서버 함수(`api/*.js`) 비밀값 — 값은 화면에 안 보이게 입력 |
25
26
  | `chiwaa lock` / `unlock` | 사이트 비밀번호 잠금(공개 전 나만 보기) |
26
27
  | `chiwaa open` · `usage` | 관리 화면 열기 · 이번 달 사용량 |
27
28
  | `chiwaa agent` | AI 도구용 안내(AGENTS.md·CLAUDE.md) 만들기 — 처음 deploy 때 자동 |
package/bin/chiwaa.js CHANGED
@@ -373,6 +373,14 @@ async function deploy(args) {
373
373
  const site = await resolveSite(dir, args);
374
374
  const { out, built } = buildIfNeeded(dir, args);
375
375
  const { files, total } = collect(out, !built);
376
+ // 서버 함수: 프로젝트 맨 위 api/ 는 빌드 결과에 안 들어가므로 따로 넣는다(서버가 사이트 파일에서 떼어 서버 함수로 돌린다)
377
+ const apiDir = path.join(dir, "api");
378
+ if (built && fs.existsSync(apiDir) && fs.statSync(apiDir).isDirectory() && !files.some((f) => f.rel === "api")) {
379
+ const extra = collect(apiDir, true);
380
+ files.push({ rel: "api", dir: true }, ...extra.files.map((f) => ({ ...f, rel: `api/${f.rel}` })));
381
+ }
382
+ const fnCount = files.filter((f) => !f.dir && /^api\/[^/_][^/]*\.(js|ts|mjs)$/.test(f.rel)).length;
383
+ if (fnCount) console.log(c.dim(`서버 함수 ${fnCount}개(api/) 함께 올림 → https://<사이트>/api/<이름>`));
376
384
  if (!files.some((f) => !f.dir && /^index\.html?$/i.test(f.rel)))
377
385
  console.log(c.dim("참고: 맨 위에 index.html 이 없습니다. 주소로 열면 첫 화면이 안 보일 수 있습니다."));
378
386
  const fileCount = files.filter((f) => !f.dir).length;
@@ -662,6 +670,40 @@ async function stats(args) {
662
670
  if (!s.total.views) console.log(c.dim("\n 아직 집계된 방문이 없습니다."));
663
671
  }
664
672
 
673
+ // ---------- env (서버 함수 비밀값) ----------
674
+ async function env(args) {
675
+ const sub = args._[1] || "ls";
676
+ const name = await siteName(args);
677
+ const base = `/api/v1/sites/${encodeURIComponent(name)}/env`;
678
+ if (sub === "ls") {
679
+ const r = await api("GET", base);
680
+ if (r.status !== 200) fail(r.data.error || "비밀값 목록을 받지 못했습니다.");
681
+ const d = r.data;
682
+ console.log(c.bold(`${name}.chiwaa.com 서버 함수 비밀값`), c.dim(`(${d.names.length}/${d.limit}개 · 값은 다시 보여 주지 않음)`));
683
+ for (const n of d.names) console.log(` ${n}`);
684
+ if (!d.names.length) console.log(c.dim(" 없음. 넣기: npx chiwaa env set 이름 (값은 화면에 안 보이게 입력)"));
685
+ console.log(c.dim(`\n이번 달 서버 함수 실행 ${Number(d.calls_this_month).toLocaleString("ko-KR")}회 · 마지막 실행 ${d.last_used_at ? d.last_used_at.slice(0, 10) : "없음"}`));
686
+ if (d.idle_90d) console.log(c.red("⚠ 90일 넘게 서버 함수를 안 썼습니다. 안 쓰는 비밀값(결제 키 등)은 지우는 게 안전합니다: npx chiwaa env rm 이름"));
687
+ return;
688
+ }
689
+ const key = args._[2];
690
+ if (!key) fail(`이름을 적어 주세요. 예: npx chiwaa env ${sub} TOSS_SECRET_KEY`);
691
+ if (sub === "set") {
692
+ if (!/^[A-Z][A-Z0-9_]{0,63}$/.test(key)) fail("이름은 영문 대문자로 시작하고 대문자·숫자·밑줄 64자까지입니다. 예: TOSS_SECRET_KEY");
693
+ const value = await readSecret(`${key} 값(화면에 안 보임): `);
694
+ if (!value) fail("값이 비어 있습니다. (AI·자동화에서는 표준입력으로: echo 값 | npx chiwaa env set 이름)");
695
+ const r = await api("POST", base, { body: { name: key, value } });
696
+ if (r.status !== 200) fail(r.data.error || "넣지 못했습니다.");
697
+ return console.log(c.green("✓"), r.data.message);
698
+ }
699
+ if (sub === "rm") {
700
+ const r = await api("POST", `${base}/remove`, { body: { name: key } });
701
+ if (r.status !== 200) fail(r.data.error || "지우지 못했습니다.");
702
+ return console.log(c.green("✓"), r.data.message);
703
+ }
704
+ fail(`모르는 env 명령입니다: ${sub}\n 쓸 수 있는 것: ls · set · rm`);
705
+ }
706
+
665
707
  // ---------- lock / unlock / open / usage ----------
666
708
  function readSecret(prompt) {
667
709
  if (!process.stdin.isTTY) {
@@ -762,6 +804,7 @@ const HELP = `chiwaa ${VERSION} — chiwaa.kr 에 사이트를 바로 올립니
762
804
  chiwaa domains add <도메인> 도메인 붙이기(x-y.net 도메인은 바로, 다른 곳 도메인은 넣을 DNS 레코드 안내)
763
805
  chiwaa domains check 연결됐는지 확인 · domains remove -y 로 연결 끊기
764
806
  chiwaa stats 방문자 통계(오늘·최근 7일, 많이 본 페이지, 들어온 곳) --days 30
807
+ chiwaa env 서버 함수 비밀값 목록 · env set 이름(값은 안 보이게 입력) · env rm 이름
765
808
  chiwaa lock / unlock 사이트 비밀번호 잠금(아이디 chiwaa) / 풀기 — 공개 전 나만 보기
766
809
  chiwaa open 관리 화면 열기 (--site 는 사이트 열기)
767
810
  chiwaa usage 이번 달 전송량·한도, 요금제
@@ -778,7 +821,7 @@ async function main() {
778
821
  const cmd = args._[0];
779
822
  if (args.version) return console.log(VERSION);
780
823
  if (args.help || !cmd || cmd === "help") return console.log(HELP);
781
- const cmds = { deploy, login, list, ls: list, versions, rollback, db, domains, domain: domains, stats, lock, unlock, open, usage, agent, whoami, logout };
824
+ const cmds = { deploy, login, list, ls: list, versions, rollback, db, domains, domain: domains, stats, env, lock, unlock, open, usage, agent, whoami, logout };
782
825
  if (!cmds[cmd]) fail(`모르는 명령입니다: ${cmd}\n\n${HELP}`);
783
826
  await cmds[cmd](args);
784
827
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chiwaa",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "chiwaa.kr 에 사이트를 터미널에서 바로 올리는 도구",
5
5
  "bin": {
6
6
  "chiwaa": "bin/chiwaa.js"