@akanjs/cli 0.0.121 → 0.0.122

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/cjs/index.js CHANGED
@@ -916,10 +916,10 @@ var Executor = class {
916
916
  exec(command, options = {}) {
917
917
  const proc = (0, import_child_process.exec)(command, { cwd: this.cwdPath, ...options });
918
918
  proc.stdout?.on("data", (data) => {
919
- Logger.raw(data.toString());
919
+ Logger.raw(import_chalk.default.dim(data.toString()));
920
920
  });
921
921
  proc.stderr?.on("data", (data) => {
922
- Logger.raw(import_chalk.default.red(data.toString()));
922
+ Logger.raw(import_chalk.default.dim(data.toString()));
923
923
  });
924
924
  return new Promise((resolve, reject) => {
925
925
  proc.on("exit", (code, signal) => {
@@ -1449,11 +1449,11 @@ var SysExecutor = class extends Executor {
1449
1449
  return viewComponents;
1450
1450
  }
1451
1451
  async getUnitComponents() {
1452
- const unitComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs4.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
1452
+ const unitComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs4.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
1453
1453
  return unitComponents;
1454
1454
  }
1455
1455
  async getTemplateComponents() {
1456
- const templateComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => import_fs4.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
1456
+ const templateComponents = (await import_promises.default.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => import_fs4.default.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
1457
1457
  return templateComponents;
1458
1458
  }
1459
1459
  async getViewsSourceCode() {
@@ -2041,6 +2041,7 @@ var runCommands = async (...commands) => {
2041
2041
  const errMsg = e instanceof Error ? e.message : typeof e === "string" ? e : JSON.stringify(e);
2042
2042
  Logger.error(`Command Error: ${import_chalk2.default.red(errMsg)}`);
2043
2043
  console.error(e);
2044
+ throw e;
2044
2045
  }
2045
2046
  });
2046
2047
  }
@@ -2408,525 +2409,1032 @@ var import_vite_tsconfig_paths = __toESM(require("vite-tsconfig-paths"));
2408
2409
 
2409
2410
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
2410
2411
  var frameworkDescription = `
2411
- \uB098\uB294 \uC880 \uB354 \uD6A8\uC728\uC801\uC73C\uB85C \uCF54\uB529\uC744 \uD558\uAE30 \uC704\uD574\uC11C \uC790\uCCB4 \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uC81C\uC791\uD588\uC5B4.
2412
- \uADF8\uB798\uC11C \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC744 \uD574\uC904\uD14C\uB2C8\uAE4C \uC798 \uC774\uD574\uD558\uB3C4\uB85D \uD574. \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uB294 next.js 13\uACFC nest.js, capacitor.js, nx, mongoDB \uAE30\uBC18\uC758 \uD504\uB860\uD2B8\uC5D4\uB4DC, \uC571, \uBC31\uC5D4\uB4DC \uD1B5\uD569 \uD504\uB808\uC784\uC6CC\uD06C\uC57C. \uADF8\uB798\uC11C \uBC31\uC5D4\uB4DC, \uD504\uB860\uD2B8\uC5D4\uB4DC, DB Schema\uC5D0 \uB300\uD55C \uCF54\uB4DC\uAC00 \uBAA8\uB450 \uD55C \uD3F4\uB354 \uC548\uC5D0 \uC788\uC5B4. \uADF8\uB798\uC11C \uC790\uBC14\uC2A4\uD06C\uB9BD\uD2B8, \uD0C0\uC785\uC2A4\uD06C\uB9BD\uD2B8, \uADF8\uB9AC\uACE0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC774\uD574\uB9CC \uC788\uB2E4\uBA74 \uAD6C\uBD84\uC9D3\uC9C0 \uC54A\uACE0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB2E4\uB294 \uC7A5\uC810\uC774 \uC788\uC5B4.
2413
-
2414
- \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2415
- - app
2412
+ \uB098\uB294 \uC880 \uB354 \uD6A8\uC728\uC801\uC73C\uB85C \uCF54\uB529\uC744 \uD558\uAE30 \uC704\uD574\uC11C \uC790\uCCB4 \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uC81C\uC791\uD588\uC5B4.
2413
+
2414
+ \uADF8\uB798\uC11C \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC744 \uD574\uC904\uD14C\uB2C8\uAE4C \uC798 \uC774\uD574\uD558\uB3C4\uB85D \uD574. \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uB294 next.js 13\uACFC nest.js, capacitor.js, nx, mongoDB \uAE30\uBC18\uC758 \uD504\uB860\uD2B8\uC5D4\uB4DC, \uC571, \uBC31\uC5D4\uB4DC \uD1B5\uD569 \uD504\uB808\uC784\uC6CC\uD06C\uC57C. \uADF8\uB798\uC11C \uBC31\uC5D4\uB4DC, \uD504\uB860\uD2B8\uC5D4\uB4DC, DB Schema\uC5D0 \uB300\uD55C \uCF54\uB4DC\uAC00 \uBAA8\uB450 \uD55C \uD3F4\uB354 \uC548\uC5D0 \uC788\uC5B4. \uADF8\uB798\uC11C \uC790\uBC14\uC2A4\uD06C\uB9BD\uD2B8, \uD0C0\uC785\uC2A4\uD06C\uB9BD\uD2B8, \uADF8\uB9AC\uACE0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC774\uD574\uB9CC \uC788\uB2E4\uBA74 \uAD6C\uBD84\uC9D3\uC9C0 \uC54A\uACE0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB2E4\uB294 \uC7A5\uC810\uC774 \uC788\uC5B4.
2415
+
2416
+
2417
+
2418
+ \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2419
+
2420
+ - app
2421
+
2416
2422
  - project1
2423
+
2417
2424
  - project2
2425
+
2418
2426
  - project3
2427
+
2419
2428
  - project4
2420
- - lib
2429
+
2430
+ - lib
2431
+
2421
2432
  - core
2433
+
2422
2434
  - external
2435
+
2423
2436
  - game
2437
+
2424
2438
  - mint
2439
+
2425
2440
  - platform
2441
+
2426
2442
  - shared
2443
+
2427
2444
  - social
2445
+
2428
2446
  - util
2429
- app\uC740 \uAC01 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uB294 \uACF3\uC774\uC57C
2430
- lib \uD558\uC704 \uD3F4\uB354\uB4E4\uC740 \uC5EC\uB7EC \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uACF5\uC6A9\uC73C\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uACA0\uB2E4 \uB77C\uACE0 \uD310\uB2E8\uD574\uC11C \uBD84\uB9AC\uD574\uB193\uC740 \uACF3\uC774\uC57C.
2431
- \uB2E4\uC74C\uC740 app/project \uB0B4\uBD80\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC904\uAC8C.
2432
-
2433
- project
2434
- - app
2447
+
2448
+ app\uC740 \uAC01 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uB294 \uACF3\uC774\uC57C
2449
+
2450
+ lib \uD558\uC704 \uD3F4\uB354\uB4E4\uC740 \uC5EC\uB7EC \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uACF5\uC6A9\uC73C\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uACA0\uB2E4 \uB77C\uACE0 \uD310\uB2E8\uD574\uC11C \uBD84\uB9AC\uD574\uB193\uC740 \uACF3\uC774\uC57C.
2451
+
2452
+ \uB2E4\uC74C\uC740 app/project \uB0B4\uBD80\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC904\uAC8C.
2453
+
2454
+
2455
+
2456
+ project
2457
+
2458
+ - app
2459
+
2435
2460
  - [lang]
2436
- - (projectName)
2437
- - (user)
2438
- - page.tsx
2439
- - layout.tsx
2440
- - (public)
2441
- - page.tsx
2442
- - layout.tsx
2443
- - (admin)
2444
- - page.tsx
2445
- - layout.tsx
2446
-
2447
- - lib
2461
+
2462
+ - (projectName)
2463
+
2464
+ - (user)
2465
+
2466
+ - page.tsx
2467
+
2468
+ - layout.tsx
2469
+
2470
+ - (public)
2471
+
2472
+ - page.tsx
2473
+
2474
+ - layout.tsx
2475
+
2476
+ - (admin)
2477
+
2478
+ - page.tsx
2479
+
2480
+ - layout.tsx
2481
+
2482
+
2483
+
2484
+ - lib
2485
+
2448
2486
  - dataName1
2487
+
2449
2488
  - dataName2
2489
+
2450
2490
  - dataName3
2491
+
2451
2492
  - dataName4
2493
+
2452
2494
  - dataName5
2495
+
2453
2496
  - dataName6
2497
+
2454
2498
  - dataName7
2455
-
2456
- app\uC740 \uC9C1\uC811\uC801\uC73C\uB85C \uC720\uC800\uAC00 \uBCF4\uB294 \uD398\uC774\uC9C0\uB97C \uC9DC\uB294 \uACF3\uC774\uC57C. \uD3F4\uB354 \uAD6C\uC870\uB294 next 13\uC758 app directory\uB97C \uB530\uB974\uACE0 \uC788\uC5B4.
2457
- public/page.tsx\uAC00 \uAC00\uC7A5 \uCD5C\uCD08\uB85C \uC811\uADFC\uB418\uB294 Index \uD398\uC774\uC9C0\uAC00 \uB420 \uAC70\uC57C.
2458
- \uC544\uB798\uB294 public/page.tsx\uC758 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2459
- \`\`\`
2460
- import {{ Image, Link }} from "@util/ui";
2461
- import {{ getSelf }} from "@akanjs/client";
2462
-
2463
- export default function Page() {{
2464
- const self = getSelf();
2465
- return (
2466
- <div className="relative w-full h-screen overflow-hidden flex items-center justify-center">
2467
- <Image
2468
- className="absolute left-0 right-0 top-0 bottom-0 w-full h-screen -z-50"
2469
- width={{1920}}
2470
- height={{1080}}
2471
- src="/back.jpg"
2472
- />
2473
- <div className="max-w-md bg-base-100/50 shadow-lg rounded-xl backdrop-blur-xs w-full py-8 px-16 flex flex-col items-center justify-center gap-3">
2474
- <h1 className="text-4xl mt-2"><%= project %></h1>
2475
- <h2 className="text-lg"><%= project %> description</h2>
2476
- <Link className="w-full" href={{self ? "/home" : "/signin"}}>
2477
- <button className="btn w-full btn-primary">Go to dashboard</button>
2478
- </Link>
2479
- </div>
2480
- </div>
2481
- );
2482
- }}
2483
- \`\`\`
2484
-
2485
- lib\uC740 \uC11C\uBE44\uC2A4\uB97C \uB9CC\uB4E4\uB2E4\uBCF4\uBA74 \uD544\uC694\uD55C \uB370\uC774\uD130\uB97C \uC815\uC758\uD558\uB294 \uACF3\uC774\uC57C.
2486
- \uB530\uB77C\uC11C dataName\uC740 DB\uC774\uB984. \uC989 \uB370\uC774\uD130\uBA85\uC744 \uB530\uB77C. \uB2E4\uB9CC \uD3F4\uB354 \uB0B4\uBD80\uC5D0\uB294 backend, frontend\uC5D0\uC11C \uD1B5\uD569\uC73C\uB85C \uC4F0\uB294 \uC18C\uC2A4\uCF54\uB4DC\uB4E4\uC774 \uC788\uC5B4.
2487
-
2488
- \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC758 \uD575\uC2EC\uC740 \uC815\uC758\uD55C \uBA54\uD0C0\uB370\uC774\uD130\uB4E4\uC744 \uC774\uC6A9\uD574\uC11C \uAC01 \uB370\uC774\uD130\uAC04\uC758 \uC5F0\uAD00\uC810\uC774\uB098, \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uBCF4\uACE0 \uBBF8\uB9AC \uC815\uB9AC\uB41C \uACB0\uACFC\uB97C \uB9CC\uB4E4\uC5B4\uC8FC\uACE0 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E0\uB2E4\uBA74 \uAC70\uC758 \uBAA8\uB450 \uD544\uC694\uD55C \uC791\uC5C5\uB4E4\uC744 \uBBF8\uB9AC \uC815\uB9AC\uD574\uB1A8\uC5B4. \uC608\uB97C \uB4E4\uC5B4 \uB370\uC774\uD130 \uD0C0\uC785\uC5D0 \uC774\uBBF8\uC9C0 \uD30C\uC77C\uC774 \uC788\uB2E4\uACE0 \uD55C\uB2E4\uBA74 \uBC31\uC5D4\uB4DC\uB97C \uD1B5\uD574 \uADF8 \uC774\uBBF8\uC9C0\uB97C \uC11C\uBC84\uC758 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uC800\uC7A5\uD558\uACE0 \uADF8 \uC800\uC7A5\uB41C \uD30C\uC77C\uC744 \uD2B9\uC815 db\uC5D0 id\uB97C \uCD94\uAC00\uD574\uC8FC\uB294 \uD568\uC218\uB4E4 \uAC19\uC740 \uAC83\uB4E4\uC740 \uC5B4\uB290 \uD504\uB85C\uC81D\uD2B8\uB358 \uAC04\uC5D0 \uBAA8\uB450 \uC0AC\uC6A9\uB418\uB294 \uBC29\uC2DD\uC774\uB77C\uACE0 \uD310\uB2E8\uD588\uC5B4. \uD558\uC9C0\uB9CC \uC6B0\uB9AC\uB294 \uD504\uB85C\uC81D\uD2B8\uB97C \uC791\uC5C5\uD560 \uB54C\uB9C8\uB2E4 \uC774 \uBD88\uD544\uC694\uD55C \uC791\uC5C5\uB4E4\uC744 \uD56D\uC0C1 \uB9CC\uB4E4\uACE0 \uD14C\uC2A4\uD2B8\uB97C \uD558\uB294 \uBD88\uD544\uC694\uD55C \uC77C\uB4E4\uC744 \uD558\uACE0\uC788\uC9C0. \uADF8\uB798\uC11C \uC6B0\uB9AC\uB294 \uAC01 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB9CC\uB4E4 \uB54C\uB9C8\uB2E4 \uD544\uC218\uB85C \uC788\uC5B4\uC57C\uD560 \uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC \uD504\uB85C\uC138\uC2A4\uB97C \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uD1B5\uD574 \uBBF8\uB9AC \uC815\uC758\uB41C \uC0C1\uD0DC\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC5B4.
2489
- \uACB0\uACFC\uC801\uC73C\uB85C \uC6B0\uB9B0 \uD544\uC694\uD558\uC9C0\uB9CC \uB9E4\uBC88 \uC791\uC5C5\uD558\uAE30\uC5D4 \uC190\uC774 \uB9CE\uC774\uAC00\uB294 \uC791\uC5C5\uB4E4\uC744 \uBBF8\uB9AC \uC815\uC758\uD574\uB1A8\uC5B4.
2490
-
2491
- \uB610\uD55C \uC6B0\uB9B0 CLI\uB97C \uD1B5\uD574\uC11C \uD2B9\uC815 \uD504\uB85C\uC81D\uD2B8 \uD3F4\uB354 \uD15C\uD50C\uB9BF\uC744 \uB9CC\uB4E4\uC5B4\uC8FC\uAC70\uB098, \uD2B9\uC815 \uBAA8\uB378\uC758 \uD544\uB4DC\uB4E4\uC744 \uB9CC\uB4E4 \uC218 \uC788\uB3C4\uB85D \uD574\uB1A8\uC5B4. Model\uC774\uB77C\uB294 \uBCC0\uC218\uC758 \uACB0\uACFC\uAC12\uC744 \uBC1B\uACE0 \uC800 \uD15C\uD50C\uB9BF\uC5D0 \uB9DE\uAC8C\uB054 \uC774\uB984\uC744 \uB123\uC5B4\uC8FC\uB294 \uAC70\uC9C0. \uB9CC\uC57D \uB0B4\uAC00 phone\uC774\uB77C\uB294 \uBCC0\uC218\uB97C \uB123\uC5C8\uB2E4\uBA74 \uC800 \uBAA8\uB378\uC5D0 Phone\uACFC \uAC19\uC740 \uACB0\uACFC\uAC12\uC73C\uB85C \uAC12\uC774 \uB4E4\uC5B4\uAC00\uAC8C \uB428\uC73C\uB85C\uC11C \uD15C\uD50C\uB9BF\uC774 \uC0DD\uC131\uB3FC. \uC774\uB294 \uC6B0\uB9AC\uAC00 \uC774\uBBF8 \uB9CC\uB4E4\uC5B4\uB193\uC740 \uCEE4\uB9E8\uB4DC\uAC00 \uC788\uC5B4.
2492
-
2493
- \uC608\uB97C \uB4E4\uC5B4 \uC5F0\uD544\uC774\uB77C\uB294 \uBAA8\uB378\uC744 \uCEE4\uB9E8\uB4DC\uB97C \uD1B5\uD574 \uC0DD\uC131\uD558\uBA74 \uC544\uB798\uC640 \uAC19\uC740 \uD30C\uC77C\uB4E4\uC774 \uC0DD\uC131\uB3FC.
2494
-
2495
- pencil
2496
- - pencil.constant.ts ( pencil\uC5D0 \uB300\uD55C db schema, query, sort \uAD6C\uBB38\uC744 \uC815\uC758 )
2497
- - pencil.document.ts ( model\uC5D0\uC11C \uC790\uC8FC \uC0AC\uC6A9\uD558\uB294 method, static function, middleware\uB85C \uAC04\uB2E8\uD55C db \uAD00\uB9AC \uD568\uC218\uB4F1\uC744 \uAD00\uB9AC\uD568.)
2498
- - pencil.dictionary.ts (\uB2E4\uAD6D\uC5B4\uB97C \uC704\uD574\uC11C schema field, enum, service name\uC758 \uB2E4\uAD6D\uC5B4 \uC815\uBCF4 \uB4F1\uC744 \uBAA8\uB450 \uAD00\uB9AC. )
2499
- - pencil.signal.ts (frontend\uC758 fetch\uB97C \uC5F4\uC5B4\uC8FC\uB294 \uC77C\uC885\uC758 \uCC3D\uAD6C, \uAD8C\uD55C\uAD00\uB9AC\uB4F1\uC744 \uD568 nestjs\uC758 resolver\uC640 \uC720\uC0AC )
2500
- - pencil.service.ts (\uC2E4\uC9C8\uC801\uC778 \uC11C\uBE44\uC2A4 \uCF54\uB4DC\uB97C \uC791\uC131\uD558\uB294 \uACF3. \uAC01\uC885 \uBE44\uC988\uB2C8\uC2A4 \uB85C\uC9C1\uC744 \uCC98\uB9AC\uD568.)
2501
- - pencil.store.ts (pencil field\uC5D0 \uB300\uD55C \uC0C1\uD0DC\uAD00\uB9AC \uC800\uC7A5\uC18C.)
2502
- - pencil.Zone.tsx (\uC544\uB798 Templete, Unit, Util, View, Util\uB4F1\uC744 \uC870\uD569\uD574\uC11C \uB2E4\uC74C \uB808\uBCA8 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC791\uC131\uD558\uB294 \uACF3 client component\uB85C \uC815\uC758\uB428. )
2503
- - pencil.Templete.tsx (\uC8FC\uB85C edit\uC5D0 \uC5F0\uAD00\uB41C \uCEF4\uD3EC\uB10C\uD2B8 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2504
- - pencil.Unit.tsx (list \uCC98\uB7FC \uBCF5\uC218\uAC1C\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2505
- - pencil.Util.tsx (Action \uBC84\uD2BC\uC744 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2506
- - pencil.View.tsx (\uB2E8\uC77C view \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2507
-
2508
-
2509
- \uC5EC\uAE30\uC11C constant\uC5D0 \uC815\uC758 \uB418\uC5B4\uC788\uB294 schema\uB97C \uAE30\uBCF8\uC73C\uB85C \uD574\uC11C \uAC01 document, dictionary, signal, service, store\uB97C \uC0DD\uC131\uD574.
2510
-
2511
- document, signal, service\uB294 \uBC31\uC5D4\uB4DC\uC640 \uC5F0\uAD00\uB418\uC5B4\uC788\uB294 \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2512
- \uC11C\uB85C\uAC04\uC758 \uAD00\uACC4\uB294 \uC8FC\uB85C signal\uC5D0\uC11C \uAC00\uC7A5 \uBA3C\uC800 \uC694\uCCAD\uC744 \uBC1B\uACE0 \uC774\uD6C4 \uB85C\uC9C1\uC758 \uBCF5\uC7A1\uB3C4\uC5D0 \uB530\uB77C\uC11C service\uB85C \uCC98\uB9AC\uD560 \uC9C0, docuemnt\uB85C \uCC98\uB9AC\uD560 \uC9C0\uB97C \uACB0\uC815\uD574.
2513
- signal - document
2514
- signal - service - document
2515
-
2516
- store\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC\uC5D0\uC11C \uC0C1\uD0DC\uAD00\uB9AC\uB97C \uD560 \uB54C \uC0AC\uC6A9\uB3FC.
2517
- \uC6B0\uB9AC\uB294 signal\uC758 \uCF54\uB4DC\uB85C \uB098\uC628 \uBA54\uD0C0\uB370\uC774\uD130\uB97C \uC774\uC6A9\uD574\uC11C store\uC5D0\uC11C \uD754\uD788 \uC0AC\uC6A9\uB420\uB9CC\uD55C \uD568\uC218\uB4E4\uC744 \uBBF8\uB9AC \uC815\uC758\uD558\uAC8C\uB054 \uB9CC\uB4E4\uC5C8\uC5B4.
2518
-
2519
- \uC774\uB807\uAC8C 11\uAC1C\uC758 \uD30C\uC77C\uB85C \uAD6C\uBD84\uD574\uC11C \uC815\uC758\uAC00 \uB3FC.
2520
- \uC9C0\uAE08\uBD80\uD134 \uD55C \uD30C\uC77C\uB4E4\uB9C8\uB2E4 \uC0C1\uC138\uD55C \uC124\uBA85\uC744 \uD574\uC904\uAC8C.
2521
-
2522
- model.constant.ts
2523
-
2524
- constant\uB294 \uAE30\uBCF8 \uC2A4\uD0A4\uB9C8\uAC00 \uAD6C\uC131\uB418\uB294 \uACF3\uC774\uC57C. \uADF8\uB798\uC11C \uC774 \uACF3\uC5D0\uC11C DB \uC2A4\uD0A4\uB9C8, \uCFFC\uB9AC, \uC815\uB82C \uAD6C\uBB38\uC744 \uC815\uC758\uD574.
2525
- \uC8FC\uC758\uD574\uC57C\uD560 \uAC74 decorator\uC5D0\uC11C \uC815\uC758\uD558\uB294 \uD0C0\uC785\uACFC \uC544\uB798\uC5D0 \uC815\uC758\uD558\uB294 \uD0C0\uC785\uC774 \uC57D\uAC04 \uB2E4\uB97C \uC218 \uC788\uC5B4
2526
- \uC608\uB97C \uB4E4\uC5B4 decorator\uC5D0\uC11C\uB294 Int\uB85C \uC815\uC758\uD558\uACE0 constant\uC5D0\uC11C\uB294 number\uB85C \uC815\uC758\uD574\uC57C\uD574.
2527
- \uCD94\uAC00\uB85C createdAt\uACFC updatedAt, status\uB294 \uAE30\uBCF8\uC801\uC73C\uB85C \uC0DD\uC131\uB418\uB294 \uD544\uB4DC\uC774\uB2C8\uAE4C \uB530\uB85C \uC815\uC758\uD558\uC9C0 \uC54A\uC544\uB3C4 \uB3FC.
2528
- \uC774\uB294 decorator\uC5D0\uC11C\uB294 GraphQL\uC5D0\uC11C \uC0AC\uC6A9\uD560 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uACE0 constant\uC5D0\uC11C\uB294 \uC2E4\uC81C \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uAC70\uC9C0.
2529
-
2530
- \`\`\`
2531
- import { enumOf, Int } from "@akanjs/base";
2532
- import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
2533
-
2534
- export const \${dict.Model}Statuses = ["active"] as const;
2535
- export type \${dict.Model}Status = (typeof \${dict.Model}Statuses)[number];
2536
-
2537
- //\uB370\uC774\uD130\uB97C \uB9CC\uB4E4 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uACF3
2538
- @Model.Input("\${dict.Model}Input")
2539
- export class \${dict.Model}Input {{
2540
- @Field.Prop(() => String)
2541
- field: string;
2542
-
2543
- @Field.Prop(() => Int, {{ nullable: true }})
2544
- fieldInt: number | null;
2545
-
2546
- @Field.Prop(() => Date, {{default: dayjs()}})
2547
- fieldInt: Dayjs;
2548
- }}
2549
-
2550
- //\uB370\uC774\uD130\uAC00 \uB9CC\uB4E4\uC5B4\uC9C4 \uC774\uD6C4 \uC0DD\uC131\uB418\uAC70\uB098 \uC800\uC7A5\uC73C\uB85C \uCD94\uAC00\uD560 \uC218 \uC788\uB294 \uACF3
2551
- @Model.Object("\${dict.Model}Object")
2552
- export class \${dict.Model}Object extends via(\${dict.Model}Input) {
2553
- @Field.Prop(() => String, {{ enum: \${dict.Model}Statuses, default: "active" }})
2554
- status: \${dict.Model}Status;
2555
- }}
2556
-
2557
- //\uB370\uC774\uD130\uB97C \uB9AC\uC2A4\uD2B8\uB85C \uBCF4\uC5EC\uC904 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130\uB9CC \uC81C\uACF5\uD558\uB294 \uACF3
2558
- @Model.Light("Light\${dict.Model}")
2559
- export class Light\${dict.Model} extends via(\${dict.Model}Object, [
2560
- "field",
2561
- "status",
2562
- ] as const) {}
2563
-
2564
- //\uCD5C\uC885 \uB370\uC774\uD130\uC758 Full \uD0C0\uC785\uC774 \uC815\uC758\uB418\uB294 \uACF3
2565
- @Model.Full("\${dict.Model}")
2566
- export class \${dict.Model} extends via(\${dict.Model}Object, Light\${dict.Model}) {}
2567
-
2568
- //\uB370\uC774\uD130\uC758 \uC778\uC0AC\uC774\uD2B8\uB97C \uCE21\uC815\uD558\uAE30 \uC704\uD574\uC11C \uD544\uC694\uD55C \uB370\uC774\uD130\uB97C \uC815\uC758\uD558\uB294 \uACF3
2569
- @Model.Insight("\${dict.Model}Insight")
2570
- export class \${dict.Model}Insight {{
2571
- @Field.Prop(() => Int, {{ default: 0, accumulate: {{ $sum: 1 }} }})
2572
- count: number;
2573
- }}
2574
-
2575
- //\uB370\uC774\uD130\uC758 \uD1B5\uACC4\uB97C \uACC4\uC0B0\uD558\uB294 \uACF3
2576
- @Model.Summary("\${dict.Model}Summary")
2577
- export class \${dict.Model}Summary {{
2578
- @Field.Prop(() => Int, {{ min: 0, default: 0, query: {{ status: {{}} }} }})
2579
- total\${dict.Model}: number;
2580
- }}
2581
-
2582
- @Model.Filter("\${dict.Model}Filter")
2583
- export class \${dict.Model}Filter extends sortOf(\${dict.Model}, {}) {}
2584
- \`\`\`
2585
-
2586
-
2587
- model.dictonary.ts
2588
- \`\`\`
2589
- import {
2590
- baseTrans,
2591
- getBaseSignalTrans,
2592
- ModelDictionary,
2593
- SignalDictionary,
2594
- SummaryDictionary,
2595
- } from "@akanjs/dictionary";
2596
-
2597
- import type { \${dict.Model}, \${dict.Model}Filter, \${dict.Model}Insight, \${dict.Model}Summary } from "./\${dict.model}.constant";
2598
- import type { \${dict.Model}Signal } from "./\${dict.model}.signal";
2599
-
2600
- const modelDictionary = {{
2601
- ...baseTrans,
2602
- modelName: ["\${dict.Model}", "\${dict.Model}"],
2603
- modelDesc: [
2604
- "\${dict.Model} description",
2605
- "\${dict.Model} \uC124\uBA85",
2606
- ],
2607
-
2608
- // * ==================== Model ==================== * //
2609
- field: ["Field", "\uD544\uB4DC"],
2610
- "desc-field": ["Field", "\uD544\uB4DC"],
2611
- // * ==================== Model ==================== * //
2612
-
2613
- // * ==================== Insight ==================== * //
2614
- count: ["Count", "\uAC1C\uC218"],
2615
- "desc-count": ["\${dict.Model} count in current query settting", "\uD604\uC7AC \uCFFC\uB9AC \uC124\uC815\uC5D0 \uB9DE\uB294 \${dict.Model} \uC218"],
2616
- // * ==================== Insight ==================== * //
2617
-
2618
- // * ==================== Filter ==================== * //
2619
- // * ==================== Filter ==================== * //
2620
-
2621
- // * ==================== Etc ==================== * //
2622
- "enum-status-active": ["Active", "\uD65C\uC131"],
2623
- "enumdesc-status-active": ["Active status", "\uD65C\uC131 \uC0C1\uD0DC"],
2624
- // * ==================== Etc ==================== * //
2625
- }} satisfies ModelDictionary<\${dict.Model}, \${dict.Model}Insight, typeof \${dict.Model}Sort>;
2626
-
2627
- export const \${dict.Model}SummaryDictionary = {{
2628
- // * ==================== Summary ==================== * //
2629
- total\${dict.Model}: ["Total \${dict.Model}", "\uCD1D \${dict.Model} \uC218"],
2630
- "desc-total\${dict.Model}": ["Total \${dict.Model} count in the database", "\uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC800\uC7A5\uB41C \uCD1D \${dict.Model} \uC218"],
2631
- // * ==================== Summary ==================== * //
2632
- }} satisfies SummaryDictionary<\${dict.Model}Summary>;
2633
-
2634
- const signalDictionary = {{
2635
- ...getBaseSignalTrans("\${dict.Model}" as const),
2636
- // * ==================== Endpoint ==================== * //
2637
- "api-\${dict.Model}ListInPublic": ["\${dict.Model} List In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uB9AC\uC2A4\uD2B8"],
2638
- "apidesc-\${dict.Model}ListInPublic": ["Get a list of public \${dict.Model}", "\uACF5\uAC1C\uB41C \${dict.Model}\uC758 \uB9AC\uC2A4\uD2B8\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4"],
2639
- "arg-\${dict.Model}ListInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2640
- "argdesc-\${dict.Model}ListInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2641
- "arg-\${dict.Model}ListInPublic-skip": ["Skip", "\uAC74\uB108\uB6F0\uAE30"],
2642
- "argdesc-\${dict.Model}ListInPublic-skip": ["Number of items to skip", "\uAC74\uB108\uB6F8 \uC544\uC774\uD15C \uC218"],
2643
- "arg-\${dict.Model}ListInPublic-limit": ["Limit", "\uC81C\uD55C"],
2644
- "argdesc-\${dict.Model}ListInPublic-limit": ["Maximum number of items to return", "\uBC18\uD658\uD560 \uCD5C\uB300 \uC544\uC774\uD15C \uC218"],
2645
- "arg-\${dict.Model}ListInPublic-sort": ["Sort", "\uC815\uB82C"],
2646
- "argdesc-\${dict.Model}ListInPublic-sort": ["Sort order of the items", "\uC544\uC774\uD15C\uC758 \uC815\uB82C \uC21C\uC11C"],
2647
-
2648
- "api-\${dict.Model}InsightInPublic": ["\${dict.Model} Insight In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uC778\uC0AC\uC774\uD2B8"],
2649
- "apidesc-\${dict.Model}InsightInPublic": [
2650
- "Get insight data for public \${dict.Model}",
2651
- "\uACF5\uAC1C\uB41C \${dict.Model}\uC5D0 \uB300\uD55C \uC778\uC0AC\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4",
2652
- ],
2653
- "arg-\${dict.Model}InsightInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2654
- "argdesc-\${dict.Model}InsightInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2655
- // * ==================== Endpoint ==================== * //
2656
- }} satisfies SignalDictionary<\${dict.Model}Signal, \${dict.Model}>;
2657
- \`\`\`
2658
- export const \${dict.model}Dictionary = {{ ...modelDictionary, ...signalDictionary }};
2659
-
2660
-
2661
-
2662
- model.document.ts
2663
- \`\`\`
2664
- import { beyond, by, Database, into, type SchemaOf } from "@akanjs/document";
2665
-
2666
- import { cnst } from "../cnst";
2667
- @Database.Input(() => cnst.\${dict.Model}Input)
2668
- export class \${dict.Model}Input extends by(cnst.\${dict.Model}Input) {}
2669
-
2670
- @Database.Document(() => cnst.\${dict.Model})
2671
- export class \${dict.Model} extends by(cnst.\${dict.Model}) {}
2672
-
2673
- @Database.Model(() => cnst.\${dict.Model})
2674
- export class \${dict.Model}Model extends into(\${dict.Model}, cnst.\${dict.Model}Cnst) {
2675
- async getSummary(): Promise<cnst.\${dict.Model}Summary> {
2676
- return {
2677
- ...(await this.getDefaultSummary()),
2678
- };
2679
- }
2680
- }
2681
-
2682
- @Database.Middleware(() => cnst.\${dict.Model})
2683
- export class \${dict.Model}Middleware extends beyond(\${dict.Model}Model, \${dict.Model}) {
2684
- onSchema(schema: SchemaOf<\${dict.Model}Model, \${dict.Model}>) {
2685
- // schema.index({ status: 1 })
2686
- }
2687
- }
2688
- \`\`\`
2689
-
2690
-
2691
- model.signal.ts
2692
- \`\`\`
2693
- import { Int } from "@akanjs/base";
2694
- import { SortOf } from "@akanjs/constant";
2695
- import { Arg, DbSignal, Mutation, Query, resolve, Signal } from "@akanjs/signal";
2696
-
2697
- import { cnst, Srvs } from "../cnst";
2698
-
2699
- @Signal(() => cnst.\${dict.Model})
2700
- export class \${dict.Model}Signal extends DbSignal(cnst.\${dict.model}Cnst, Srvs, {
2701
- guards: { get: Query.Public, cru: Mutation.Public },
2702
- }) {
2703
- // * /////////////////////////////////////
2704
- // * Public Slice
2705
- @Query.Public(() => [cnst.\${dict.Model}])
2706
- async \${dict.model}ListInPublic(
2707
- @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null,
2708
- @Arg.Query("skip", () => Int, { nullable: true }) skip: number | null,
2709
- @Arg.Query("limit", () => Int, { nullable: true }) limit: number | null,
2710
- @Arg.Query("sort", () => String, { nullable: true }) sort: SortOf<cnst.\${dict.Model}Filter> | null
2711
- ) {
2712
- const \${dict.models} = await this.\${dict.model}Service.listByStatuses(statuses, { skip, limit, sort });
2713
- return resolve<cnst.\${dict.Model}[]>(\${dict.models});
2714
- }
2715
- @Query.Public(() => cnst.\${dict.Model}Insight)
2716
- async \${dict.model}InsightInPublic(
2717
- @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null
2718
- ) {
2719
- const \${dict.model}Insight = await this.\${dict.model}Service.insightByStatuses(statuses);
2720
- return resolve<cnst.\${dict.Model}Insight>(\${dict.model}Insight);
2721
- }
2722
- // * Public Slice
2723
- // * /////////////////////////////////////
2724
- }
2725
- \`\`\`
2726
-
2727
-
2728
- model.service.ts
2729
- \`\`\`
2730
- import { DbService, Service } from "@akanjs/service";
2731
-
2732
- import { cnst } from "../cnst";
2733
- import * as db from "../db";
2734
-
2735
- @Service("\${dict.Model}Service")
2736
- export class \${dict.Model}Service extends DbService(db.\${dict.Model}Db) {
2737
- async summarize(): Promise<cnst.\${dict.Model}Summary> {
2738
- return {
2739
- ...(await this.\${dict.Model}Model.getSummary()),
2740
- };
2741
- }
2742
- }
2743
- \`\`\`
2744
-
2745
-
2746
- model.store.ts
2747
- \`\`\`
2748
- import { stateOf, Store } from "@akanjs/store";
2749
-
2750
- import { cnst } from "../cnst";
2751
- import { fetch } from "../fetch";
2752
-
2753
- @Store(() => cnst.\${dict.Model})
2754
- export class \${dict.Model}Store extends stateOf(fetch.\${dict.model}Gql, {
2755
- // state
2756
- }) {
2757
- // action
2758
- }
2759
- \`\`\`
2760
-
2761
-
2762
- model.Zone.tsx
2763
- \`\`\`
2764
- "use client";
2765
- import { Data, Load } from "@shared/ui";
2766
- import { ModelsProps } from "@akanjs/client";
2767
- import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
2768
- import { ClientInit, ClientView, DefaultOf } from "@akanjs/signal";
2769
-
2770
- export const Admin = ({ sliceName = "\${dict.model}", init, query }: ModelsProps<cnst.\${dict.Model}>>) => {
2771
- return (
2772
- <Data.ListContainer
2773
- init={init}
2774
- query={query}
2775
- sliceName={sliceName}
2776
- renderItem={\${dict.Model}.Unit.Card}
2777
- renderDashboard={\${dict.Model}.Util.Stat}
2778
- renderInsight={\${dict.Model}.Util.Insight}
2779
- renderTemplate={\${dict.Model}.Template.General}
2780
- renderTitle={(\${dict.model}: DefaultOf<cnst.\${dict.Model}>>) => \`\${dict.Model} - \${\${dict.model}.id ? \${dict.model}.id : "New"}\`}
2781
- renderView={(\${dict.model}: cnst.\${dict.Model}>) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />}
2782
- columns={[
2783
- "id",
2784
- "status",
2785
- "createdAt",
2786
- "updatedAt",
2787
- ]}
2788
- actions={(\${dict.model}: cnst.Light\${dict.Model}, idx) => ["remove", "edit", "view"]}
2789
- />
2790
- );
2791
- };
2792
-
2793
- interface CardProps {
2794
- className?: string;
2795
- init: ClientInit<"\${dict.model}", cnst.Light\${dict.Model}>;
2796
- }
2797
- export const Card = ({ className, init }: CardProps) => {
2798
- return (
2799
- <Load.Units
2800
- className={className}
2801
- init={init}
2802
- renderItem={(\${dict.model}: cnst.Light\${dict.Model}) => (
2803
- <\${dict.Model}.Unit.Card key={\${dict.model}.id} href={\`/\${dict.model}/\${\${dict.model}.id}\`} \${dict.model}={\${dict.model}} />
2804
- )}
2805
- />
2806
- );
2807
- };
2808
-
2809
- interface ViewProps {
2810
- className?: string;
2811
- view: ClientView<"\${dict.model}", cnst.\${dict.Model}>;
2812
- }
2813
- export const View = ({ view }: ViewProps) => {
2814
- return <Load.View view={view} renderView={(\${dict.model}) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />} />;
2815
- };
2816
- \`\`\`
2817
-
2818
- model.Templete.tsx
2819
- \`\`\`
2820
- "use client";
2821
- import { cnst, st, usePage } from "@\${dict.appName}/client";
2822
- import { Field } from "@shared/ui";
2823
- import { Layout } from "@util/ui";
2824
-
2825
- interface \${dict.Model}EditProps {
2826
- \${dict.model}Id?: string | null;
2827
- }
2828
-
2829
- export const General = ({ \${dict.model}Id = undefined }: \${dict.Model}EditProps) => {
2830
- const \${dict.model}Form = st.use.\${dict.model}Form();
2831
- const { l } = usePage();
2832
- return (
2833
- <Layout.Template>
2834
- <Field.Text
2835
- label={l.field("\${dict.model}", "id")}
2836
- desc={l.desc("\${dict.model}", "id")}
2837
- value={\${dict.model}Form.id}
2838
- onChange={st.do.setIdOn\${dict.Model}}
2839
- />
2840
- </Layout.Template>
2841
- );
2842
- };
2843
- \`\`\`
2844
-
2845
-
2846
- model.Unit.tsx
2847
- \`\`\`
2848
- import { ModelProps } from "@akanjs/client";
2849
- import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
2850
- import { Link } from "@util/ui";
2851
-
2852
- export const Card = ({ \${dict.model}, href }: ModelProps<"\${dict.model}", cnst.Light\${dict.Model}>>) => {
2853
- return (
2854
- <Link href={href} className="animate-fadeIn w-full h-36 flex rounded-lg shadow-sm hover:shadow-lg duration-300">
2855
- <div>{\${dict.model}.id}</div>
2856
- </Link>
2857
- );
2858
- };
2859
- \`\`\`
2860
-
2861
-
2862
- model.Util.tsx
2863
- \`\`\`
2864
- "use client";
2865
- import { ModelDashboardProps, ModelInsightProps } from "@akanjs/client";
2866
- import { getQueryMap } from "@akanjs/constant";
2867
- import { cnst } from "@\${dict.appName}/client";
2868
- import { Data } from "@shared/ui";
2869
-
2870
- export const Stat = ({
2871
- className,
2872
- summary,
2873
- sliceName = "\${dict.model}",
2874
- queryMap = getQueryMap(cnst.\${dict.Model}Summary),
2875
- hidePresents,
2876
- }: ModelDashboardProps<cnst.Summary>) => {
2877
- return (
2878
- <Data.Dashboard
2879
- className={className}
2880
- summary={summary}
2881
- sliceName={sliceName}
2882
- queryMap={queryMap}
2883
- columns={["total\${dict.Model}"]}
2884
- hidePresents={hidePresents}
2885
- />
2886
- );
2887
- };
2888
-
2889
- export const Insight = ({
2890
- className,
2891
- insight,
2892
- sliceName = "\${dict.model}",
2893
- }: ModelInsightProps<cnst.\${dict.Model}Insight>) => {
2894
- return (
2895
- <Data.Insight
2896
- className={className}
2897
- insight={insight}
2898
- sliceName={sliceName}
2899
- columns={["count"]}
2900
- />
2901
- );
2902
- };
2903
- \`\`\`
2904
-
2905
-
2906
- model.View.tsx
2907
- \`\`\`
2908
- import { clsx } from "@akanjs/client";
2909
- import { cnst } from "@\${dict.appName}/client";
2910
- import { Image } from "@util/ui";
2911
-
2912
- interface \${dict.Model}ViewProps {
2913
- className?: string;
2914
- \${dict.model}: cnst.\${dict.Model};
2915
- self?: { id?: string } | null;
2916
- }
2917
-
2918
- export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewProps) => {
2919
- return (
2920
- <div className={clsx(className, "animate-fadeIn w-full")}>
2921
- <div>{\${dict.model}.id}</div>
2922
- </div>
2923
- );
2924
- };
2925
- \`\`\`
2926
- \uC774\uB7F0\uC2DD\uC73C\uB85C \uC6B0\uB9AC\uAC00 \uC9C1\uC811 \uB9CC\uB4E0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uAE30\uBC18\uD574\uC11C db\uC640 \uC11C\uBE44\uC2A4 \uC2A4\uD1A0\uC5B4\uAE4C\uC9C0 \uBAA8\uB450 \uC5F0\uB3D9\uD574\uC11C \uD558\uB098\uC758 \uBAA8\uB378\uC5D0 \uB9DE\uAC8C\uB054 \uBAA8\uB4C8\uC744 \uD55C \uD3F4\uB354\uC5D0\uC11C \uC791\uC5C5\uD560 \uC218 \uC788\uAC8C\uB054 \uAD6C\uC870\uB97C \uB9CC\uB4E4\uC5C8\uC5B4.
2927
-
2928
- \uC77C\uB2E8 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC740 \uC774 \uC815\uB3C4\uB85C \uD558\uACE0 \uC774 \uC815\uBCF4\uB4E4\uC744 \uAE30\uBC18\uC73C\uB85C \uB0B4\uAC00 \uC6D0\uD558\uB294 \uC694\uAD6C\uB97C \uB4E4\uC5B4\uC918.
2929
- `;
2499
+
2500
+
2501
+
2502
+ app\uC740 \uC9C1\uC811\uC801\uC73C\uB85C \uC720\uC800\uAC00 \uBCF4\uB294 \uD398\uC774\uC9C0\uB97C \uC9DC\uB294 \uACF3\uC774\uC57C. \uD3F4\uB354 \uAD6C\uC870\uB294 next 13\uC758 app directory\uB97C \uB530\uB974\uACE0 \uC788\uC5B4.
2503
+
2504
+ public/page.tsx\uAC00 \uAC00\uC7A5 \uCD5C\uCD08\uB85C \uC811\uADFC\uB418\uB294 Index \uD398\uC774\uC9C0\uAC00 \uB420 \uAC70\uC57C.
2505
+
2506
+ \uC544\uB798\uB294 public/page.tsx\uC758 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2507
+
2508
+ \`\`\`
2509
+
2510
+ import {{ Image, Link }} from "@util/ui";
2511
+
2512
+ import {{ getSelf }} from "@akanjs/client";
2513
+
2514
+
2515
+
2516
+ export default function Page() {{
2517
+
2518
+ const self = getSelf();
2519
+
2520
+ return (
2521
+
2522
+ <div className="relative w-full h-screen overflow-hidden flex items-center justify-center">
2523
+
2524
+ <Image
2525
+
2526
+ className="absolute left-0 right-0 top-0 bottom-0 w-full h-screen -z-50"
2527
+
2528
+ width={{1920}}
2529
+
2530
+ height={{1080}}
2531
+
2532
+ src="/back.jpg"
2533
+
2534
+ />
2535
+
2536
+ <div className="max-w-md bg-base-100/50 shadow-lg rounded-xl backdrop-blur-xs w-full py-8 px-16 flex flex-col items-center justify-center gap-3">
2537
+
2538
+ <h1 className="text-4xl mt-2"><%= project %></h1>
2539
+
2540
+ <h2 className="text-lg"><%= project %> description</h2>
2541
+
2542
+ <Link className="w-full" href={{self ? "/home" : "/signin"}}>
2543
+
2544
+ <button className="btn w-full btn-primary">Go to dashboard</button>
2545
+
2546
+ </Link>
2547
+
2548
+ </div>
2549
+
2550
+ </div>
2551
+
2552
+ );
2553
+
2554
+ }}
2555
+
2556
+ \`\`\`
2557
+
2558
+
2559
+
2560
+ lib\uC740 \uC11C\uBE44\uC2A4\uB97C \uB9CC\uB4E4\uB2E4\uBCF4\uBA74 \uD544\uC694\uD55C \uB370\uC774\uD130\uB97C \uC815\uC758\uD558\uB294 \uACF3\uC774\uC57C.
2561
+
2562
+ \uB530\uB77C\uC11C dataName\uC740 DB\uC774\uB984. \uC989 \uB370\uC774\uD130\uBA85\uC744 \uB530\uB77C. \uB2E4\uB9CC \uD3F4\uB354 \uB0B4\uBD80\uC5D0\uB294 backend, frontend\uC5D0\uC11C \uD1B5\uD569\uC73C\uB85C \uC4F0\uB294 \uC18C\uC2A4\uCF54\uB4DC\uB4E4\uC774 \uC788\uC5B4.
2563
+
2564
+
2565
+
2566
+ \uC6B0\uB9AC \uD504\uB808\uC784\uC6CC\uD06C\uC758 \uD575\uC2EC\uC740 \uC815\uC758\uD55C \uBA54\uD0C0\uB370\uC774\uD130\uB4E4\uC744 \uC774\uC6A9\uD574\uC11C \uAC01 \uB370\uC774\uD130\uAC04\uC758 \uC5F0\uAD00\uC810\uC774\uB098, \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uBCF4\uACE0 \uBBF8\uB9AC \uC815\uB9AC\uB41C \uACB0\uACFC\uB97C \uB9CC\uB4E4\uC5B4\uC8FC\uACE0 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E0\uB2E4\uBA74 \uAC70\uC758 \uBAA8\uB450 \uD544\uC694\uD55C \uC791\uC5C5\uB4E4\uC744 \uBBF8\uB9AC \uC815\uB9AC\uD574\uB1A8\uC5B4. \uC608\uB97C \uB4E4\uC5B4 \uB370\uC774\uD130 \uD0C0\uC785\uC5D0 \uC774\uBBF8\uC9C0 \uD30C\uC77C\uC774 \uC788\uB2E4\uACE0 \uD55C\uB2E4\uBA74 \uBC31\uC5D4\uB4DC\uB97C \uD1B5\uD574 \uADF8 \uC774\uBBF8\uC9C0\uB97C \uC11C\uBC84\uC758 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uC800\uC7A5\uD558\uACE0 \uADF8 \uC800\uC7A5\uB41C \uD30C\uC77C\uC744 \uD2B9\uC815 db\uC5D0 id\uB97C \uCD94\uAC00\uD574\uC8FC\uB294 \uD568\uC218\uB4E4 \uAC19\uC740 \uAC83\uB4E4\uC740 \uC5B4\uB290 \uD504\uB85C\uC81D\uD2B8\uB358 \uAC04\uC5D0 \uBAA8\uB450 \uC0AC\uC6A9\uB418\uB294 \uBC29\uC2DD\uC774\uB77C\uACE0 \uD310\uB2E8\uD588\uC5B4. \uD558\uC9C0\uB9CC \uC6B0\uB9AC\uB294 \uD504\uB85C\uC81D\uD2B8\uB97C \uC791\uC5C5\uD560 \uB54C\uB9C8\uB2E4 \uC774 \uBD88\uD544\uC694\uD55C \uC791\uC5C5\uB4E4\uC744 \uD56D\uC0C1 \uB9CC\uB4E4\uACE0 \uD14C\uC2A4\uD2B8\uB97C \uD558\uB294 \uBD88\uD544\uC694\uD55C \uC77C\uB4E4\uC744 \uD558\uACE0\uC788\uC9C0. \uADF8\uB798\uC11C \uC6B0\uB9AC\uB294 \uAC01 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB9CC\uB4E4 \uB54C\uB9C8\uB2E4 \uD544\uC218\uB85C \uC788\uC5B4\uC57C\uD560 \uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC \uD504\uB85C\uC138\uC2A4\uB97C \uD504\uB808\uC784\uC6CC\uD06C\uB97C \uD1B5\uD574 \uBBF8\uB9AC \uC815\uC758\uB41C \uC0C1\uD0DC\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC5B4.
2567
+
2568
+ \uACB0\uACFC\uC801\uC73C\uB85C \uC6B0\uB9B0 \uD544\uC694\uD558\uC9C0\uB9CC \uB9E4\uBC88 \uC791\uC5C5\uD558\uAE30\uC5D4 \uC190\uC774 \uB9CE\uC774\uAC00\uB294 \uC791\uC5C5\uB4E4\uC744 \uBBF8\uB9AC \uC815\uC758\uD574\uB1A8\uC5B4.
2569
+
2570
+
2571
+
2572
+ \uB610\uD55C \uC6B0\uB9B0 CLI\uB97C \uD1B5\uD574\uC11C \uD2B9\uC815 \uD504\uB85C\uC81D\uD2B8 \uD3F4\uB354 \uD15C\uD50C\uB9BF\uC744 \uB9CC\uB4E4\uC5B4\uC8FC\uAC70\uB098, \uD2B9\uC815 \uBAA8\uB378\uC758 \uD544\uB4DC\uB4E4\uC744 \uB9CC\uB4E4 \uC218 \uC788\uB3C4\uB85D \uD574\uB1A8\uC5B4. Model\uC774\uB77C\uB294 \uBCC0\uC218\uC758 \uACB0\uACFC\uAC12\uC744 \uBC1B\uACE0 \uC800 \uD15C\uD50C\uB9BF\uC5D0 \uB9DE\uAC8C\uB054 \uC774\uB984\uC744 \uB123\uC5B4\uC8FC\uB294 \uAC70\uC9C0. \uB9CC\uC57D \uB0B4\uAC00 phone\uC774\uB77C\uB294 \uBCC0\uC218\uB97C \uB123\uC5C8\uB2E4\uBA74 \uC800 \uBAA8\uB378\uC5D0 Phone\uACFC \uAC19\uC740 \uACB0\uACFC\uAC12\uC73C\uB85C \uAC12\uC774 \uB4E4\uC5B4\uAC00\uAC8C \uB428\uC73C\uB85C\uC11C \uD15C\uD50C\uB9BF\uC774 \uC0DD\uC131\uB3FC. \uC774\uB294 \uC6B0\uB9AC\uAC00 \uC774\uBBF8 \uB9CC\uB4E4\uC5B4\uB193\uC740 \uCEE4\uB9E8\uB4DC\uAC00 \uC788\uC5B4.
2573
+
2574
+
2575
+
2576
+ \uC608\uB97C \uB4E4\uC5B4 \uC5F0\uD544\uC774\uB77C\uB294 \uBAA8\uB378\uC744 \uCEE4\uB9E8\uB4DC\uB97C \uD1B5\uD574 \uC0DD\uC131\uD558\uBA74 \uC544\uB798\uC640 \uAC19\uC740 \uD30C\uC77C\uB4E4\uC774 \uC0DD\uC131\uB3FC.
2577
+
2578
+
2579
+
2580
+ pencil
2581
+
2582
+ - pencil.constant.ts ( pencil\uC5D0 \uB300\uD55C db schema, query, sort \uAD6C\uBB38\uC744 \uC815\uC758 )
2583
+
2584
+ - pencil.document.ts ( model\uC5D0\uC11C \uC790\uC8FC \uC0AC\uC6A9\uD558\uB294 method, static function, middleware\uB85C \uAC04\uB2E8\uD55C db \uAD00\uB9AC \uD568\uC218\uB4F1\uC744 \uAD00\uB9AC\uD568.)
2585
+
2586
+ - pencil.dictionary.ts (\uB2E4\uAD6D\uC5B4\uB97C \uC704\uD574\uC11C schema field, enum, service name\uC758 \uB2E4\uAD6D\uC5B4 \uC815\uBCF4 \uB4F1\uC744 \uBAA8\uB450 \uAD00\uB9AC. )
2587
+
2588
+ - pencil.signal.ts (frontend\uC758 fetch\uB97C \uC5F4\uC5B4\uC8FC\uB294 \uC77C\uC885\uC758 \uCC3D\uAD6C, \uAD8C\uD55C\uAD00\uB9AC\uB4F1\uC744 \uD568 nestjs\uC758 resolver\uC640 \uC720\uC0AC )
2589
+
2590
+ - pencil.service.ts (\uC2E4\uC9C8\uC801\uC778 \uC11C\uBE44\uC2A4 \uCF54\uB4DC\uB97C \uC791\uC131\uD558\uB294 \uACF3. \uAC01\uC885 \uBE44\uC988\uB2C8\uC2A4 \uB85C\uC9C1\uC744 \uCC98\uB9AC\uD568.)
2591
+
2592
+ - pencil.store.ts (pencil field\uC5D0 \uB300\uD55C \uC0C1\uD0DC\uAD00\uB9AC \uC800\uC7A5\uC18C.)
2593
+
2594
+ - pencil.Zone.tsx (\uC544\uB798 Templete, Unit, Util, View, Util\uB4F1\uC744 \uC870\uD569\uD574\uC11C \uB2E4\uC74C \uB808\uBCA8 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC791\uC131\uD558\uB294 \uACF3 client component\uB85C \uC815\uC758\uB428. )
2595
+
2596
+ - pencil.Templete.tsx (\uC8FC\uB85C edit\uC5D0 \uC5F0\uAD00\uB41C \uCEF4\uD3EC\uB10C\uD2B8 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2597
+
2598
+ - pencil.Unit.tsx (list \uCC98\uB7FC \uBCF5\uC218\uAC1C\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2599
+
2600
+ - pencil.Util.tsx (Action \uBC84\uD2BC\uC744 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2601
+
2602
+ - pencil.View.tsx (\uB2E8\uC77C view \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2603
+
2604
+
2605
+
2606
+
2607
+ \uC5EC\uAE30\uC11C constant\uC5D0 \uC815\uC758 \uB418\uC5B4\uC788\uB294 schema\uB97C \uAE30\uBCF8\uC73C\uB85C \uD574\uC11C \uAC01 document, dictionary, signal, service, store\uB97C \uC0DD\uC131\uD574.
2608
+
2609
+
2610
+
2611
+ document, signal, service\uB294 \uBC31\uC5D4\uB4DC\uC640 \uC5F0\uAD00\uB418\uC5B4\uC788\uB294 \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2612
+
2613
+ \uC11C\uB85C\uAC04\uC758 \uAD00\uACC4\uB294 \uC8FC\uB85C signal\uC5D0\uC11C \uAC00\uC7A5 \uBA3C\uC800 \uC694\uCCAD\uC744 \uBC1B\uACE0 \uC774\uD6C4 \uB85C\uC9C1\uC758 \uBCF5\uC7A1\uB3C4\uC5D0 \uB530\uB77C\uC11C service\uB85C \uCC98\uB9AC\uD560 \uC9C0, docuemnt\uB85C \uCC98\uB9AC\uD560 \uC9C0\uB97C \uACB0\uC815\uD574.
2614
+
2615
+ signal - document
2616
+
2617
+ signal - service - document
2618
+
2619
+
2620
+
2621
+ store\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC\uC5D0\uC11C \uC0C1\uD0DC\uAD00\uB9AC\uB97C \uD560 \uB54C \uC0AC\uC6A9\uB3FC.
2622
+
2623
+ \uC6B0\uB9AC\uB294 signal\uC758 \uCF54\uB4DC\uB85C \uB098\uC628 \uBA54\uD0C0\uB370\uC774\uD130\uB97C \uC774\uC6A9\uD574\uC11C store\uC5D0\uC11C \uD754\uD788 \uC0AC\uC6A9\uB420\uB9CC\uD55C \uD568\uC218\uB4E4\uC744 \uBBF8\uB9AC \uC815\uC758\uD558\uAC8C\uB054 \uB9CC\uB4E4\uC5C8\uC5B4.
2624
+
2625
+
2626
+
2627
+ \uC774\uB807\uAC8C 11\uAC1C\uC758 \uD30C\uC77C\uB85C \uAD6C\uBD84\uD574\uC11C \uC815\uC758\uAC00 \uB3FC.
2628
+
2629
+ \uC9C0\uAE08\uBD80\uD134 \uD55C \uD30C\uC77C\uB4E4\uB9C8\uB2E4 \uC0C1\uC138\uD55C \uC124\uBA85\uC744 \uD574\uC904\uAC8C.
2630
+
2631
+
2632
+
2633
+ model.constant.ts
2634
+
2635
+
2636
+
2637
+ constant\uB294 \uAE30\uBCF8 \uC2A4\uD0A4\uB9C8\uAC00 \uAD6C\uC131\uB418\uB294 \uACF3\uC774\uC57C. \uADF8\uB798\uC11C \uC774 \uACF3\uC5D0\uC11C DB \uC2A4\uD0A4\uB9C8, \uCFFC\uB9AC, \uC815\uB82C \uAD6C\uBB38\uC744 \uC815\uC758\uD574.
2638
+
2639
+ \uC8FC\uC758\uD574\uC57C\uD560 \uAC74 decorator\uC5D0\uC11C \uC815\uC758\uD558\uB294 \uD0C0\uC785\uACFC \uC544\uB798\uC5D0 \uC815\uC758\uD558\uB294 \uD0C0\uC785\uC774 \uC57D\uAC04 \uB2E4\uB97C \uC218 \uC788\uC5B4
2640
+
2641
+ \uC608\uB97C \uB4E4\uC5B4 decorator\uC5D0\uC11C\uB294 Int\uB85C \uC815\uC758\uD558\uACE0 constant\uC5D0\uC11C\uB294 number\uB85C \uC815\uC758\uD574\uC57C\uD574.
2642
+
2643
+ \uCD94\uAC00\uB85C createdAt\uACFC updatedAt, status\uB294 \uAE30\uBCF8\uC801\uC73C\uB85C \uC0DD\uC131\uB418\uB294 \uD544\uB4DC\uC774\uB2C8\uAE4C \uB530\uB85C \uC815\uC758\uD558\uC9C0 \uC54A\uC544\uB3C4 \uB3FC.
2644
+
2645
+ \uC774\uB294 decorator\uC5D0\uC11C\uB294 GraphQL\uC5D0\uC11C \uC0AC\uC6A9\uD560 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uACE0 constant\uC5D0\uC11C\uB294 \uC2E4\uC81C \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uAC70\uC9C0.
2646
+
2647
+
2648
+
2649
+ \`\`\`
2650
+
2651
+ import { enumOf, Int } from "@akanjs/base";
2652
+
2653
+ import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
2654
+
2655
+
2656
+
2657
+ export const \${dict.Model}Statuses = ["active"] as const;
2658
+
2659
+ export type \${dict.Model}Status = (typeof \${dict.Model}Statuses)[number];
2660
+
2661
+
2662
+
2663
+ //\uB370\uC774\uD130\uB97C \uB9CC\uB4E4 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uACF3
2664
+
2665
+ @Model.Input("\${dict.Model}Input")
2666
+
2667
+ export class \${dict.Model}Input {{
2668
+
2669
+ @Field.Prop(() => String)
2670
+
2671
+ field: string;
2672
+
2673
+
2674
+
2675
+ @Field.Prop(() => Int, {{ nullable: true }})
2676
+
2677
+ fieldInt: number | null;
2678
+
2679
+
2680
+
2681
+ @Field.Prop(() => Date, {{default: dayjs()}})
2682
+
2683
+ fieldInt: Dayjs;
2684
+
2685
+ }}
2686
+
2687
+
2688
+
2689
+ //\uB370\uC774\uD130\uAC00 \uB9CC\uB4E4\uC5B4\uC9C4 \uC774\uD6C4 \uC0DD\uC131\uB418\uAC70\uB098 \uC800\uC7A5\uC73C\uB85C \uCD94\uAC00\uD560 \uC218 \uC788\uB294 \uACF3
2690
+
2691
+ @Model.Object("\${dict.Model}Object")
2692
+
2693
+ export class \${dict.Model}Object extends via(\${dict.Model}Input) {
2694
+
2695
+ @Field.Prop(() => String, {{ enum: \${dict.Model}Statuses, default: "active" }})
2696
+
2697
+ status: \${dict.Model}Status;
2698
+
2699
+ }}
2700
+
2701
+
2702
+
2703
+ //\uB370\uC774\uD130\uB97C \uB9AC\uC2A4\uD2B8\uB85C \uBCF4\uC5EC\uC904 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130\uB9CC \uC81C\uACF5\uD558\uB294 \uACF3
2704
+
2705
+ @Model.Light("Light\${dict.Model}")
2706
+
2707
+ export class Light\${dict.Model} extends via(\${dict.Model}Object, [
2708
+
2709
+ "field",
2710
+
2711
+ "status",
2712
+
2713
+ ] as const) {}
2714
+
2715
+
2716
+
2717
+ //\uCD5C\uC885 \uB370\uC774\uD130\uC758 Full \uD0C0\uC785\uC774 \uC815\uC758\uB418\uB294 \uACF3
2718
+
2719
+ @Model.Full("\${dict.Model}")
2720
+
2721
+ export class \${dict.Model} extends via(\${dict.Model}Object, Light\${dict.Model}) {}
2722
+
2723
+
2724
+
2725
+ //\uB370\uC774\uD130\uC758 \uC778\uC0AC\uC774\uD2B8\uB97C \uCE21\uC815\uD558\uAE30 \uC704\uD574\uC11C \uD544\uC694\uD55C \uB370\uC774\uD130\uB97C \uC815\uC758\uD558\uB294 \uACF3
2726
+
2727
+ @Model.Insight("\${dict.Model}Insight")
2728
+
2729
+ export class \${dict.Model}Insight {{
2730
+
2731
+ @Field.Prop(() => Int, {{ default: 0, accumulate: {{ $sum: 1 }} }})
2732
+
2733
+ count: number;
2734
+
2735
+ }}
2736
+
2737
+
2738
+
2739
+ //\uB370\uC774\uD130\uC758 \uD1B5\uACC4\uB97C \uACC4\uC0B0\uD558\uB294 \uACF3
2740
+
2741
+ @Model.Summary("\${dict.Model}Summary")
2742
+
2743
+ export class \${dict.Model}Summary {{
2744
+
2745
+ @Field.Prop(() => Int, {{ min: 0, default: 0, query: {{ status: {{}} }} }})
2746
+
2747
+ total\${dict.Model}: number;
2748
+
2749
+ }}
2750
+
2751
+
2752
+
2753
+ @Model.Filter("\${dict.Model}Filter")
2754
+
2755
+ export class \${dict.Model}Filter extends sortOf(\${dict.Model}, {}) {}
2756
+
2757
+ \`\`\`
2758
+
2759
+
2760
+
2761
+
2762
+ model.dictonary.ts
2763
+
2764
+ \`\`\`
2765
+
2766
+ import {
2767
+
2768
+ baseTrans,
2769
+
2770
+ getBaseSignalTrans,
2771
+
2772
+ ModelDictionary,
2773
+
2774
+ SignalDictionary,
2775
+
2776
+ SummaryDictionary,
2777
+
2778
+ } from "@akanjs/dictionary";
2779
+
2780
+
2781
+
2782
+ import type { \${dict.Model}, \${dict.Model}Filter, \${dict.Model}Insight, \${dict.Model}Summary } from "./\${dict.model}.constant";
2783
+
2784
+ import type { \${dict.Model}Signal } from "./\${dict.model}.signal";
2785
+
2786
+
2787
+
2788
+ const modelDictionary = {{
2789
+
2790
+ ...baseTrans,
2791
+
2792
+ modelName: ["\${dict.Model}", "\${dict.Model}"],
2793
+
2794
+ modelDesc: [
2795
+
2796
+ "\${dict.Model} description",
2797
+
2798
+ "\${dict.Model} \uC124\uBA85",
2799
+
2800
+ ],
2801
+
2802
+
2803
+
2804
+ // * ==================== Model ==================== * //
2805
+
2806
+ field: ["Field", "\uD544\uB4DC"],
2807
+
2808
+ "desc-field": ["Field", "\uD544\uB4DC"],
2809
+
2810
+ // * ==================== Model ==================== * //
2811
+
2812
+
2813
+
2814
+ // * ==================== Insight ==================== * //
2815
+
2816
+ count: ["Count", "\uAC1C\uC218"],
2817
+
2818
+ "desc-count": ["\${dict.Model} count in current query settting", "\uD604\uC7AC \uCFFC\uB9AC \uC124\uC815\uC5D0 \uB9DE\uB294 \${dict.Model} \uC218"],
2819
+
2820
+ // * ==================== Insight ==================== * //
2821
+
2822
+
2823
+
2824
+ // * ==================== Filter ==================== * //
2825
+
2826
+ // * ==================== Filter ==================== * //
2827
+
2828
+
2829
+
2830
+ // * ==================== Etc ==================== * //
2831
+
2832
+ "enum-status-active": ["Active", "\uD65C\uC131"],
2833
+
2834
+ "enumdesc-status-active": ["Active status", "\uD65C\uC131 \uC0C1\uD0DC"],
2835
+
2836
+ // * ==================== Etc ==================== * //
2837
+
2838
+ }} satisfies ModelDictionary<\${dict.Model}, \${dict.Model}Insight, typeof \${dict.Model}Sort>;
2839
+
2840
+
2841
+
2842
+ export const \${dict.Model}SummaryDictionary = {{
2843
+
2844
+ // * ==================== Summary ==================== * //
2845
+
2846
+ total\${dict.Model}: ["Total \${dict.Model}", "\uCD1D \${dict.Model} \uC218"],
2847
+
2848
+ "desc-total\${dict.Model}": ["Total \${dict.Model} count in the database", "\uB370\uC774\uD130\uBCA0\uC774\uC2A4\uC5D0 \uC800\uC7A5\uB41C \uCD1D \${dict.Model} \uC218"],
2849
+
2850
+ // * ==================== Summary ==================== * //
2851
+
2852
+ }} satisfies SummaryDictionary<\${dict.Model}Summary>;
2853
+
2854
+
2855
+
2856
+ const signalDictionary = {{
2857
+
2858
+ ...getBaseSignalTrans("\${dict.Model}" as const),
2859
+
2860
+ // * ==================== Endpoint ==================== * //
2861
+
2862
+ "api-\${dict.Model}ListInPublic": ["\${dict.Model} List In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uB9AC\uC2A4\uD2B8"],
2863
+
2864
+ "apidesc-\${dict.Model}ListInPublic": ["Get a list of public \${dict.Model}", "\uACF5\uAC1C\uB41C \${dict.Model}\uC758 \uB9AC\uC2A4\uD2B8\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4"],
2865
+
2866
+ "arg-\${dict.Model}ListInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2867
+
2868
+ "argdesc-\${dict.Model}ListInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2869
+
2870
+ "arg-\${dict.Model}ListInPublic-skip": ["Skip", "\uAC74\uB108\uB6F0\uAE30"],
2871
+
2872
+ "argdesc-\${dict.Model}ListInPublic-skip": ["Number of items to skip", "\uAC74\uB108\uB6F8 \uC544\uC774\uD15C \uC218"],
2873
+
2874
+ "arg-\${dict.Model}ListInPublic-limit": ["Limit", "\uC81C\uD55C"],
2875
+
2876
+ "argdesc-\${dict.Model}ListInPublic-limit": ["Maximum number of items to return", "\uBC18\uD658\uD560 \uCD5C\uB300 \uC544\uC774\uD15C \uC218"],
2877
+
2878
+ "arg-\${dict.Model}ListInPublic-sort": ["Sort", "\uC815\uB82C"],
2879
+
2880
+ "argdesc-\${dict.Model}ListInPublic-sort": ["Sort order of the items", "\uC544\uC774\uD15C\uC758 \uC815\uB82C \uC21C\uC11C"],
2881
+
2882
+
2883
+
2884
+ "api-\${dict.Model}InsightInPublic": ["\${dict.Model} Insight In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uC778\uC0AC\uC774\uD2B8"],
2885
+
2886
+ "apidesc-\${dict.Model}InsightInPublic": [
2887
+
2888
+ "Get insight data for public \${dict.Model}",
2889
+
2890
+ "\uACF5\uAC1C\uB41C \${dict.Model}\uC5D0 \uB300\uD55C \uC778\uC0AC\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4",
2891
+
2892
+ ],
2893
+
2894
+ "arg-\${dict.Model}InsightInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2895
+
2896
+ "argdesc-\${dict.Model}InsightInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2897
+
2898
+ // * ==================== Endpoint ==================== * //
2899
+
2900
+ }} satisfies SignalDictionary<\${dict.Model}Signal, \${dict.Model}>;
2901
+
2902
+ \`\`\`
2903
+
2904
+ export const \${dict.model}Dictionary = {{ ...modelDictionary, ...signalDictionary }};
2905
+
2906
+
2907
+
2908
+
2909
+
2910
+ model.document.ts
2911
+
2912
+ \`\`\`
2913
+
2914
+ import { beyond, by, Database, into, type SchemaOf } from "@akanjs/document";
2915
+
2916
+
2917
+
2918
+ import { cnst } from "../cnst";
2919
+
2920
+ @Database.Input(() => cnst.\${dict.Model}Input)
2921
+
2922
+ export class \${dict.Model}Input extends by(cnst.\${dict.Model}Input) {}
2923
+
2924
+
2925
+
2926
+ @Database.Document(() => cnst.\${dict.Model})
2927
+
2928
+ export class \${dict.Model} extends by(cnst.\${dict.Model}) {}
2929
+
2930
+
2931
+
2932
+ @Database.Model(() => cnst.\${dict.Model})
2933
+
2934
+ export class \${dict.Model}Model extends into(\${dict.Model}, cnst.\${dict.Model}Cnst) {
2935
+
2936
+ async getSummary(): Promise<cnst.\${dict.Model}Summary> {
2937
+
2938
+ return {
2939
+
2940
+ ...(await this.getDefaultSummary()),
2941
+
2942
+ };
2943
+
2944
+ }
2945
+
2946
+ }
2947
+
2948
+
2949
+
2950
+ @Database.Middleware(() => cnst.\${dict.Model})
2951
+
2952
+ export class \${dict.Model}Middleware extends beyond(\${dict.Model}Model, \${dict.Model}) {
2953
+
2954
+ onSchema(schema: SchemaOf<\${dict.Model}Model, \${dict.Model}>) {
2955
+
2956
+ // schema.index({ status: 1 })
2957
+
2958
+ }
2959
+
2960
+ }
2961
+
2962
+ \`\`\`
2963
+
2964
+
2965
+
2966
+
2967
+ model.signal.ts
2968
+
2969
+ \`\`\`
2970
+
2971
+ import { Int } from "@akanjs/base";
2972
+
2973
+ import { SortOf } from "@akanjs/constant";
2974
+
2975
+ import { Arg, DbSignal, Mutation, Query, resolve, Signal } from "@akanjs/signal";
2976
+
2977
+
2978
+
2979
+ import { cnst, Srvs } from "../cnst";
2980
+
2981
+
2982
+
2983
+ @Signal(() => cnst.\${dict.Model})
2984
+
2985
+ export class \${dict.Model}Signal extends DbSignal(cnst.\${dict.model}Cnst, Srvs, {
2986
+
2987
+ guards: { get: Query.Public, cru: Mutation.Public },
2988
+
2989
+ }) {
2990
+
2991
+ // * /////////////////////////////////////
2992
+
2993
+ // * Public Slice
2994
+
2995
+ @Query.Public(() => [cnst.\${dict.Model}])
2996
+
2997
+ async \${dict.model}ListInPublic(
2998
+
2999
+ @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null,
3000
+
3001
+ @Arg.Query("skip", () => Int, { nullable: true }) skip: number | null,
3002
+
3003
+ @Arg.Query("limit", () => Int, { nullable: true }) limit: number | null,
3004
+
3005
+ @Arg.Query("sort", () => String, { nullable: true }) sort: SortOf<cnst.\${dict.Model}Filter> | null
3006
+
3007
+ ) {
3008
+
3009
+ const \${dict.models} = await this.\${dict.model}Service.listByStatuses(statuses, { skip, limit, sort });
3010
+
3011
+ return resolve<cnst.\${dict.Model}[]>(\${dict.models});
3012
+
3013
+ }
3014
+
3015
+ @Query.Public(() => cnst.\${dict.Model}Insight)
3016
+
3017
+ async \${dict.model}InsightInPublic(
3018
+
3019
+ @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null
3020
+
3021
+ ) {
3022
+
3023
+ const \${dict.model}Insight = await this.\${dict.model}Service.insightByStatuses(statuses);
3024
+
3025
+ return resolve<cnst.\${dict.Model}Insight>(\${dict.model}Insight);
3026
+
3027
+ }
3028
+
3029
+ // * Public Slice
3030
+
3031
+ // * /////////////////////////////////////
3032
+
3033
+ }
3034
+
3035
+ \`\`\`
3036
+
3037
+
3038
+
3039
+
3040
+ model.service.ts
3041
+
3042
+ \`\`\`
3043
+
3044
+ import { DbService, Service } from "@akanjs/service";
3045
+
3046
+
3047
+
3048
+ import { cnst } from "../cnst";
3049
+
3050
+ import * as db from "../db";
3051
+
3052
+
3053
+
3054
+ @Service("\${dict.Model}Service")
3055
+
3056
+ export class \${dict.Model}Service extends DbService(db.\${dict.Model}Db) {
3057
+
3058
+ async summarize(): Promise<cnst.\${dict.Model}Summary> {
3059
+
3060
+ return {
3061
+
3062
+ ...(await this.\${dict.Model}Model.getSummary()),
3063
+
3064
+ };
3065
+
3066
+ }
3067
+
3068
+ }
3069
+
3070
+ \`\`\`
3071
+
3072
+
3073
+
3074
+
3075
+ model.store.ts
3076
+
3077
+ \`\`\`
3078
+
3079
+ import { stateOf, Store } from "@akanjs/store";
3080
+
3081
+
3082
+
3083
+ import { cnst } from "../cnst";
3084
+
3085
+ import { fetch } from "../fetch";
3086
+
3087
+
3088
+
3089
+ @Store(() => cnst.\${dict.Model})
3090
+
3091
+ export class \${dict.Model}Store extends stateOf(fetch.\${dict.model}Gql, {
3092
+
3093
+ // state
3094
+
3095
+ }) {
3096
+
3097
+ // action
3098
+
3099
+ }
3100
+
3101
+ \`\`\`
3102
+
3103
+
3104
+
3105
+
3106
+ model.Zone.tsx
3107
+
3108
+ \`\`\`
3109
+
3110
+ "use client";
3111
+
3112
+ import { Data, Load } from "@shared/ui";
3113
+
3114
+ import { ModelsProps } from "@akanjs/client";
3115
+
3116
+ import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
3117
+
3118
+ import { ClientInit, ClientView, DefaultOf } from "@akanjs/signal";
3119
+
3120
+
3121
+
3122
+ export const Admin = ({ sliceName = "\${dict.model}", init, query }: ModelsProps<cnst.\${dict.Model}>>) => {
3123
+
3124
+ return (
3125
+
3126
+ <Data.ListContainer
3127
+
3128
+ init={init}
3129
+
3130
+ query={query}
3131
+
3132
+ sliceName={sliceName}
3133
+
3134
+ renderItem={\${dict.Model}.Unit.Card}
3135
+
3136
+ renderDashboard={\${dict.Model}.Util.Stat}
3137
+
3138
+ renderInsight={\${dict.Model}.Util.Insight}
3139
+
3140
+ renderTemplate={\${dict.Model}.Template.General}
3141
+
3142
+ renderTitle={(\${dict.model}: DefaultOf<cnst.\${dict.Model}>>) => \`\${dict.Model} - \${\${dict.model}.id ? \${dict.model}.id : "New"}\`}
3143
+
3144
+ renderView={(\${dict.model}: cnst.\${dict.Model}>) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />}
3145
+
3146
+ columns={[
3147
+
3148
+ "id",
3149
+
3150
+ "status",
3151
+
3152
+ "createdAt",
3153
+
3154
+ "updatedAt",
3155
+
3156
+ ]}
3157
+
3158
+ actions={(\${dict.model}: cnst.Light\${dict.Model}, idx) => ["remove", "edit", "view"]}
3159
+
3160
+ />
3161
+
3162
+ );
3163
+
3164
+ };
3165
+
3166
+
3167
+
3168
+ interface CardProps {
3169
+
3170
+ className?: string;
3171
+
3172
+ init: ClientInit<"\${dict.model}", cnst.Light\${dict.Model}>;
3173
+
3174
+ }
3175
+
3176
+ export const Card = ({ className, init }: CardProps) => {
3177
+
3178
+ return (
3179
+
3180
+ <Load.Units
3181
+
3182
+ className={className}
3183
+
3184
+ init={init}
3185
+
3186
+ renderItem={(\${dict.model}: cnst.Light\${dict.Model}) => (
3187
+
3188
+ <\${dict.Model}.Unit.Card key={\${dict.model}.id} href={\`/\${dict.model}/\${\${dict.model}.id}\`} \${dict.model}={\${dict.model}} />
3189
+
3190
+ )}
3191
+
3192
+ />
3193
+
3194
+ );
3195
+
3196
+ };
3197
+
3198
+
3199
+
3200
+ interface ViewProps {
3201
+
3202
+ className?: string;
3203
+
3204
+ view: ClientView<"\${dict.model}", cnst.\${dict.Model}>;
3205
+
3206
+ }
3207
+
3208
+ export const View = ({ view }: ViewProps) => {
3209
+
3210
+ return <Load.View view={view} renderView={(\${dict.model}) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />} />;
3211
+
3212
+ };
3213
+
3214
+ \`\`\`
3215
+
3216
+
3217
+
3218
+ model.Templete.tsx
3219
+
3220
+ \`\`\`
3221
+
3222
+ "use client";
3223
+
3224
+ import { cnst, st, usePage } from "@\${dict.appName}/client";
3225
+
3226
+ import { Field } from "@shared/ui";
3227
+
3228
+ import { Layout } from "@util/ui";
3229
+
3230
+
3231
+
3232
+ interface \${dict.Model}EditProps {
3233
+
3234
+ \${dict.model}Id?: string | null;
3235
+
3236
+ }
3237
+
3238
+
3239
+
3240
+ export const General = ({ \${dict.model}Id = undefined }: \${dict.Model}EditProps) => {
3241
+
3242
+ const \${dict.model}Form = st.use.\${dict.model}Form();
3243
+
3244
+ const { l } = usePage();
3245
+
3246
+ return (
3247
+
3248
+ <Layout.Template>
3249
+
3250
+ <Field.Text
3251
+
3252
+ label={l.field("\${dict.model}", "id")}
3253
+
3254
+ desc={l.desc("\${dict.model}", "id")}
3255
+
3256
+ value={\${dict.model}Form.id}
3257
+
3258
+ onChange={st.do.setIdOn\${dict.Model}}
3259
+
3260
+ />
3261
+
3262
+ </Layout.Template>
3263
+
3264
+ );
3265
+
3266
+ };
3267
+
3268
+ \`\`\`
3269
+
3270
+
3271
+
3272
+
3273
+ model.Unit.tsx
3274
+
3275
+ \`\`\`
3276
+
3277
+ import { ModelProps } from "@akanjs/client";
3278
+
3279
+ import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
3280
+
3281
+ import { Link } from "@util/ui";
3282
+
3283
+
3284
+
3285
+ export const Card = ({ \${dict.model}, href }: ModelProps<"\${dict.model}", cnst.Light\${dict.Model}>>) => {
3286
+
3287
+ return (
3288
+
3289
+ <Link href={href} className="animate-fadeIn w-full h-36 flex rounded-lg shadow-sm hover:shadow-lg duration-300">
3290
+
3291
+ <div>{\${dict.model}.id}</div>
3292
+
3293
+ </Link>
3294
+
3295
+ );
3296
+
3297
+ };
3298
+
3299
+ \`\`\`
3300
+
3301
+
3302
+
3303
+
3304
+ model.Util.tsx
3305
+
3306
+ \`\`\`
3307
+
3308
+ "use client";
3309
+
3310
+ import { ModelDashboardProps, ModelInsightProps } from "@akanjs/client";
3311
+
3312
+ import { getQueryMap } from "@akanjs/constant";
3313
+
3314
+ import { cnst } from "@\${dict.appName}/client";
3315
+
3316
+ import { Data } from "@shared/ui";
3317
+
3318
+
3319
+
3320
+ export const Stat = ({
3321
+
3322
+ className,
3323
+
3324
+ summary,
3325
+
3326
+ sliceName = "\${dict.model}",
3327
+
3328
+ queryMap = getQueryMap(cnst.\${dict.Model}Summary),
3329
+
3330
+ hidePresents,
3331
+
3332
+ }: ModelDashboardProps<cnst.Summary>) => {
3333
+
3334
+ return (
3335
+
3336
+ <Data.Dashboard
3337
+
3338
+ className={className}
3339
+
3340
+ summary={summary}
3341
+
3342
+ sliceName={sliceName}
3343
+
3344
+ queryMap={queryMap}
3345
+
3346
+ columns={["total\${dict.Model}"]}
3347
+
3348
+ hidePresents={hidePresents}
3349
+
3350
+ />
3351
+
3352
+ );
3353
+
3354
+ };
3355
+
3356
+
3357
+
3358
+ export const Insight = ({
3359
+
3360
+ className,
3361
+
3362
+ insight,
3363
+
3364
+ sliceName = "\${dict.model}",
3365
+
3366
+ }: ModelInsightProps<cnst.\${dict.Model}Insight>) => {
3367
+
3368
+ return (
3369
+
3370
+ <Data.Insight
3371
+
3372
+ className={className}
3373
+
3374
+ insight={insight}
3375
+
3376
+ sliceName={sliceName}
3377
+
3378
+ columns={["count"]}
3379
+
3380
+ />
3381
+
3382
+ );
3383
+
3384
+ };
3385
+
3386
+ \`\`\`
3387
+
3388
+
3389
+
3390
+
3391
+ model.View.tsx
3392
+
3393
+ \`\`\`
3394
+
3395
+ import { clsx } from "@akanjs/client";
3396
+
3397
+ import { cnst } from "@\${dict.appName}/client";
3398
+
3399
+ import { Image } from "@util/ui";
3400
+
3401
+
3402
+
3403
+ interface \${dict.Model}ViewProps {
3404
+
3405
+ className?: string;
3406
+
3407
+ \${dict.model}: cnst.\${dict.Model};
3408
+
3409
+ self?: { id?: string } | null;
3410
+
3411
+ }
3412
+
3413
+
3414
+
3415
+ export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewProps) => {
3416
+
3417
+ return (
3418
+
3419
+ <div className={clsx(className, "animate-fadeIn w-full")}>
3420
+
3421
+ <div>{\${dict.model}.id}</div>
3422
+
3423
+ </div>
3424
+
3425
+ );
3426
+
3427
+ };
3428
+
3429
+ \`\`\`
3430
+
3431
+ \uC774\uB7F0\uC2DD\uC73C\uB85C \uC6B0\uB9AC\uAC00 \uC9C1\uC811 \uB9CC\uB4E0 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uAE30\uBC18\uD574\uC11C db\uC640 \uC11C\uBE44\uC2A4 \uC2A4\uD1A0\uC5B4\uAE4C\uC9C0 \uBAA8\uB450 \uC5F0\uB3D9\uD574\uC11C \uD558\uB098\uC758 \uBAA8\uB378\uC5D0 \uB9DE\uAC8C\uB054 \uBAA8\uB4C8\uC744 \uD55C \uD3F4\uB354\uC5D0\uC11C \uC791\uC5C5\uD560 \uC218 \uC788\uAC8C\uB054 \uAD6C\uC870\uB97C \uB9CC\uB4E4\uC5C8\uC5B4.
3432
+
3433
+
3434
+
3435
+ \uC77C\uB2E8 \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uC124\uBA85\uC740 \uC774 \uC815\uB3C4\uB85C \uD558\uACE0 \uC774 \uC815\uBCF4\uB4E4\uC744 \uAE30\uBC18\uC73C\uB85C \uB0B4\uAC00 \uC6D0\uD558\uB294 \uC694\uAD6C\uB97C \uB4E4\uC5B4\uC918.
3436
+
3437
+ `;
2930
3438
  var moduleDesription = `
2931
3439
 
2932
3440
  The project follows a modular architecture with clear separation of concerns. Each module in lib/<model>/ represents a domain
@@ -2935,23 +3443,29 @@ entity with a standardized file structure that promotes consistency and maintain
2935
3443
  ## Core Components
2936
3444
 
2937
3445
  ### <Model>.View.tsx
2938
- Presentation-only components that render data without managing state.
2939
- It works as a server component, They accept model data as props and display it according to specific layouts.
2940
- These components focus purely on how data looks to the user.
2941
- only use the full model.
2942
- This component is only viewing the component. So don't use click event or other interaction events.
2943
- If you need interaction, possible to wrapping the component with the <Model>.Zone.tsx component.
2944
- But useable the Link component for navigation.
2945
- Components created in Model.View.tsx should primarily be made to show the entire detailed data of the model rather than showing only partial data of the model.
2946
-
3446
+ - Core Purpose: Presentation-only components that render data
3447
+ - Execution Context: Works as a server component
3448
+ - State Management: Does not manage internal state
3449
+ - Data Handling: Accepts model data as props and displays it according to specific layouts
3450
+ - Primary Focus: Focuses purely on how data looks to the user
3451
+ - Model Usage: Only uses the full model
3452
+ - Interaction Restrictions: No click events or other interaction events
3453
+ - Interaction Extension: If interaction is needed, wrap with <Model>.Zone.tsx component
3454
+ - Navigation: Link component can be used for navigation purposes
3455
+ - Full Model Rendering: Implements complete rendering of the entire model data structure, ensuring all properties and relationships within the model are displayed rather than selecting only partial attributes
2947
3456
 
2948
3457
  ### <Model>.Template.tsx
2949
3458
  Reusable layout patterns with integrated state management. It works as a client component, These components provide consistent UI patterns and handle data
2950
3459
  binding, often using store hooks to access application state.
2951
3460
 
2952
3461
  ### <Model>.Unit.tsx
2953
- Small, self-contained UI components representing individual model instances. It works as a server component, They're designed for rendering single items in
2954
- lists or grids, displaying model data in compact formats. only use the light model.
3462
+ - Single Component Export: Each file exports one Card component for displaying model data
3463
+ - Server-Side Rendered: React Server Components without "use client" directive
3464
+ - Type-Safe Props: Uses ModelProps<"modelName", cnst.LightModel> interface
3465
+ - Optional Navigation: useable Link component for navigation in util/ui
3466
+ - Tailwind Styling: Universal use of Tailwind CSS with DaisyUI classes
3467
+ - Model Data Display: Direct access to typed model properties and methods
3468
+
2955
3469
 
2956
3470
  ### <Model>.Zone.tsx
2957
3471
  Top-level container components that orchestrate other components. It works as a client component, They compose views, templates, and units into complete UI
@@ -2995,6 +3509,7 @@ var utilUiDescription = `
2995
3509
  The libs/util/ui directory contains a comprehensive React component library designed for modern web applications.
2996
3510
  This framework provides a complete set of production-ready, reusable UI components with consistent styling, type safety, and advanced functionality.
2997
3511
 
3512
+ [Strict caution]
2998
3513
  - Every component must be used exactly as described in the documentation.
2999
3514
  - Do not add any additional props to the components.
3000
3515
  - Must use the written props exactly.
@@ -3006,7 +3521,7 @@ var utilUiDescription = `
3006
3521
 
3007
3522
  Core Technologies:
3008
3523
  - Built on React 18+ with TypeScript for strict type safety
3009
- - Styled with Tailwind CSS and DaisyUI for consistent design system
3524
+ - Styled based on Tailwind CSS and DaisyUI base for a consistent design system.
3010
3525
  - Implements modern React patterns including hooks, context providers, and portals
3011
3526
  - Full internationalization (i18n) support for multilingual applications
3012
3527
  - Responsive-first design with mobile optimization
@@ -3830,13 +4345,13 @@ var requestView = ({
3830
4345
  1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
3831
4346
  ${frameworkAbstract}
3832
4347
 
3833
- 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uAC1C\uC694
4348
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uC124\uBA85
3834
4349
  ${moduleDesription}
3835
4350
 
3836
- 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uAC1C\uC694
4351
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
3837
4352
  ${eslintDescription}
3838
4353
 
3839
- 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uAC1C\uC694
4354
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
3840
4355
  ${utilUiDescription}
3841
4356
 
3842
4357
 
@@ -3857,40 +4372,142 @@ ${properties.map(
3857
4372
  ).join("\n\n")}
3858
4373
 
3859
4374
 
3860
- 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
3861
- ${exampleFiles.map(
4375
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
4376
+ ${exampleFiles.map(
3862
4377
  (example) => `
3863
- Example filename: ${example.filepath}
3864
- \`\`\`
3865
- ${example.content}
3866
- \`\`\`
3867
- `
4378
+ Example filename: ${example.filepath}
4379
+ \`\`\`
4380
+ ${example.content}
4381
+ \`\`\`
4382
+ `
3868
4383
  ).join("\n\n")}
3869
4384
 
3870
4385
 
3871
4386
 
4387
+
4388
+
4389
+
4390
+ \uC5ED\uD560\uBD80\uC5EC
4391
+ - Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C
4392
+
4393
+ \uCF54\uB529 \uADDC\uCE59
4394
+ - \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4395
+ - \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4396
+ - CSS: DaisyUI (btn, input, badge \uAC19\uC740 \uAE30\uBCF8 \uC694\uC18C\uB9CC \uC0AC\uC6A9 \uAC00\uB2A5, card/hero \uAC19\uC740 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uBD88\uAC00)
4397
+ - \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4398
+ \uCF54\uB4DC \uC2A4\uD0C0\uC77C
4399
+ - \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
4400
+ - \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
4401
+ - \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
4402
+ - \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
4403
+ \uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
4404
+
4405
+ \uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
4406
+ - UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
4407
+ - \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
4408
+ - \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
4409
+
4410
+ \uC694\uCCAD\uC0AC\uD56D
4411
+ ${ModelName}.View.tsx \uCF54\uB4DC \uC791\uC131
4412
+ \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC740 \uBAA8\uB378 \uC774\uB984\uC740 \uC81C\uC678\uD55C \uCEF4\uD3EC\uB10C\uD2B8\uC758 \uB514\uC790\uC778\uC5D0 \uCD08\uC810\uC744 \uB450\uACE0 \uC791\uC131
4413
+ \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9 \uAC00\uB2A5\uD55C General \uCEF4\uD3EC\uB10C\uD2B8 1\uAC1C\uB97C \uC81C\uC678\uD55C \uB514\uC790\uC778 \uCEF4\uD3EC\uB10C\uD2B8 4\uAC1C \uAC1C\uBC1C
4414
+ \uCD94\uC0C1\uD654 \uD574\uC57C\uD558\uB294 \uACBD\uC6B0\uAC00 \uC788\uC744 \uACBD\uC6B0\uC5D4 \uBB38\uC11C\uB97C \uB2E4\uC2DC \uCC38\uACE0\uD558\uACE0 \uC124\uBA85\uB41C \uB0B4\uC5D0\uC11C \uD574\uACB0\uD574\uC57C\uD568.
4415
+
4416
+
3872
4417
  Application name: ${sysName}
3873
4418
  Model name: ${modelName}
4419
+
3874
4420
  Target filename: ${ModelName}.View.tsx
4421
+ \`\`\`
4422
+
4423
+ \`\`\`
3875
4424
 
4425
+
4426
+ `;
4427
+ var requestUnit = ({
4428
+ sysName,
4429
+ modelName,
4430
+ ModelName,
4431
+ constant,
4432
+ properties,
4433
+ exampleFiles
4434
+ }) => `
4435
+
3876
4436
 
3877
- \uB108\uB294 Akan.js\uB77C\uB294 \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C\uB85C Typescript \uAE30\uBC18 \uD504\uB85C\uADF8\uB7A8\uC744 \uC791\uC131\uD558\uB294 \uC2DC\uB2C8\uC5B4 \uAC1C\uBC1C\uC790\uC57C.
3878
- \uADF8 \uC911\uC5D0\uC11C\uB3C4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
3879
- \uB9CC\uC57D\uC5D0 \uC544\uC774\uCF58 \uC0AC\uC6A9\uC774 \uD544\uC694\uD558\uBA74 react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC5D0\uC11C \uC801\uD569\uD55C \uC544\uC774\uCF58\uC744 \uCC3E\uC544\uC11C \uC0AC\uC6A9\uD574\uC918.
3880
- \uB610, \uC0C9\uC0C1\uC744 \uC0AC\uC6A9\uD558\uB824\uACE0 \uD558\uBA74 \uD558\uB4DC\uCF54\uB529\uB41C \uC0C9\uC0C1(bg-red)\uC774 \uC544\uB2CC \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary)\uC744 \uC0AC\uC6A9\uD574\uC11C \uC791\uC131\uD574\uC918.
3881
- \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
3882
- css\uB77C\uC774\uBE0C\uB7EC\uB9AC\uB294 DaisyUI\uB97C \uAE30\uBC18\uC73C\uB85C \uC791\uC131\uD574\uC8FC\uB294\uB370, btn, input, badge\uC640 \uAC19\uC740 \uB2E8\uC21C\uD55C \uAE30\uBCF8 css\uB294 \uC0AC\uC6A9\uD574\uB3C4 \uAD1C\uCC2E\uC544. \uADF8\uB7F0\uB370 card, hero\uAC19\uC774 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8\uB294 \uC0AC\uC6A9\uD558\uBA74 \uC548\uB3FC.
3883
- \uBAA8\uB378\uC5D0 \uB300\uD574\uC11C object destructuring\uC740 \uD558\uC9C0\uB9D0\uACE0 ${modelName}.field \uD615\uD0DC\uB85C \uC811\uADFC\uD558\uACE0, \uD0C0\uC785\uC5D0 \uC5D0\uB7EC\uB294 \uC808\uB300\uB85C \uBC1C\uC0DD\uD558\uC9C0 \uC54A\uB3C4\uB85D ${modelName}.constant.ts\uC5D0 \uC791\uC131\uB418\uC788\uB294 \uC2A4\uD0A4\uB9C8\uB97C \uBCF4\uACE0 \uC791\uC131\uD574.
3884
- \uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC57C\uB3FC.
3885
- \uBAA8\uB4E0 \uBAA8\uB378 \uD544\uB4DC\uC5D0 \uC811\uADFC\uD558\uAE30 \uC804\uC5D0, \uAC01 \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8\uB97C \uC791\uC131\uD558\uACE0 \uAC80\uD1A0\uD574. \uD2B9\uD788 \uC911\uCCA9\uB41C \uAC1D\uCCB4( ex) XXX.XXX.XXX )\uC5D0 \uC811\uADFC\uD560 \uB54C\uB294 \uB354\uC6B1 \uC8FC\uC758\uD574.
3886
- \uB610\uD55C ${modelName}\uACFC \uC885\uC18D\uC131\uC774 \uC788\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785\uB4E4\uB3C4 \uBAA8\uB450 \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.
3887
- \uC704\uC5D0\uC11C \uC124\uBA85\uD55C \uBAA8\uB4E0 \uB8F0\uACFC \uC124\uBA85, \uD0C0\uC785\uC744 \uC808\uB300\uB85C \uC704\uBC30\uD558\uC9C0\uB9D0\uACE0 \uC798 \uD30C\uC545\uD558\uACE0 \uC791\uC131\uD574.(\uAC01 \uB370\uC774\uD130\uC758 \uD0C0\uC785, \uCEF4\uD3EC\uB10C\uD2B8\uC758 props\uB4F1...)
3888
- \uC124\uBA85\uD55C \uB0B4\uC6A9 \uC774\uC678\uC5D0 \uB0B4\uC6A9\uC73C\uB85C \uB2C8\uAC00 \uCD94\uC0C1\uD574\uC11C \uC4F0\uC9C0\uB9D0\uACE0 \uC704\uC5D0 \uBA85\uC2DC\uB418\uC788\uB294 \uB8F0 \uC548\uC5D0\uC11C\uB9CC \uC791\uC131\uD574. \uC788\uC9C0\uB3C4 \uC54A\uC740 \uAC83\uB4E4 \uB9CC\uB4E4\uC5B4\uC11C \uCD94\uC0C1\uD654 \uC2DC\uCF1C\uC11C \uC790\uAFB8 \uC4F0\uB294 \uC77C\uC740 \uC808\uB300\uB85C \uD558\uC9C0\uB9C8.
3889
- \uD2B9\uD788\uB098 \uBC29\uAE08 \uB9D0\uD55C \uC774 \uC704 \uB450 \uBB38\uC7A5\uC740 \uC808\uB300\uC801\uC73C\uB85C \uC9C0\uCF1C\uC57C \uD560 \uB8F0\uC774\uC57C \uC791\uC131\uD560 \uB54C \uD56D\uC0C1 \uC9C0\uD0A4\uACE0 \uB530\uB77C.
3890
- ${ModelName}.View.tsx \uCF54\uB4DC\uB97C \uC791\uC131\uD574\uC918. \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD560 \uC218 \uC788\uB294 \uB514\uC790\uC778\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C 4\uAC1C \uC815\uB3C4 \uB9CC\uB4E4\uC5B4\uC918. (ex card, table...)
3891
- \uC608\uC2DC \uB4E4\uC5B4\uC92C\uB2E4\uACE0 \uC608\uC2DC\uB9CC \uB9CC\uB4E4\uC9C0 \uB9D0\uACE0 \uB2C8 \uC0DD\uAC01\uC5D0 \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9\uD55C\uB2E4 \uD558\uB294 \uCEF4\uD3EC\uB10C\uD2B8\uB85C \uC0DD\uAC01\uD574\uC11C \uB9CC\uB4E4\uC5B4.
4437
+ 1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
4438
+ ${frameworkAbstract}
3892
4439
 
3893
- Target filename: ${ModelName}.View.tsx
4440
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uC124\uBA85
4441
+ ${moduleDesription}
4442
+
4443
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
4444
+ ${eslintDescription}
4445
+
4446
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
4447
+ ${utilUiDescription}
4448
+
4449
+ 5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
4450
+ ${constant}
4451
+
4452
+ 6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
4453
+ ${properties.map(
4454
+ (property) => `
4455
+ \`\`\`
4456
+ ${property.key}.constant.ts
4457
+
4458
+
4459
+ ${property.source}
4460
+ \`\`\`
4461
+ `
4462
+ ).join("\n\n")}
4463
+
4464
+
4465
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
4466
+ ${exampleFiles.map(
4467
+ (example) => `
4468
+ Example filename: ${example.filepath}
4469
+ \`\`\`
4470
+ ${example.content}
4471
+ \`\`\`
4472
+ `
4473
+ ).join("\n\n")}
4474
+
4475
+
4476
+
4477
+
4478
+
4479
+
4480
+ \uC5ED\uD560\uBD80\uC5EC
4481
+ - Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uC2DC\uB2C8\uC5B4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
4482
+
4483
+ \uCF54\uB529 \uADDC\uCE59
4484
+ - \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4485
+ - \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4486
+ - CSS: DaisyUI (btn, input, badge \uAC19\uC740 \uAE30\uBCF8 \uC694\uC18C\uB9CC \uC0AC\uC6A9 \uAC00\uB2A5, card/hero \uAC19\uC740 \uBCF5\uC7A1\uD55C \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uBD88\uAC00)
4487
+ - \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4488
+ \uCF54\uB4DC \uC2A4\uD0C0\uC77C
4489
+ - \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
4490
+ - \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
4491
+ - \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
4492
+ - \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
4493
+ \uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
4494
+
4495
+ \uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
4496
+ - UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
4497
+ - \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
4498
+ - \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
4499
+
4500
+ \uC694\uCCAD\uC0AC\uD56D
4501
+ - ${ModelName}.Unit.tsx \uCF54\uB4DC \uC791\uC131
4502
+ - \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC5D0 ModelName\uC740 \uC0DD\uB7B5\uD558\uBA70, \uC608\uC2DC\uD30C\uC77C\uB4E4\uC758 \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uCC38\uACE0\uD558\uC5EC \uC791\uBA85
4503
+ - \uC608\uC2DC\uD30C\uC77C \uCEF4\uD3EC\uB10C\uD2B8\uC758 \uAE30\uBC18\uD558\uC5EC \uC77C\uBC18\uC801\uC73C\uB85C \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uCEF4\uD3EC\uB10C\uD2B8 1\uAC1C\uC640 \uB514\uC790\uC778\uC801 \uC694\uC18C\uAC00 \uD3EC\uD568\uB41C \uCEF4\uD3EC\uB10C\uD2B8 3\uAC1C \uAC1C\uBC1C
4504
+ - \uCD94\uC0C1\uD654 \uD574\uC57C\uD558\uB294 \uACBD\uC6B0\uAC00 \uC788\uC744 \uACBD\uC6B0\uC5D4 \uBB38\uC11C\uB97C \uB2E4\uC2DC \uCC38\uACE0\uD558\uACE0 \uC124\uBA85\uB41C \uB0B4\uC5D0\uC11C \uD574\uACB0\uD574\uC57C\uD568.
4505
+
4506
+
4507
+ Application name: ${sysName}
4508
+ Model name: ${modelName}
4509
+
4510
+ Target filename: ${ModelName}.Unit.tsx
3894
4511
  \`\`\`
3895
4512
 
3896
4513
  \`\`\`
@@ -5330,7 +5947,6 @@ var ModuleScript = class {
5330
5947
  }
5331
5948
  async createUnit(sys2) {
5332
5949
  const libs = await sys2.getModules();
5333
- const unitExampleFiles = await sys2.getUnitsSourceCode();
5334
5950
  const lib = await (0, import_prompts8.select)({
5335
5951
  message: "Select the lib",
5336
5952
  choices: libs
@@ -5344,10 +5960,11 @@ var ModuleScript = class {
5344
5960
  if (!name)
5345
5961
  return;
5346
5962
  const Name = capitalize(name);
5963
+ const unitExampleFiles = (await sys2.getUnitsSourceCode()).filter((f) => !f.filepath.includes(`${name}.Unit.tsx`));
5347
5964
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5348
5965
  const constant = import_fs10.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5349
5966
  const session = new AiSession();
5350
- const promptRst = requestView({
5967
+ const promptRst = requestUnit({
5351
5968
  sysName: sys2.name,
5352
5969
  modelName: name,
5353
5970
  ModelName: Name,
@@ -5356,8 +5973,8 @@ var ModuleScript = class {
5356
5973
  exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
5357
5974
  });
5358
5975
  const content = await session.editTypescript(promptRst);
5359
- import_fs10.default.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5360
- import_fs10.default.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
5976
+ import_fs10.default.writeFileSync(`${sys2.cwdPath}/promptUnit.txt`, promptRst);
5977
+ import_fs10.default.writeFileSync(`${sys2.cwdPath}/resultUnit.txt`, content);
5361
5978
  }
5362
5979
  async createView(sys2) {
5363
5980
  const libs = await sys2.getModules();
@@ -5373,7 +5990,7 @@ var ModuleScript = class {
5373
5990
  const name = lib.split("/").pop();
5374
5991
  if (!name)
5375
5992
  return;
5376
- const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
5993
+ const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => !f.filepath.includes(`${name}.View.tsx`));
5377
5994
  const Name = capitalize(name);
5378
5995
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5379
5996
  const constant = import_fs10.default.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
@@ -5412,7 +6029,8 @@ var ModuleCommand = class {
5412
6029
  async createView(sys2, workspace) {
5413
6030
  await this.moduleScript.createView(sys2);
5414
6031
  }
5415
- async createUnit(name, workspace) {
6032
+ async createUnit(sys2, workspace) {
6033
+ await this.moduleScript.createUnit(sys2);
5416
6034
  }
5417
6035
  };
5418
6036
  __decorateClass([
@@ -5455,7 +6073,7 @@ __decorateClass([
5455
6073
  ], ModuleCommand.prototype, "createView", 1);
5456
6074
  __decorateClass([
5457
6075
  Target.Public(),
5458
- __decorateParam(0, Option("name", { desc: "name of unit module" })),
6076
+ __decorateParam(0, Sys()),
5459
6077
  __decorateParam(1, Workspace())
5460
6078
  ], ModuleCommand.prototype, "createUnit", 1);
5461
6079
  ModuleCommand = __decorateClass([
@@ -5535,60 +6153,12 @@ PageCommand = __decorateClass([
5535
6153
  Commands()
5536
6154
  ], PageCommand);
5537
6155
 
5538
- // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
5539
- var import_latest_version2 = __toESM(require("latest-version"));
5540
- var import_path5 = __toESM(require("path"));
5541
-
5542
6156
  // pkgs/@akanjs/cli/src/workspace/workspace.runner.ts
5543
6157
  var import_uuid2 = require("uuid");
6158
+ var import_lodash = require("lodash");
6159
+ var import_latest_version2 = __toESM(require("latest-version"));
6160
+ var import_path5 = __toESM(require("path"));
5544
6161
  var WorkspaceRunner = class {
5545
- async createWorkspace(repoName, appName, dirname = ".") {
5546
- }
5547
- async generateMongo(workspace) {
5548
- const namespace = "00000000-0000-0000-0000-000000000000";
5549
- const appNames = await workspace.getApps();
5550
- const apps = appNames.map((appName) => AppExecutor.from(workspace, appName));
5551
- const appDatas = apps.reduce(
5552
- (acc, app) => [
5553
- ...acc,
5554
- ...["debug", "develop", "main"].map((env) => ({
5555
- appName: app.name,
5556
- env,
5557
- secret: getCredentials(app, env)
5558
- }))
5559
- ],
5560
- []
5561
- );
5562
- const mongoConnectionList = {
5563
- type: "Compass Connections",
5564
- version: { $numberInt: "1" },
5565
- connections: appDatas.map(({ appName, env, secret }) => ({
5566
- id: (0, import_uuid2.v5)(`${appName}-${env}`, namespace),
5567
- favorite: {
5568
- name: `${appName}-${env}`,
5569
- color: "color9"
5570
- },
5571
- savedConnectionType: "favorite",
5572
- connectionOptions: {
5573
- connectionString: `mongodb://${secret.mongo.account.user.username}:${secret.mongo.account.user.password}@mongo-0.mongo-svc.${appName}-${env}/?directConnection=true&authSource=${appName}-${env}`,
5574
- sshTunnel: {
5575
- host: `${appName}-${env}.akamir.com`,
5576
- port: "32767",
5577
- username: "root",
5578
- password: "akamir"
5579
- }
5580
- }
5581
- }))
5582
- };
5583
- workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
5584
- }
5585
- };
5586
-
5587
- // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
5588
- var WorkspaceScript = class {
5589
- #runner = new WorkspaceRunner();
5590
- applicationScript = new ApplicationScript();
5591
- libraryScript = new LibraryScript();
5592
6162
  async createWorkspace(repoName, appName, dirname = ".") {
5593
6163
  const cwdPath = process.cwd();
5594
6164
  const workspaceRoot = import_path5.default.join(cwdPath, dirname, repoName);
@@ -5598,9 +6168,9 @@ var WorkspaceScript = class {
5598
6168
  template: "workspaceRoot",
5599
6169
  dict: {
5600
6170
  repoName,
5601
- RepoName: capitalize(repoName),
6171
+ RepoName: (0, import_lodash.capitalize)(repoName),
5602
6172
  appName,
5603
- AppName: capitalize(appName),
6173
+ AppName: (0, import_lodash.capitalize)(appName),
5604
6174
  serveDomain: "localhost"
5605
6175
  }
5606
6176
  });
@@ -5640,9 +6210,60 @@ var WorkspaceScript = class {
5640
6210
  await workspace.spawn("pnpm", ["install", "--reporter=silent"]);
5641
6211
  workspace.log("Initializing git repository and commit...");
5642
6212
  await workspace.commit("Initial commit", { init: true });
6213
+ return workspace;
6214
+ }
6215
+ async generateMongo(workspace) {
6216
+ const namespace = "00000000-0000-0000-0000-000000000000";
6217
+ const appNames = await workspace.getApps();
6218
+ const apps = appNames.map((appName) => AppExecutor.from(workspace, appName));
6219
+ const appDatas = apps.reduce(
6220
+ (acc, app) => [
6221
+ ...acc,
6222
+ ...["debug", "develop", "main"].map((env) => ({
6223
+ appName: app.name,
6224
+ env,
6225
+ secret: getCredentials(app, env)
6226
+ }))
6227
+ ],
6228
+ []
6229
+ );
6230
+ const mongoConnectionList = {
6231
+ type: "Compass Connections",
6232
+ version: { $numberInt: "1" },
6233
+ connections: appDatas.map(({ appName, env, secret }) => ({
6234
+ id: (0, import_uuid2.v5)(`${appName}-${env}`, namespace),
6235
+ favorite: {
6236
+ name: `${appName}-${env}`,
6237
+ color: "color9"
6238
+ },
6239
+ savedConnectionType: "favorite",
6240
+ connectionOptions: {
6241
+ connectionString: `mongodb://${secret.mongo.account.user.username}:${secret.mongo.account.user.password}@mongo-0.mongo-svc.${appName}-${env}/?directConnection=true&authSource=${appName}-${env}`,
6242
+ sshTunnel: {
6243
+ host: `${appName}-${env}.akamir.com`,
6244
+ port: "32767",
6245
+ username: "root",
6246
+ password: "akamir"
6247
+ }
6248
+ }
6249
+ }))
6250
+ };
6251
+ workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
6252
+ }
6253
+ };
6254
+
6255
+ // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
6256
+ var WorkspaceScript = class {
6257
+ #runner = new WorkspaceRunner();
6258
+ applicationScript = new ApplicationScript();
6259
+ libraryScript = new LibraryScript();
6260
+ async createWorkspace(repoName, appName, dirname = ".") {
6261
+ const workspace = await this.#runner.createWorkspace(repoName, appName, dirname);
5643
6262
  await this.libraryScript.installLibrary(workspace, "util");
5644
6263
  await this.libraryScript.installLibrary(workspace, "shared");
5645
6264
  await this.applicationScript.createApplication(appName, workspace);
6265
+ workspace.log(`Workspace created in ${workspace.workspaceRoot}`);
6266
+ Logger.rawLog(`Run \`cd ${repoName} && akan start ${appName}\` to start the development server.`);
5646
6267
  }
5647
6268
  async generateMongo(workspace) {
5648
6269
  await this.#runner.generateMongo(workspace);
@@ -5692,4 +6313,5 @@ void runCommands(
5692
6313
  //! 2. csr폴더를 현 위치로 복사 후 압축 후 삭제
5693
6314
  //! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
5694
6315
  //! add path in tsconfig.json
6316
+ //! 파일을 {name}.Unit.tsx에 저장.
5695
6317
  //! 파일을 {name}.View.tsx에 저장.