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.
- package/bin/chiwaa.js +61 -5
- 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
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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 (
|
|
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`));
|