chiwaa 0.1.12 → 0.1.13

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.
Files changed (2) hide show
  1. package/bin/chiwaa.js +61 -5
  2. package/package.json +1 -1
package/bin/chiwaa.js CHANGED
@@ -236,12 +236,20 @@ function buildIfNeeded(dir, args) {
236
236
  const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
237
237
  const found = OUTPUTS.find(([n]) => deps[n]);
238
238
  let outName = args.dir || (found ? found[1] : "dist");
239
- if (found && found[0] === "next" && !args.dir) checkNext(dir);
239
+ let restore = null;
240
+ if (found && found[0] === "next" && !args.dir) {
241
+ checkNext(dir);
242
+ if (!args["no-build"]) restore = wrapNextConfig(dir);
243
+ }
240
244
  if (args["no-build"]) {
241
245
  console.log(c.dim("빌드는 건너뜁니다(--no-build)."));
242
246
  } else {
243
- if (!fs.existsSync(path.join(dir, "node_modules"))) run("npm install", dir);
244
- run("npm run build", dir);
247
+ try {
248
+ if (!fs.existsSync(path.join(dir, "node_modules"))) run("npm install", dir);
249
+ run("npm run build", dir);
250
+ } finally {
251
+ if (restore) restore();
252
+ }
245
253
  }
246
254
  let out = path.join(dir, outName);
247
255
  if (!fs.existsSync(out)) {
@@ -289,8 +297,56 @@ function checkNext(dir) {
289
297
  fail(`이 Next.js 앱은 서버에서 돌아가는 기능을 씁니다(${shown}). chiwaa 는 화면 파일(HTML·JS)을 올리는 곳이라 이대로는 열리지 않습니다.\n` +
290
298
  `AI 에게 「이 Next.js 앱을 chiwaa 에 올릴 수 있게 output: 'export' 정적 사이트로 바꾸고, API·middleware 같은 서버 기능은 맨 위 api/ 폴더의 chiwaa 서버 함수로 옮겨 줘. ${AI_GUIDE}」라고 말해 보세요.`);
291
299
  }
300
+ }
301
+
302
+ // 서버 기능이 없는 Next.js 는 next.config 를 그대로 두고 이번 빌드만 정적 내보내기로 덧씌운다(빌드 서버 prepare_next 와 같은 덧씌우기).
303
+ // 빌드가 끝나면(실패·Ctrl+C 포함) 원래 설정으로 되돌린다. 되돌리는 함수, 덧씌울 필요가 없으면 null.
304
+ function wrapNextConfig(dir) {
292
305
  const conf = ["next.config.js", "next.config.mjs", "next.config.cjs", "next.config.ts"].find((n) => fs.existsSync(path.join(dir, n)));
293
- if (!conf || !/output\s*:\s*['"]export['"]/.test(fs.readFileSync(path.join(dir, conf), "utf8"))) fail(NEXT_EXPORT_MSG);
306
+ if (conf && /output\s*:\s*['"]export['"]/.test(fs.readFileSync(path.join(dir, conf), "utf8"))) return null;
307
+ const ext = conf ? path.extname(conf) : ".mjs";
308
+ const target = path.join(dir, conf || "next.config.mjs");
309
+ const orig = `next.config.chiwaa-orig${ext}`;
310
+ const body = [
311
+ ' const base = (typeof orig === "function" ? await orig(phase, ctx) : await orig) || {};',
312
+ " // cacheComponents·partialPrefetching(PPR)은 정적 내보내기와 함께 쓸 수 없다(Next 16 기본 설정에 들어 있음)",
313
+ " const { cacheComponents, partialPrefetching, ...rest } = base;",
314
+ ' return { ...rest, output: "export", images: { ...(rest.images || {}), unoptimized: true } };',
315
+ "",
316
+ ].join("\n");
317
+ let text;
318
+ if (!conf) {
319
+ text = 'export default { output: "export", images: { unoptimized: true } };\n';
320
+ } else {
321
+ const pkg = readJSON(path.join(dir, "package.json")) || {};
322
+ const cjs = ext === ".cjs" || (ext === ".js" && pkg.type !== "module");
323
+ const from = ext === ".ts" ? "next.config.chiwaa-orig" : orig;
324
+ text = cjs
325
+ ? `// @ts-nocheck
326
+ const orig = require("./${from}");
327
+ module.exports = async (phase, ctx) => {
328
+ ${body}};
329
+ `
330
+ : `// @ts-nocheck
331
+ import orig from "./${from}";
332
+ export default async function chiwaa(phase, ctx) {
333
+ ${body}}
334
+ `;
335
+ fs.renameSync(target, path.join(dir, orig));
336
+ }
337
+ fs.writeFileSync(target, text);
338
+ let done = false;
339
+ const restore = () => {
340
+ if (done) return;
341
+ done = true;
342
+ fs.rmSync(target, { force: true });
343
+ if (conf) fs.renameSync(path.join(dir, orig), target);
344
+ process.removeListener("SIGINT", onInt);
345
+ };
346
+ const onInt = () => { restore(); process.exit(130); };
347
+ process.on("SIGINT", onInt);
348
+ console.log(c.dim("next.config 는 그대로 두고, 이번 빌드만 정적 사이트로 내보냅니다(output: 'export')."));
349
+ return restore;
294
350
  }
295
351
 
296
352
  // 첫 화면(index.html)이 없는 폴더를 올리려 하면, 앱이나 HTML 이 들어 있는 하위 폴더를 알려 주고 멈춘다
@@ -432,7 +488,7 @@ async function deploy(args) {
432
488
  files.push({ rel: "api", dir: true }, ...extra.files.map((f) => ({ ...f, rel: `api/${f.rel}` })));
433
489
  }
434
490
  const fnCount = files.filter((f) => !f.dir && /^api\/[^/_][^/]*\.(js|ts|mjs)$/.test(f.rel)).length;
435
- if (fnCount) console.log(c.dim(`서버 함수 ${fnCount}개(api/) 함께 올림 → https://<사이트>/api/<이름>`));
491
+ if (fnCount) console.log(c.dim(`서버 함수 ${fnCount}개(api/) 함께 올림 → https://<사이트>/api/<이름> (서버 함수는 1분 안에 켜집니다 — 그 전에는 404 일 수 있음)`));
436
492
  if (!files.some((f) => !f.dir && f.rel === "index.html")) fail(noIndexMessage(out));
437
493
  const fileCount = files.filter((f) => !f.dir).length;
438
494
  console.log(c.dim(`올리는 중: ${path.relative(process.cwd(), out) || "."} — 파일 ${fileCount}개, ${(total / 1048576).toFixed(1)}MB`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chiwaa",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "chiwaa.kr 에 사이트를 터미널에서 바로 올리는 도구",
5
5
  "bin": {
6
6
  "chiwaa": "bin/chiwaa.js"