@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/esm/index.js CHANGED
@@ -903,10 +903,10 @@ var Executor = class {
903
903
  exec(command, options = {}) {
904
904
  const proc = exec(command, { cwd: this.cwdPath, ...options });
905
905
  proc.stdout?.on("data", (data) => {
906
- Logger.raw(data.toString());
906
+ Logger.raw(chalk.dim(data.toString()));
907
907
  });
908
908
  proc.stderr?.on("data", (data) => {
909
- Logger.raw(chalk.red(data.toString()));
909
+ Logger.raw(chalk.dim(data.toString()));
910
910
  });
911
911
  return new Promise((resolve, reject) => {
912
912
  proc.on("exit", (code, signal) => {
@@ -1436,11 +1436,11 @@ var SysExecutor = class extends Executor {
1436
1436
  return viewComponents;
1437
1437
  }
1438
1438
  async getUnitComponents() {
1439
- const unitComponents = (await fsPromise.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => fs6.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
1439
+ const unitComponents = (await fsPromise.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => fs6.existsSync(`${this.cwdPath}/lib/${name}/${name}.Unit.tsx`));
1440
1440
  return unitComponents;
1441
1441
  }
1442
1442
  async getTemplateComponents() {
1443
- const templateComponents = (await fsPromise.readdir(`${this.cwdPath}/lib`)).filter((name) => name.startsWith("_") && !name.startsWith("__")).filter((name) => fs6.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
1443
+ const templateComponents = (await fsPromise.readdir(`${this.cwdPath}/lib`)).filter((name) => !name.startsWith("_") && !name.startsWith("__") && !name.endsWith(".ts")).filter((name) => fs6.existsSync(`${this.cwdPath}/lib/${name}/${name}.Template.tsx`));
1444
1444
  return templateComponents;
1445
1445
  }
1446
1446
  async getViewsSourceCode() {
@@ -2028,6 +2028,7 @@ var runCommands = async (...commands) => {
2028
2028
  const errMsg = e instanceof Error ? e.message : typeof e === "string" ? e : JSON.stringify(e);
2029
2029
  Logger.error(`Command Error: ${chalk2.red(errMsg)}`);
2030
2030
  console.error(e);
2031
+ throw e;
2031
2032
  }
2032
2033
  });
2033
2034
  }
@@ -2395,525 +2396,1032 @@ import tsconfigPaths from "vite-tsconfig-paths";
2395
2396
 
2396
2397
  // pkgs/@akanjs/cli/src/module/module.prompt.ts
2397
2398
  var frameworkDescription = `
2398
- \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.
2399
- \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.
2400
-
2401
- \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2402
- - app
2399
+ \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.
2400
+
2401
+ \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.
2402
+
2403
+
2404
+
2405
+ \uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
2406
+
2407
+ - app
2408
+
2403
2409
  - project1
2410
+
2404
2411
  - project2
2412
+
2405
2413
  - project3
2414
+
2406
2415
  - project4
2407
- - lib
2416
+
2417
+ - lib
2418
+
2408
2419
  - core
2420
+
2409
2421
  - external
2422
+
2410
2423
  - game
2424
+
2411
2425
  - mint
2426
+
2412
2427
  - platform
2428
+
2413
2429
  - shared
2430
+
2414
2431
  - social
2432
+
2415
2433
  - util
2416
- app\uC740 \uAC01 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uB294 \uACF3\uC774\uC57C
2417
- 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.
2418
- \uB2E4\uC74C\uC740 app/project \uB0B4\uBD80\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC904\uAC8C.
2419
-
2420
- project
2421
- - app
2434
+
2435
+ app\uC740 \uAC01 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uB294 \uACF3\uC774\uC57C
2436
+
2437
+ 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.
2438
+
2439
+ \uB2E4\uC74C\uC740 app/project \uB0B4\uBD80\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC904\uAC8C.
2440
+
2441
+
2442
+
2443
+ project
2444
+
2445
+ - app
2446
+
2422
2447
  - [lang]
2423
- - (projectName)
2424
- - (user)
2425
- - page.tsx
2426
- - layout.tsx
2427
- - (public)
2428
- - page.tsx
2429
- - layout.tsx
2430
- - (admin)
2431
- - page.tsx
2432
- - layout.tsx
2433
-
2434
- - lib
2448
+
2449
+ - (projectName)
2450
+
2451
+ - (user)
2452
+
2453
+ - page.tsx
2454
+
2455
+ - layout.tsx
2456
+
2457
+ - (public)
2458
+
2459
+ - page.tsx
2460
+
2461
+ - layout.tsx
2462
+
2463
+ - (admin)
2464
+
2465
+ - page.tsx
2466
+
2467
+ - layout.tsx
2468
+
2469
+
2470
+
2471
+ - lib
2472
+
2435
2473
  - dataName1
2474
+
2436
2475
  - dataName2
2476
+
2437
2477
  - dataName3
2478
+
2438
2479
  - dataName4
2480
+
2439
2481
  - dataName5
2482
+
2440
2483
  - dataName6
2484
+
2441
2485
  - dataName7
2442
-
2443
- 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.
2444
- public/page.tsx\uAC00 \uAC00\uC7A5 \uCD5C\uCD08\uB85C \uC811\uADFC\uB418\uB294 Index \uD398\uC774\uC9C0\uAC00 \uB420 \uAC70\uC57C.
2445
- \uC544\uB798\uB294 public/page.tsx\uC758 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2446
- \`\`\`
2447
- import {{ Image, Link }} from "@util/ui";
2448
- import {{ getSelf }} from "@akanjs/client";
2449
-
2450
- export default function Page() {{
2451
- const self = getSelf();
2452
- return (
2453
- <div className="relative w-full h-screen overflow-hidden flex items-center justify-center">
2454
- <Image
2455
- className="absolute left-0 right-0 top-0 bottom-0 w-full h-screen -z-50"
2456
- width={{1920}}
2457
- height={{1080}}
2458
- src="/back.jpg"
2459
- />
2460
- <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">
2461
- <h1 className="text-4xl mt-2"><%= project %></h1>
2462
- <h2 className="text-lg"><%= project %> description</h2>
2463
- <Link className="w-full" href={{self ? "/home" : "/signin"}}>
2464
- <button className="btn w-full btn-primary">Go to dashboard</button>
2465
- </Link>
2466
- </div>
2467
- </div>
2468
- );
2469
- }}
2470
- \`\`\`
2471
-
2472
- 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.
2473
- \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.
2474
-
2475
- \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.
2476
- \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.
2477
-
2478
- \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.
2479
-
2480
- \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.
2481
-
2482
- pencil
2483
- - pencil.constant.ts ( pencil\uC5D0 \uB300\uD55C db schema, query, sort \uAD6C\uBB38\uC744 \uC815\uC758 )
2484
- - 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.)
2485
- - 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. )
2486
- - 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 )
2487
- - 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.)
2488
- - pencil.store.ts (pencil field\uC5D0 \uB300\uD55C \uC0C1\uD0DC\uAD00\uB9AC \uC800\uC7A5\uC18C.)
2489
- - 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. )
2490
- - 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. )
2491
- - 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. )
2492
- - pencil.Util.tsx (Action \uBC84\uD2BC\uC744 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2493
- - pencil.View.tsx (\uB2E8\uC77C view \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2494
-
2495
-
2496
- \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.
2497
-
2498
- document, signal, service\uB294 \uBC31\uC5D4\uB4DC\uC640 \uC5F0\uAD00\uB418\uC5B4\uC788\uB294 \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2499
- \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.
2500
- signal - document
2501
- signal - service - document
2502
-
2503
- store\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC\uC5D0\uC11C \uC0C1\uD0DC\uAD00\uB9AC\uB97C \uD560 \uB54C \uC0AC\uC6A9\uB3FC.
2504
- \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.
2505
-
2506
- \uC774\uB807\uAC8C 11\uAC1C\uC758 \uD30C\uC77C\uB85C \uAD6C\uBD84\uD574\uC11C \uC815\uC758\uAC00 \uB3FC.
2507
- \uC9C0\uAE08\uBD80\uD134 \uD55C \uD30C\uC77C\uB4E4\uB9C8\uB2E4 \uC0C1\uC138\uD55C \uC124\uBA85\uC744 \uD574\uC904\uAC8C.
2508
-
2509
- model.constant.ts
2510
-
2511
- 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.
2512
- \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
2513
- \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.
2514
- \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.
2515
- \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.
2516
-
2517
- \`\`\`
2518
- import { enumOf, Int } from "@akanjs/base";
2519
- import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
2520
-
2521
- export const \${dict.Model}Statuses = ["active"] as const;
2522
- export type \${dict.Model}Status = (typeof \${dict.Model}Statuses)[number];
2523
-
2524
- //\uB370\uC774\uD130\uB97C \uB9CC\uB4E4 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uACF3
2525
- @Model.Input("\${dict.Model}Input")
2526
- export class \${dict.Model}Input {{
2527
- @Field.Prop(() => String)
2528
- field: string;
2529
-
2530
- @Field.Prop(() => Int, {{ nullable: true }})
2531
- fieldInt: number | null;
2532
-
2533
- @Field.Prop(() => Date, {{default: dayjs()}})
2534
- fieldInt: Dayjs;
2535
- }}
2536
-
2537
- //\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
2538
- @Model.Object("\${dict.Model}Object")
2539
- export class \${dict.Model}Object extends via(\${dict.Model}Input) {
2540
- @Field.Prop(() => String, {{ enum: \${dict.Model}Statuses, default: "active" }})
2541
- status: \${dict.Model}Status;
2542
- }}
2543
-
2544
- //\uB370\uC774\uD130\uB97C \uB9AC\uC2A4\uD2B8\uB85C \uBCF4\uC5EC\uC904 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130\uB9CC \uC81C\uACF5\uD558\uB294 \uACF3
2545
- @Model.Light("Light\${dict.Model}")
2546
- export class Light\${dict.Model} extends via(\${dict.Model}Object, [
2547
- "field",
2548
- "status",
2549
- ] as const) {}
2550
-
2551
- //\uCD5C\uC885 \uB370\uC774\uD130\uC758 Full \uD0C0\uC785\uC774 \uC815\uC758\uB418\uB294 \uACF3
2552
- @Model.Full("\${dict.Model}")
2553
- export class \${dict.Model} extends via(\${dict.Model}Object, Light\${dict.Model}) {}
2554
-
2555
- //\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
2556
- @Model.Insight("\${dict.Model}Insight")
2557
- export class \${dict.Model}Insight {{
2558
- @Field.Prop(() => Int, {{ default: 0, accumulate: {{ $sum: 1 }} }})
2559
- count: number;
2560
- }}
2561
-
2562
- //\uB370\uC774\uD130\uC758 \uD1B5\uACC4\uB97C \uACC4\uC0B0\uD558\uB294 \uACF3
2563
- @Model.Summary("\${dict.Model}Summary")
2564
- export class \${dict.Model}Summary {{
2565
- @Field.Prop(() => Int, {{ min: 0, default: 0, query: {{ status: {{}} }} }})
2566
- total\${dict.Model}: number;
2567
- }}
2568
-
2569
- @Model.Filter("\${dict.Model}Filter")
2570
- export class \${dict.Model}Filter extends sortOf(\${dict.Model}, {}) {}
2571
- \`\`\`
2572
-
2573
-
2574
- model.dictonary.ts
2575
- \`\`\`
2576
- import {
2577
- baseTrans,
2578
- getBaseSignalTrans,
2579
- ModelDictionary,
2580
- SignalDictionary,
2581
- SummaryDictionary,
2582
- } from "@akanjs/dictionary";
2583
-
2584
- import type { \${dict.Model}, \${dict.Model}Filter, \${dict.Model}Insight, \${dict.Model}Summary } from "./\${dict.model}.constant";
2585
- import type { \${dict.Model}Signal } from "./\${dict.model}.signal";
2586
-
2587
- const modelDictionary = {{
2588
- ...baseTrans,
2589
- modelName: ["\${dict.Model}", "\${dict.Model}"],
2590
- modelDesc: [
2591
- "\${dict.Model} description",
2592
- "\${dict.Model} \uC124\uBA85",
2593
- ],
2594
-
2595
- // * ==================== Model ==================== * //
2596
- field: ["Field", "\uD544\uB4DC"],
2597
- "desc-field": ["Field", "\uD544\uB4DC"],
2598
- // * ==================== Model ==================== * //
2599
-
2600
- // * ==================== Insight ==================== * //
2601
- count: ["Count", "\uAC1C\uC218"],
2602
- "desc-count": ["\${dict.Model} count in current query settting", "\uD604\uC7AC \uCFFC\uB9AC \uC124\uC815\uC5D0 \uB9DE\uB294 \${dict.Model} \uC218"],
2603
- // * ==================== Insight ==================== * //
2604
-
2605
- // * ==================== Filter ==================== * //
2606
- // * ==================== Filter ==================== * //
2607
-
2608
- // * ==================== Etc ==================== * //
2609
- "enum-status-active": ["Active", "\uD65C\uC131"],
2610
- "enumdesc-status-active": ["Active status", "\uD65C\uC131 \uC0C1\uD0DC"],
2611
- // * ==================== Etc ==================== * //
2612
- }} satisfies ModelDictionary<\${dict.Model}, \${dict.Model}Insight, typeof \${dict.Model}Sort>;
2613
-
2614
- export const \${dict.Model}SummaryDictionary = {{
2615
- // * ==================== Summary ==================== * //
2616
- total\${dict.Model}: ["Total \${dict.Model}", "\uCD1D \${dict.Model} \uC218"],
2617
- "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"],
2618
- // * ==================== Summary ==================== * //
2619
- }} satisfies SummaryDictionary<\${dict.Model}Summary>;
2620
-
2621
- const signalDictionary = {{
2622
- ...getBaseSignalTrans("\${dict.Model}" as const),
2623
- // * ==================== Endpoint ==================== * //
2624
- "api-\${dict.Model}ListInPublic": ["\${dict.Model} List In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uB9AC\uC2A4\uD2B8"],
2625
- "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"],
2626
- "arg-\${dict.Model}ListInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2627
- "argdesc-\${dict.Model}ListInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2628
- "arg-\${dict.Model}ListInPublic-skip": ["Skip", "\uAC74\uB108\uB6F0\uAE30"],
2629
- "argdesc-\${dict.Model}ListInPublic-skip": ["Number of items to skip", "\uAC74\uB108\uB6F8 \uC544\uC774\uD15C \uC218"],
2630
- "arg-\${dict.Model}ListInPublic-limit": ["Limit", "\uC81C\uD55C"],
2631
- "argdesc-\${dict.Model}ListInPublic-limit": ["Maximum number of items to return", "\uBC18\uD658\uD560 \uCD5C\uB300 \uC544\uC774\uD15C \uC218"],
2632
- "arg-\${dict.Model}ListInPublic-sort": ["Sort", "\uC815\uB82C"],
2633
- "argdesc-\${dict.Model}ListInPublic-sort": ["Sort order of the items", "\uC544\uC774\uD15C\uC758 \uC815\uB82C \uC21C\uC11C"],
2634
-
2635
- "api-\${dict.Model}InsightInPublic": ["\${dict.Model} Insight In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uC778\uC0AC\uC774\uD2B8"],
2636
- "apidesc-\${dict.Model}InsightInPublic": [
2637
- "Get insight data for public \${dict.Model}",
2638
- "\uACF5\uAC1C\uB41C \${dict.Model}\uC5D0 \uB300\uD55C \uC778\uC0AC\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4",
2639
- ],
2640
- "arg-\${dict.Model}InsightInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2641
- "argdesc-\${dict.Model}InsightInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2642
- // * ==================== Endpoint ==================== * //
2643
- }} satisfies SignalDictionary<\${dict.Model}Signal, \${dict.Model}>;
2644
- \`\`\`
2645
- export const \${dict.model}Dictionary = {{ ...modelDictionary, ...signalDictionary }};
2646
-
2647
-
2648
-
2649
- model.document.ts
2650
- \`\`\`
2651
- import { beyond, by, Database, into, type SchemaOf } from "@akanjs/document";
2652
-
2653
- import { cnst } from "../cnst";
2654
- @Database.Input(() => cnst.\${dict.Model}Input)
2655
- export class \${dict.Model}Input extends by(cnst.\${dict.Model}Input) {}
2656
-
2657
- @Database.Document(() => cnst.\${dict.Model})
2658
- export class \${dict.Model} extends by(cnst.\${dict.Model}) {}
2659
-
2660
- @Database.Model(() => cnst.\${dict.Model})
2661
- export class \${dict.Model}Model extends into(\${dict.Model}, cnst.\${dict.Model}Cnst) {
2662
- async getSummary(): Promise<cnst.\${dict.Model}Summary> {
2663
- return {
2664
- ...(await this.getDefaultSummary()),
2665
- };
2666
- }
2667
- }
2668
-
2669
- @Database.Middleware(() => cnst.\${dict.Model})
2670
- export class \${dict.Model}Middleware extends beyond(\${dict.Model}Model, \${dict.Model}) {
2671
- onSchema(schema: SchemaOf<\${dict.Model}Model, \${dict.Model}>) {
2672
- // schema.index({ status: 1 })
2673
- }
2674
- }
2675
- \`\`\`
2676
-
2677
-
2678
- model.signal.ts
2679
- \`\`\`
2680
- import { Int } from "@akanjs/base";
2681
- import { SortOf } from "@akanjs/constant";
2682
- import { Arg, DbSignal, Mutation, Query, resolve, Signal } from "@akanjs/signal";
2683
-
2684
- import { cnst, Srvs } from "../cnst";
2685
-
2686
- @Signal(() => cnst.\${dict.Model})
2687
- export class \${dict.Model}Signal extends DbSignal(cnst.\${dict.model}Cnst, Srvs, {
2688
- guards: { get: Query.Public, cru: Mutation.Public },
2689
- }) {
2690
- // * /////////////////////////////////////
2691
- // * Public Slice
2692
- @Query.Public(() => [cnst.\${dict.Model}])
2693
- async \${dict.model}ListInPublic(
2694
- @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null,
2695
- @Arg.Query("skip", () => Int, { nullable: true }) skip: number | null,
2696
- @Arg.Query("limit", () => Int, { nullable: true }) limit: number | null,
2697
- @Arg.Query("sort", () => String, { nullable: true }) sort: SortOf<cnst.\${dict.Model}Filter> | null
2698
- ) {
2699
- const \${dict.models} = await this.\${dict.model}Service.listByStatuses(statuses, { skip, limit, sort });
2700
- return resolve<cnst.\${dict.Model}[]>(\${dict.models});
2701
- }
2702
- @Query.Public(() => cnst.\${dict.Model}Insight)
2703
- async \${dict.model}InsightInPublic(
2704
- @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null
2705
- ) {
2706
- const \${dict.model}Insight = await this.\${dict.model}Service.insightByStatuses(statuses);
2707
- return resolve<cnst.\${dict.Model}Insight>(\${dict.model}Insight);
2708
- }
2709
- // * Public Slice
2710
- // * /////////////////////////////////////
2711
- }
2712
- \`\`\`
2713
-
2714
-
2715
- model.service.ts
2716
- \`\`\`
2717
- import { DbService, Service } from "@akanjs/service";
2718
-
2719
- import { cnst } from "../cnst";
2720
- import * as db from "../db";
2721
-
2722
- @Service("\${dict.Model}Service")
2723
- export class \${dict.Model}Service extends DbService(db.\${dict.Model}Db) {
2724
- async summarize(): Promise<cnst.\${dict.Model}Summary> {
2725
- return {
2726
- ...(await this.\${dict.Model}Model.getSummary()),
2727
- };
2728
- }
2729
- }
2730
- \`\`\`
2731
-
2732
-
2733
- model.store.ts
2734
- \`\`\`
2735
- import { stateOf, Store } from "@akanjs/store";
2736
-
2737
- import { cnst } from "../cnst";
2738
- import { fetch } from "../fetch";
2739
-
2740
- @Store(() => cnst.\${dict.Model})
2741
- export class \${dict.Model}Store extends stateOf(fetch.\${dict.model}Gql, {
2742
- // state
2743
- }) {
2744
- // action
2745
- }
2746
- \`\`\`
2747
-
2748
-
2749
- model.Zone.tsx
2750
- \`\`\`
2751
- "use client";
2752
- import { Data, Load } from "@shared/ui";
2753
- import { ModelsProps } from "@akanjs/client";
2754
- import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
2755
- import { ClientInit, ClientView, DefaultOf } from "@akanjs/signal";
2756
-
2757
- export const Admin = ({ sliceName = "\${dict.model}", init, query }: ModelsProps<cnst.\${dict.Model}>>) => {
2758
- return (
2759
- <Data.ListContainer
2760
- init={init}
2761
- query={query}
2762
- sliceName={sliceName}
2763
- renderItem={\${dict.Model}.Unit.Card}
2764
- renderDashboard={\${dict.Model}.Util.Stat}
2765
- renderInsight={\${dict.Model}.Util.Insight}
2766
- renderTemplate={\${dict.Model}.Template.General}
2767
- renderTitle={(\${dict.model}: DefaultOf<cnst.\${dict.Model}>>) => \`\${dict.Model} - \${\${dict.model}.id ? \${dict.model}.id : "New"}\`}
2768
- renderView={(\${dict.model}: cnst.\${dict.Model}>) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />}
2769
- columns={[
2770
- "id",
2771
- "status",
2772
- "createdAt",
2773
- "updatedAt",
2774
- ]}
2775
- actions={(\${dict.model}: cnst.Light\${dict.Model}, idx) => ["remove", "edit", "view"]}
2776
- />
2777
- );
2778
- };
2779
-
2780
- interface CardProps {
2781
- className?: string;
2782
- init: ClientInit<"\${dict.model}", cnst.Light\${dict.Model}>;
2783
- }
2784
- export const Card = ({ className, init }: CardProps) => {
2785
- return (
2786
- <Load.Units
2787
- className={className}
2788
- init={init}
2789
- renderItem={(\${dict.model}: cnst.Light\${dict.Model}) => (
2790
- <\${dict.Model}.Unit.Card key={\${dict.model}.id} href={\`/\${dict.model}/\${\${dict.model}.id}\`} \${dict.model}={\${dict.model}} />
2791
- )}
2792
- />
2793
- );
2794
- };
2795
-
2796
- interface ViewProps {
2797
- className?: string;
2798
- view: ClientView<"\${dict.model}", cnst.\${dict.Model}>;
2799
- }
2800
- export const View = ({ view }: ViewProps) => {
2801
- return <Load.View view={view} renderView={(\${dict.model}) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />} />;
2802
- };
2803
- \`\`\`
2804
-
2805
- model.Templete.tsx
2806
- \`\`\`
2807
- "use client";
2808
- import { cnst, st, usePage } from "@\${dict.appName}/client";
2809
- import { Field } from "@shared/ui";
2810
- import { Layout } from "@util/ui";
2811
-
2812
- interface \${dict.Model}EditProps {
2813
- \${dict.model}Id?: string | null;
2814
- }
2815
-
2816
- export const General = ({ \${dict.model}Id = undefined }: \${dict.Model}EditProps) => {
2817
- const \${dict.model}Form = st.use.\${dict.model}Form();
2818
- const { l } = usePage();
2819
- return (
2820
- <Layout.Template>
2821
- <Field.Text
2822
- label={l.field("\${dict.model}", "id")}
2823
- desc={l.desc("\${dict.model}", "id")}
2824
- value={\${dict.model}Form.id}
2825
- onChange={st.do.setIdOn\${dict.Model}}
2826
- />
2827
- </Layout.Template>
2828
- );
2829
- };
2830
- \`\`\`
2831
-
2832
-
2833
- model.Unit.tsx
2834
- \`\`\`
2835
- import { ModelProps } from "@akanjs/client";
2836
- import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
2837
- import { Link } from "@util/ui";
2838
-
2839
- export const Card = ({ \${dict.model}, href }: ModelProps<"\${dict.model}", cnst.Light\${dict.Model}>>) => {
2840
- return (
2841
- <Link href={href} className="animate-fadeIn w-full h-36 flex rounded-lg shadow-sm hover:shadow-lg duration-300">
2842
- <div>{\${dict.model}.id}</div>
2843
- </Link>
2844
- );
2845
- };
2846
- \`\`\`
2847
-
2848
-
2849
- model.Util.tsx
2850
- \`\`\`
2851
- "use client";
2852
- import { ModelDashboardProps, ModelInsightProps } from "@akanjs/client";
2853
- import { getQueryMap } from "@akanjs/constant";
2854
- import { cnst } from "@\${dict.appName}/client";
2855
- import { Data } from "@shared/ui";
2856
-
2857
- export const Stat = ({
2858
- className,
2859
- summary,
2860
- sliceName = "\${dict.model}",
2861
- queryMap = getQueryMap(cnst.\${dict.Model}Summary),
2862
- hidePresents,
2863
- }: ModelDashboardProps<cnst.Summary>) => {
2864
- return (
2865
- <Data.Dashboard
2866
- className={className}
2867
- summary={summary}
2868
- sliceName={sliceName}
2869
- queryMap={queryMap}
2870
- columns={["total\${dict.Model}"]}
2871
- hidePresents={hidePresents}
2872
- />
2873
- );
2874
- };
2875
-
2876
- export const Insight = ({
2877
- className,
2878
- insight,
2879
- sliceName = "\${dict.model}",
2880
- }: ModelInsightProps<cnst.\${dict.Model}Insight>) => {
2881
- return (
2882
- <Data.Insight
2883
- className={className}
2884
- insight={insight}
2885
- sliceName={sliceName}
2886
- columns={["count"]}
2887
- />
2888
- );
2889
- };
2890
- \`\`\`
2891
-
2892
-
2893
- model.View.tsx
2894
- \`\`\`
2895
- import { clsx } from "@akanjs/client";
2896
- import { cnst } from "@\${dict.appName}/client";
2897
- import { Image } from "@util/ui";
2898
-
2899
- interface \${dict.Model}ViewProps {
2900
- className?: string;
2901
- \${dict.model}: cnst.\${dict.Model};
2902
- self?: { id?: string } | null;
2903
- }
2904
-
2905
- export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewProps) => {
2906
- return (
2907
- <div className={clsx(className, "animate-fadeIn w-full")}>
2908
- <div>{\${dict.model}.id}</div>
2909
- </div>
2910
- );
2911
- };
2912
- \`\`\`
2913
- \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.
2914
-
2915
- \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.
2916
- `;
2486
+
2487
+
2488
+
2489
+ 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.
2490
+
2491
+ public/page.tsx\uAC00 \uAC00\uC7A5 \uCD5C\uCD08\uB85C \uC811\uADFC\uB418\uB294 Index \uD398\uC774\uC9C0\uAC00 \uB420 \uAC70\uC57C.
2492
+
2493
+ \uC544\uB798\uB294 public/page.tsx\uC758 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2494
+
2495
+ \`\`\`
2496
+
2497
+ import {{ Image, Link }} from "@util/ui";
2498
+
2499
+ import {{ getSelf }} from "@akanjs/client";
2500
+
2501
+
2502
+
2503
+ export default function Page() {{
2504
+
2505
+ const self = getSelf();
2506
+
2507
+ return (
2508
+
2509
+ <div className="relative w-full h-screen overflow-hidden flex items-center justify-center">
2510
+
2511
+ <Image
2512
+
2513
+ className="absolute left-0 right-0 top-0 bottom-0 w-full h-screen -z-50"
2514
+
2515
+ width={{1920}}
2516
+
2517
+ height={{1080}}
2518
+
2519
+ src="/back.jpg"
2520
+
2521
+ />
2522
+
2523
+ <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">
2524
+
2525
+ <h1 className="text-4xl mt-2"><%= project %></h1>
2526
+
2527
+ <h2 className="text-lg"><%= project %> description</h2>
2528
+
2529
+ <Link className="w-full" href={{self ? "/home" : "/signin"}}>
2530
+
2531
+ <button className="btn w-full btn-primary">Go to dashboard</button>
2532
+
2533
+ </Link>
2534
+
2535
+ </div>
2536
+
2537
+ </div>
2538
+
2539
+ );
2540
+
2541
+ }}
2542
+
2543
+ \`\`\`
2544
+
2545
+
2546
+
2547
+ 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.
2548
+
2549
+ \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.
2550
+
2551
+
2552
+
2553
+ \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.
2554
+
2555
+ \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.
2556
+
2557
+
2558
+
2559
+ \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.
2560
+
2561
+
2562
+
2563
+ \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.
2564
+
2565
+
2566
+
2567
+ pencil
2568
+
2569
+ - pencil.constant.ts ( pencil\uC5D0 \uB300\uD55C db schema, query, sort \uAD6C\uBB38\uC744 \uC815\uC758 )
2570
+
2571
+ - 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.)
2572
+
2573
+ - 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. )
2574
+
2575
+ - 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 )
2576
+
2577
+ - 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.)
2578
+
2579
+ - pencil.store.ts (pencil field\uC5D0 \uB300\uD55C \uC0C1\uD0DC\uAD00\uB9AC \uC800\uC7A5\uC18C.)
2580
+
2581
+ - 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. )
2582
+
2583
+ - 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. )
2584
+
2585
+ - 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. )
2586
+
2587
+ - pencil.Util.tsx (Action \uBC84\uD2BC\uC744 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
2588
+
2589
+ - pencil.View.tsx (\uB2E8\uC77C view \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
2590
+
2591
+
2592
+
2593
+
2594
+ \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.
2595
+
2596
+
2597
+
2598
+ document, signal, service\uB294 \uBC31\uC5D4\uB4DC\uC640 \uC5F0\uAD00\uB418\uC5B4\uC788\uB294 \uC18C\uC2A4\uCF54\uB4DC\uC57C.
2599
+
2600
+ \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.
2601
+
2602
+ signal - document
2603
+
2604
+ signal - service - document
2605
+
2606
+
2607
+
2608
+ store\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC\uC5D0\uC11C \uC0C1\uD0DC\uAD00\uB9AC\uB97C \uD560 \uB54C \uC0AC\uC6A9\uB3FC.
2609
+
2610
+ \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.
2611
+
2612
+
2613
+
2614
+ \uC774\uB807\uAC8C 11\uAC1C\uC758 \uD30C\uC77C\uB85C \uAD6C\uBD84\uD574\uC11C \uC815\uC758\uAC00 \uB3FC.
2615
+
2616
+ \uC9C0\uAE08\uBD80\uD134 \uD55C \uD30C\uC77C\uB4E4\uB9C8\uB2E4 \uC0C1\uC138\uD55C \uC124\uBA85\uC744 \uD574\uC904\uAC8C.
2617
+
2618
+
2619
+
2620
+ model.constant.ts
2621
+
2622
+
2623
+
2624
+ 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.
2625
+
2626
+ \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
2627
+
2628
+ \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.
2629
+
2630
+ \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.
2631
+
2632
+ \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.
2633
+
2634
+
2635
+
2636
+ \`\`\`
2637
+
2638
+ import { enumOf, Int } from "@akanjs/base";
2639
+
2640
+ import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
2641
+
2642
+
2643
+
2644
+ export const \${dict.Model}Statuses = ["active"] as const;
2645
+
2646
+ export type \${dict.Model}Status = (typeof \${dict.Model}Statuses)[number];
2647
+
2648
+
2649
+
2650
+ //\uB370\uC774\uD130\uB97C \uB9CC\uB4E4 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uACF3
2651
+
2652
+ @Model.Input("\${dict.Model}Input")
2653
+
2654
+ export class \${dict.Model}Input {{
2655
+
2656
+ @Field.Prop(() => String)
2657
+
2658
+ field: string;
2659
+
2660
+
2661
+
2662
+ @Field.Prop(() => Int, {{ nullable: true }})
2663
+
2664
+ fieldInt: number | null;
2665
+
2666
+
2667
+
2668
+ @Field.Prop(() => Date, {{default: dayjs()}})
2669
+
2670
+ fieldInt: Dayjs;
2671
+
2672
+ }}
2673
+
2674
+
2675
+
2676
+ //\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
2677
+
2678
+ @Model.Object("\${dict.Model}Object")
2679
+
2680
+ export class \${dict.Model}Object extends via(\${dict.Model}Input) {
2681
+
2682
+ @Field.Prop(() => String, {{ enum: \${dict.Model}Statuses, default: "active" }})
2683
+
2684
+ status: \${dict.Model}Status;
2685
+
2686
+ }}
2687
+
2688
+
2689
+
2690
+ //\uB370\uC774\uD130\uB97C \uB9AC\uC2A4\uD2B8\uB85C \uBCF4\uC5EC\uC904 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130\uB9CC \uC81C\uACF5\uD558\uB294 \uACF3
2691
+
2692
+ @Model.Light("Light\${dict.Model}")
2693
+
2694
+ export class Light\${dict.Model} extends via(\${dict.Model}Object, [
2695
+
2696
+ "field",
2697
+
2698
+ "status",
2699
+
2700
+ ] as const) {}
2701
+
2702
+
2703
+
2704
+ //\uCD5C\uC885 \uB370\uC774\uD130\uC758 Full \uD0C0\uC785\uC774 \uC815\uC758\uB418\uB294 \uACF3
2705
+
2706
+ @Model.Full("\${dict.Model}")
2707
+
2708
+ export class \${dict.Model} extends via(\${dict.Model}Object, Light\${dict.Model}) {}
2709
+
2710
+
2711
+
2712
+ //\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
2713
+
2714
+ @Model.Insight("\${dict.Model}Insight")
2715
+
2716
+ export class \${dict.Model}Insight {{
2717
+
2718
+ @Field.Prop(() => Int, {{ default: 0, accumulate: {{ $sum: 1 }} }})
2719
+
2720
+ count: number;
2721
+
2722
+ }}
2723
+
2724
+
2725
+
2726
+ //\uB370\uC774\uD130\uC758 \uD1B5\uACC4\uB97C \uACC4\uC0B0\uD558\uB294 \uACF3
2727
+
2728
+ @Model.Summary("\${dict.Model}Summary")
2729
+
2730
+ export class \${dict.Model}Summary {{
2731
+
2732
+ @Field.Prop(() => Int, {{ min: 0, default: 0, query: {{ status: {{}} }} }})
2733
+
2734
+ total\${dict.Model}: number;
2735
+
2736
+ }}
2737
+
2738
+
2739
+
2740
+ @Model.Filter("\${dict.Model}Filter")
2741
+
2742
+ export class \${dict.Model}Filter extends sortOf(\${dict.Model}, {}) {}
2743
+
2744
+ \`\`\`
2745
+
2746
+
2747
+
2748
+
2749
+ model.dictonary.ts
2750
+
2751
+ \`\`\`
2752
+
2753
+ import {
2754
+
2755
+ baseTrans,
2756
+
2757
+ getBaseSignalTrans,
2758
+
2759
+ ModelDictionary,
2760
+
2761
+ SignalDictionary,
2762
+
2763
+ SummaryDictionary,
2764
+
2765
+ } from "@akanjs/dictionary";
2766
+
2767
+
2768
+
2769
+ import type { \${dict.Model}, \${dict.Model}Filter, \${dict.Model}Insight, \${dict.Model}Summary } from "./\${dict.model}.constant";
2770
+
2771
+ import type { \${dict.Model}Signal } from "./\${dict.model}.signal";
2772
+
2773
+
2774
+
2775
+ const modelDictionary = {{
2776
+
2777
+ ...baseTrans,
2778
+
2779
+ modelName: ["\${dict.Model}", "\${dict.Model}"],
2780
+
2781
+ modelDesc: [
2782
+
2783
+ "\${dict.Model} description",
2784
+
2785
+ "\${dict.Model} \uC124\uBA85",
2786
+
2787
+ ],
2788
+
2789
+
2790
+
2791
+ // * ==================== Model ==================== * //
2792
+
2793
+ field: ["Field", "\uD544\uB4DC"],
2794
+
2795
+ "desc-field": ["Field", "\uD544\uB4DC"],
2796
+
2797
+ // * ==================== Model ==================== * //
2798
+
2799
+
2800
+
2801
+ // * ==================== Insight ==================== * //
2802
+
2803
+ count: ["Count", "\uAC1C\uC218"],
2804
+
2805
+ "desc-count": ["\${dict.Model} count in current query settting", "\uD604\uC7AC \uCFFC\uB9AC \uC124\uC815\uC5D0 \uB9DE\uB294 \${dict.Model} \uC218"],
2806
+
2807
+ // * ==================== Insight ==================== * //
2808
+
2809
+
2810
+
2811
+ // * ==================== Filter ==================== * //
2812
+
2813
+ // * ==================== Filter ==================== * //
2814
+
2815
+
2816
+
2817
+ // * ==================== Etc ==================== * //
2818
+
2819
+ "enum-status-active": ["Active", "\uD65C\uC131"],
2820
+
2821
+ "enumdesc-status-active": ["Active status", "\uD65C\uC131 \uC0C1\uD0DC"],
2822
+
2823
+ // * ==================== Etc ==================== * //
2824
+
2825
+ }} satisfies ModelDictionary<\${dict.Model}, \${dict.Model}Insight, typeof \${dict.Model}Sort>;
2826
+
2827
+
2828
+
2829
+ export const \${dict.Model}SummaryDictionary = {{
2830
+
2831
+ // * ==================== Summary ==================== * //
2832
+
2833
+ total\${dict.Model}: ["Total \${dict.Model}", "\uCD1D \${dict.Model} \uC218"],
2834
+
2835
+ "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"],
2836
+
2837
+ // * ==================== Summary ==================== * //
2838
+
2839
+ }} satisfies SummaryDictionary<\${dict.Model}Summary>;
2840
+
2841
+
2842
+
2843
+ const signalDictionary = {{
2844
+
2845
+ ...getBaseSignalTrans("\${dict.Model}" as const),
2846
+
2847
+ // * ==================== Endpoint ==================== * //
2848
+
2849
+ "api-\${dict.Model}ListInPublic": ["\${dict.Model} List In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uB9AC\uC2A4\uD2B8"],
2850
+
2851
+ "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"],
2852
+
2853
+ "arg-\${dict.Model}ListInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2854
+
2855
+ "argdesc-\${dict.Model}ListInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2856
+
2857
+ "arg-\${dict.Model}ListInPublic-skip": ["Skip", "\uAC74\uB108\uB6F0\uAE30"],
2858
+
2859
+ "argdesc-\${dict.Model}ListInPublic-skip": ["Number of items to skip", "\uAC74\uB108\uB6F8 \uC544\uC774\uD15C \uC218"],
2860
+
2861
+ "arg-\${dict.Model}ListInPublic-limit": ["Limit", "\uC81C\uD55C"],
2862
+
2863
+ "argdesc-\${dict.Model}ListInPublic-limit": ["Maximum number of items to return", "\uBC18\uD658\uD560 \uCD5C\uB300 \uC544\uC774\uD15C \uC218"],
2864
+
2865
+ "arg-\${dict.Model}ListInPublic-sort": ["Sort", "\uC815\uB82C"],
2866
+
2867
+ "argdesc-\${dict.Model}ListInPublic-sort": ["Sort order of the items", "\uC544\uC774\uD15C\uC758 \uC815\uB82C \uC21C\uC11C"],
2868
+
2869
+
2870
+
2871
+ "api-\${dict.Model}InsightInPublic": ["\${dict.Model} Insight In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uC778\uC0AC\uC774\uD2B8"],
2872
+
2873
+ "apidesc-\${dict.Model}InsightInPublic": [
2874
+
2875
+ "Get insight data for public \${dict.Model}",
2876
+
2877
+ "\uACF5\uAC1C\uB41C \${dict.Model}\uC5D0 \uB300\uD55C \uC778\uC0AC\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4",
2878
+
2879
+ ],
2880
+
2881
+ "arg-\${dict.Model}InsightInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
2882
+
2883
+ "argdesc-\${dict.Model}InsightInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
2884
+
2885
+ // * ==================== Endpoint ==================== * //
2886
+
2887
+ }} satisfies SignalDictionary<\${dict.Model}Signal, \${dict.Model}>;
2888
+
2889
+ \`\`\`
2890
+
2891
+ export const \${dict.model}Dictionary = {{ ...modelDictionary, ...signalDictionary }};
2892
+
2893
+
2894
+
2895
+
2896
+
2897
+ model.document.ts
2898
+
2899
+ \`\`\`
2900
+
2901
+ import { beyond, by, Database, into, type SchemaOf } from "@akanjs/document";
2902
+
2903
+
2904
+
2905
+ import { cnst } from "../cnst";
2906
+
2907
+ @Database.Input(() => cnst.\${dict.Model}Input)
2908
+
2909
+ export class \${dict.Model}Input extends by(cnst.\${dict.Model}Input) {}
2910
+
2911
+
2912
+
2913
+ @Database.Document(() => cnst.\${dict.Model})
2914
+
2915
+ export class \${dict.Model} extends by(cnst.\${dict.Model}) {}
2916
+
2917
+
2918
+
2919
+ @Database.Model(() => cnst.\${dict.Model})
2920
+
2921
+ export class \${dict.Model}Model extends into(\${dict.Model}, cnst.\${dict.Model}Cnst) {
2922
+
2923
+ async getSummary(): Promise<cnst.\${dict.Model}Summary> {
2924
+
2925
+ return {
2926
+
2927
+ ...(await this.getDefaultSummary()),
2928
+
2929
+ };
2930
+
2931
+ }
2932
+
2933
+ }
2934
+
2935
+
2936
+
2937
+ @Database.Middleware(() => cnst.\${dict.Model})
2938
+
2939
+ export class \${dict.Model}Middleware extends beyond(\${dict.Model}Model, \${dict.Model}) {
2940
+
2941
+ onSchema(schema: SchemaOf<\${dict.Model}Model, \${dict.Model}>) {
2942
+
2943
+ // schema.index({ status: 1 })
2944
+
2945
+ }
2946
+
2947
+ }
2948
+
2949
+ \`\`\`
2950
+
2951
+
2952
+
2953
+
2954
+ model.signal.ts
2955
+
2956
+ \`\`\`
2957
+
2958
+ import { Int } from "@akanjs/base";
2959
+
2960
+ import { SortOf } from "@akanjs/constant";
2961
+
2962
+ import { Arg, DbSignal, Mutation, Query, resolve, Signal } from "@akanjs/signal";
2963
+
2964
+
2965
+
2966
+ import { cnst, Srvs } from "../cnst";
2967
+
2968
+
2969
+
2970
+ @Signal(() => cnst.\${dict.Model})
2971
+
2972
+ export class \${dict.Model}Signal extends DbSignal(cnst.\${dict.model}Cnst, Srvs, {
2973
+
2974
+ guards: { get: Query.Public, cru: Mutation.Public },
2975
+
2976
+ }) {
2977
+
2978
+ // * /////////////////////////////////////
2979
+
2980
+ // * Public Slice
2981
+
2982
+ @Query.Public(() => [cnst.\${dict.Model}])
2983
+
2984
+ async \${dict.model}ListInPublic(
2985
+
2986
+ @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null,
2987
+
2988
+ @Arg.Query("skip", () => Int, { nullable: true }) skip: number | null,
2989
+
2990
+ @Arg.Query("limit", () => Int, { nullable: true }) limit: number | null,
2991
+
2992
+ @Arg.Query("sort", () => String, { nullable: true }) sort: SortOf<cnst.\${dict.Model}Filter> | null
2993
+
2994
+ ) {
2995
+
2996
+ const \${dict.models} = await this.\${dict.model}Service.listByStatuses(statuses, { skip, limit, sort });
2997
+
2998
+ return resolve<cnst.\${dict.Model}[]>(\${dict.models});
2999
+
3000
+ }
3001
+
3002
+ @Query.Public(() => cnst.\${dict.Model}Insight)
3003
+
3004
+ async \${dict.model}InsightInPublic(
3005
+
3006
+ @Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null
3007
+
3008
+ ) {
3009
+
3010
+ const \${dict.model}Insight = await this.\${dict.model}Service.insightByStatuses(statuses);
3011
+
3012
+ return resolve<cnst.\${dict.Model}Insight>(\${dict.model}Insight);
3013
+
3014
+ }
3015
+
3016
+ // * Public Slice
3017
+
3018
+ // * /////////////////////////////////////
3019
+
3020
+ }
3021
+
3022
+ \`\`\`
3023
+
3024
+
3025
+
3026
+
3027
+ model.service.ts
3028
+
3029
+ \`\`\`
3030
+
3031
+ import { DbService, Service } from "@akanjs/service";
3032
+
3033
+
3034
+
3035
+ import { cnst } from "../cnst";
3036
+
3037
+ import * as db from "../db";
3038
+
3039
+
3040
+
3041
+ @Service("\${dict.Model}Service")
3042
+
3043
+ export class \${dict.Model}Service extends DbService(db.\${dict.Model}Db) {
3044
+
3045
+ async summarize(): Promise<cnst.\${dict.Model}Summary> {
3046
+
3047
+ return {
3048
+
3049
+ ...(await this.\${dict.Model}Model.getSummary()),
3050
+
3051
+ };
3052
+
3053
+ }
3054
+
3055
+ }
3056
+
3057
+ \`\`\`
3058
+
3059
+
3060
+
3061
+
3062
+ model.store.ts
3063
+
3064
+ \`\`\`
3065
+
3066
+ import { stateOf, Store } from "@akanjs/store";
3067
+
3068
+
3069
+
3070
+ import { cnst } from "../cnst";
3071
+
3072
+ import { fetch } from "../fetch";
3073
+
3074
+
3075
+
3076
+ @Store(() => cnst.\${dict.Model})
3077
+
3078
+ export class \${dict.Model}Store extends stateOf(fetch.\${dict.model}Gql, {
3079
+
3080
+ // state
3081
+
3082
+ }) {
3083
+
3084
+ // action
3085
+
3086
+ }
3087
+
3088
+ \`\`\`
3089
+
3090
+
3091
+
3092
+
3093
+ model.Zone.tsx
3094
+
3095
+ \`\`\`
3096
+
3097
+ "use client";
3098
+
3099
+ import { Data, Load } from "@shared/ui";
3100
+
3101
+ import { ModelsProps } from "@akanjs/client";
3102
+
3103
+ import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
3104
+
3105
+ import { ClientInit, ClientView, DefaultOf } from "@akanjs/signal";
3106
+
3107
+
3108
+
3109
+ export const Admin = ({ sliceName = "\${dict.model}", init, query }: ModelsProps<cnst.\${dict.Model}>>) => {
3110
+
3111
+ return (
3112
+
3113
+ <Data.ListContainer
3114
+
3115
+ init={init}
3116
+
3117
+ query={query}
3118
+
3119
+ sliceName={sliceName}
3120
+
3121
+ renderItem={\${dict.Model}.Unit.Card}
3122
+
3123
+ renderDashboard={\${dict.Model}.Util.Stat}
3124
+
3125
+ renderInsight={\${dict.Model}.Util.Insight}
3126
+
3127
+ renderTemplate={\${dict.Model}.Template.General}
3128
+
3129
+ renderTitle={(\${dict.model}: DefaultOf<cnst.\${dict.Model}>>) => \`\${dict.Model} - \${\${dict.model}.id ? \${dict.model}.id : "New"}\`}
3130
+
3131
+ renderView={(\${dict.model}: cnst.\${dict.Model}>) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />}
3132
+
3133
+ columns={[
3134
+
3135
+ "id",
3136
+
3137
+ "status",
3138
+
3139
+ "createdAt",
3140
+
3141
+ "updatedAt",
3142
+
3143
+ ]}
3144
+
3145
+ actions={(\${dict.model}: cnst.Light\${dict.Model}, idx) => ["remove", "edit", "view"]}
3146
+
3147
+ />
3148
+
3149
+ );
3150
+
3151
+ };
3152
+
3153
+
3154
+
3155
+ interface CardProps {
3156
+
3157
+ className?: string;
3158
+
3159
+ init: ClientInit<"\${dict.model}", cnst.Light\${dict.Model}>;
3160
+
3161
+ }
3162
+
3163
+ export const Card = ({ className, init }: CardProps) => {
3164
+
3165
+ return (
3166
+
3167
+ <Load.Units
3168
+
3169
+ className={className}
3170
+
3171
+ init={init}
3172
+
3173
+ renderItem={(\${dict.model}: cnst.Light\${dict.Model}) => (
3174
+
3175
+ <\${dict.Model}.Unit.Card key={\${dict.model}.id} href={\`/\${dict.model}/\${\${dict.model}.id}\`} \${dict.model}={\${dict.model}} />
3176
+
3177
+ )}
3178
+
3179
+ />
3180
+
3181
+ );
3182
+
3183
+ };
3184
+
3185
+
3186
+
3187
+ interface ViewProps {
3188
+
3189
+ className?: string;
3190
+
3191
+ view: ClientView<"\${dict.model}", cnst.\${dict.Model}>;
3192
+
3193
+ }
3194
+
3195
+ export const View = ({ view }: ViewProps) => {
3196
+
3197
+ return <Load.View view={view} renderView={(\${dict.model}) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />} />;
3198
+
3199
+ };
3200
+
3201
+ \`\`\`
3202
+
3203
+
3204
+
3205
+ model.Templete.tsx
3206
+
3207
+ \`\`\`
3208
+
3209
+ "use client";
3210
+
3211
+ import { cnst, st, usePage } from "@\${dict.appName}/client";
3212
+
3213
+ import { Field } from "@shared/ui";
3214
+
3215
+ import { Layout } from "@util/ui";
3216
+
3217
+
3218
+
3219
+ interface \${dict.Model}EditProps {
3220
+
3221
+ \${dict.model}Id?: string | null;
3222
+
3223
+ }
3224
+
3225
+
3226
+
3227
+ export const General = ({ \${dict.model}Id = undefined }: \${dict.Model}EditProps) => {
3228
+
3229
+ const \${dict.model}Form = st.use.\${dict.model}Form();
3230
+
3231
+ const { l } = usePage();
3232
+
3233
+ return (
3234
+
3235
+ <Layout.Template>
3236
+
3237
+ <Field.Text
3238
+
3239
+ label={l.field("\${dict.model}", "id")}
3240
+
3241
+ desc={l.desc("\${dict.model}", "id")}
3242
+
3243
+ value={\${dict.model}Form.id}
3244
+
3245
+ onChange={st.do.setIdOn\${dict.Model}}
3246
+
3247
+ />
3248
+
3249
+ </Layout.Template>
3250
+
3251
+ );
3252
+
3253
+ };
3254
+
3255
+ \`\`\`
3256
+
3257
+
3258
+
3259
+
3260
+ model.Unit.tsx
3261
+
3262
+ \`\`\`
3263
+
3264
+ import { ModelProps } from "@akanjs/client";
3265
+
3266
+ import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
3267
+
3268
+ import { Link } from "@util/ui";
3269
+
3270
+
3271
+
3272
+ export const Card = ({ \${dict.model}, href }: ModelProps<"\${dict.model}", cnst.Light\${dict.Model}>>) => {
3273
+
3274
+ return (
3275
+
3276
+ <Link href={href} className="animate-fadeIn w-full h-36 flex rounded-lg shadow-sm hover:shadow-lg duration-300">
3277
+
3278
+ <div>{\${dict.model}.id}</div>
3279
+
3280
+ </Link>
3281
+
3282
+ );
3283
+
3284
+ };
3285
+
3286
+ \`\`\`
3287
+
3288
+
3289
+
3290
+
3291
+ model.Util.tsx
3292
+
3293
+ \`\`\`
3294
+
3295
+ "use client";
3296
+
3297
+ import { ModelDashboardProps, ModelInsightProps } from "@akanjs/client";
3298
+
3299
+ import { getQueryMap } from "@akanjs/constant";
3300
+
3301
+ import { cnst } from "@\${dict.appName}/client";
3302
+
3303
+ import { Data } from "@shared/ui";
3304
+
3305
+
3306
+
3307
+ export const Stat = ({
3308
+
3309
+ className,
3310
+
3311
+ summary,
3312
+
3313
+ sliceName = "\${dict.model}",
3314
+
3315
+ queryMap = getQueryMap(cnst.\${dict.Model}Summary),
3316
+
3317
+ hidePresents,
3318
+
3319
+ }: ModelDashboardProps<cnst.Summary>) => {
3320
+
3321
+ return (
3322
+
3323
+ <Data.Dashboard
3324
+
3325
+ className={className}
3326
+
3327
+ summary={summary}
3328
+
3329
+ sliceName={sliceName}
3330
+
3331
+ queryMap={queryMap}
3332
+
3333
+ columns={["total\${dict.Model}"]}
3334
+
3335
+ hidePresents={hidePresents}
3336
+
3337
+ />
3338
+
3339
+ );
3340
+
3341
+ };
3342
+
3343
+
3344
+
3345
+ export const Insight = ({
3346
+
3347
+ className,
3348
+
3349
+ insight,
3350
+
3351
+ sliceName = "\${dict.model}",
3352
+
3353
+ }: ModelInsightProps<cnst.\${dict.Model}Insight>) => {
3354
+
3355
+ return (
3356
+
3357
+ <Data.Insight
3358
+
3359
+ className={className}
3360
+
3361
+ insight={insight}
3362
+
3363
+ sliceName={sliceName}
3364
+
3365
+ columns={["count"]}
3366
+
3367
+ />
3368
+
3369
+ );
3370
+
3371
+ };
3372
+
3373
+ \`\`\`
3374
+
3375
+
3376
+
3377
+
3378
+ model.View.tsx
3379
+
3380
+ \`\`\`
3381
+
3382
+ import { clsx } from "@akanjs/client";
3383
+
3384
+ import { cnst } from "@\${dict.appName}/client";
3385
+
3386
+ import { Image } from "@util/ui";
3387
+
3388
+
3389
+
3390
+ interface \${dict.Model}ViewProps {
3391
+
3392
+ className?: string;
3393
+
3394
+ \${dict.model}: cnst.\${dict.Model};
3395
+
3396
+ self?: { id?: string } | null;
3397
+
3398
+ }
3399
+
3400
+
3401
+
3402
+ export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewProps) => {
3403
+
3404
+ return (
3405
+
3406
+ <div className={clsx(className, "animate-fadeIn w-full")}>
3407
+
3408
+ <div>{\${dict.model}.id}</div>
3409
+
3410
+ </div>
3411
+
3412
+ );
3413
+
3414
+ };
3415
+
3416
+ \`\`\`
3417
+
3418
+ \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.
3419
+
3420
+
3421
+
3422
+ \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.
3423
+
3424
+ `;
2917
3425
  var moduleDesription = `
2918
3426
 
2919
3427
  The project follows a modular architecture with clear separation of concerns. Each module in lib/<model>/ represents a domain
@@ -2922,23 +3430,29 @@ entity with a standardized file structure that promotes consistency and maintain
2922
3430
  ## Core Components
2923
3431
 
2924
3432
  ### <Model>.View.tsx
2925
- Presentation-only components that render data without managing state.
2926
- It works as a server component, They accept model data as props and display it according to specific layouts.
2927
- These components focus purely on how data looks to the user.
2928
- only use the full model.
2929
- This component is only viewing the component. So don't use click event or other interaction events.
2930
- If you need interaction, possible to wrapping the component with the <Model>.Zone.tsx component.
2931
- But useable the Link component for navigation.
2932
- 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.
2933
-
3433
+ - Core Purpose: Presentation-only components that render data
3434
+ - Execution Context: Works as a server component
3435
+ - State Management: Does not manage internal state
3436
+ - Data Handling: Accepts model data as props and displays it according to specific layouts
3437
+ - Primary Focus: Focuses purely on how data looks to the user
3438
+ - Model Usage: Only uses the full model
3439
+ - Interaction Restrictions: No click events or other interaction events
3440
+ - Interaction Extension: If interaction is needed, wrap with <Model>.Zone.tsx component
3441
+ - Navigation: Link component can be used for navigation purposes
3442
+ - 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
2934
3443
 
2935
3444
  ### <Model>.Template.tsx
2936
3445
  Reusable layout patterns with integrated state management. It works as a client component, These components provide consistent UI patterns and handle data
2937
3446
  binding, often using store hooks to access application state.
2938
3447
 
2939
3448
  ### <Model>.Unit.tsx
2940
- Small, self-contained UI components representing individual model instances. It works as a server component, They're designed for rendering single items in
2941
- lists or grids, displaying model data in compact formats. only use the light model.
3449
+ - Single Component Export: Each file exports one Card component for displaying model data
3450
+ - Server-Side Rendered: React Server Components without "use client" directive
3451
+ - Type-Safe Props: Uses ModelProps<"modelName", cnst.LightModel> interface
3452
+ - Optional Navigation: useable Link component for navigation in util/ui
3453
+ - Tailwind Styling: Universal use of Tailwind CSS with DaisyUI classes
3454
+ - Model Data Display: Direct access to typed model properties and methods
3455
+
2942
3456
 
2943
3457
  ### <Model>.Zone.tsx
2944
3458
  Top-level container components that orchestrate other components. It works as a client component, They compose views, templates, and units into complete UI
@@ -2982,6 +3496,7 @@ var utilUiDescription = `
2982
3496
  The libs/util/ui directory contains a comprehensive React component library designed for modern web applications.
2983
3497
  This framework provides a complete set of production-ready, reusable UI components with consistent styling, type safety, and advanced functionality.
2984
3498
 
3499
+ [Strict caution]
2985
3500
  - Every component must be used exactly as described in the documentation.
2986
3501
  - Do not add any additional props to the components.
2987
3502
  - Must use the written props exactly.
@@ -2993,7 +3508,7 @@ var utilUiDescription = `
2993
3508
 
2994
3509
  Core Technologies:
2995
3510
  - Built on React 18+ with TypeScript for strict type safety
2996
- - Styled with Tailwind CSS and DaisyUI for consistent design system
3511
+ - Styled based on Tailwind CSS and DaisyUI base for a consistent design system.
2997
3512
  - Implements modern React patterns including hooks, context providers, and portals
2998
3513
  - Full internationalization (i18n) support for multilingual applications
2999
3514
  - Responsive-first design with mobile optimization
@@ -3817,13 +4332,13 @@ var requestView = ({
3817
4332
  1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
3818
4333
  ${frameworkAbstract}
3819
4334
 
3820
- 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uAC1C\uC694
4335
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uC124\uBA85
3821
4336
  ${moduleDesription}
3822
4337
 
3823
- 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uAC1C\uC694
4338
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
3824
4339
  ${eslintDescription}
3825
4340
 
3826
- 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uAC1C\uC694
4341
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
3827
4342
  ${utilUiDescription}
3828
4343
 
3829
4344
 
@@ -3844,40 +4359,142 @@ ${properties.map(
3844
4359
  ).join("\n\n")}
3845
4360
 
3846
4361
 
3847
- 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
3848
- ${exampleFiles.map(
4362
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
4363
+ ${exampleFiles.map(
3849
4364
  (example) => `
3850
- Example filename: ${example.filepath}
3851
- \`\`\`
3852
- ${example.content}
3853
- \`\`\`
3854
- `
4365
+ Example filename: ${example.filepath}
4366
+ \`\`\`
4367
+ ${example.content}
4368
+ \`\`\`
4369
+ `
3855
4370
  ).join("\n\n")}
3856
4371
 
3857
4372
 
3858
4373
 
4374
+
4375
+
4376
+
4377
+ \uC5ED\uD560\uBD80\uC5EC
4378
+ - Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C
4379
+
4380
+ \uCF54\uB529 \uADDC\uCE59
4381
+ - \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4382
+ - \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4383
+ - 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)
4384
+ - \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4385
+ \uCF54\uB4DC \uC2A4\uD0C0\uC77C
4386
+ - \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
4387
+ - \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
4388
+ - \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
4389
+ - \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
4390
+ \uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
4391
+
4392
+ \uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
4393
+ - UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
4394
+ - \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
4395
+ - \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
4396
+
4397
+ \uC694\uCCAD\uC0AC\uD56D
4398
+ ${ModelName}.View.tsx \uCF54\uB4DC \uC791\uC131
4399
+ \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
4400
+ \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
4401
+ \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.
4402
+
4403
+
3859
4404
  Application name: ${sysName}
3860
4405
  Model name: ${modelName}
4406
+
3861
4407
  Target filename: ${ModelName}.View.tsx
4408
+ \`\`\`
4409
+
4410
+ \`\`\`
3862
4411
 
4412
+
4413
+ `;
4414
+ var requestUnit = ({
4415
+ sysName,
4416
+ modelName,
4417
+ ModelName,
4418
+ constant,
4419
+ properties,
4420
+ exampleFiles
4421
+ }) => `
4422
+
3863
4423
 
3864
- \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.
3865
- \uADF8 \uC911\uC5D0\uC11C\uB3C4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
3866
- \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.
3867
- \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.
3868
- \uADF8\uB9AC\uACE0 optional\uD55C \uD544\uB4DC\uB294 field && <div>... \uAC00 \uC544\uB2CC, field ? <div>... : null \uD615\uD0DC\uB85C \uC791\uC131\uD574\uC918.
3869
- 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.
3870
- \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.
3871
- \uC870\uAC74\uBD80 className\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uC5D0\uB294 clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB97C \uC0AC\uC6A9\uD574\uC57C\uB3FC.
3872
- \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.
3873
- \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.
3874
- \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...)
3875
- \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.
3876
- \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.
3877
- ${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...)
3878
- \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.
4424
+ 1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
4425
+ ${frameworkAbstract}
3879
4426
 
3880
- Target filename: ${ModelName}.View.tsx
4427
+ 2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uC124\uBA85
4428
+ ${moduleDesription}
4429
+
4430
+ 3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
4431
+ ${eslintDescription}
4432
+
4433
+ 4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
4434
+ ${utilUiDescription}
4435
+
4436
+ 5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
4437
+ ${constant}
4438
+
4439
+ 6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
4440
+ ${properties.map(
4441
+ (property) => `
4442
+ \`\`\`
4443
+ ${property.key}.constant.ts
4444
+
4445
+
4446
+ ${property.source}
4447
+ \`\`\`
4448
+ `
4449
+ ).join("\n\n")}
4450
+
4451
+
4452
+ 7. \uC608\uC2DC \uD30C\uC77C\uB4E4
4453
+ ${exampleFiles.map(
4454
+ (example) => `
4455
+ Example filename: ${example.filepath}
4456
+ \`\`\`
4457
+ ${example.content}
4458
+ \`\`\`
4459
+ `
4460
+ ).join("\n\n")}
4461
+
4462
+
4463
+
4464
+
4465
+
4466
+
4467
+ \uC5ED\uD560\uBD80\uC5EC
4468
+ - Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uC2DC\uB2C8\uC5B4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
4469
+
4470
+ \uCF54\uB529 \uADDC\uCE59
4471
+ - \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4472
+ - \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4473
+ - 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)
4474
+ - \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
4475
+ \uCF54\uB4DC \uC2A4\uD0C0\uC77C
4476
+ - \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
4477
+ - \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
4478
+ - \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
4479
+ - \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
4480
+ \uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
4481
+
4482
+ \uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
4483
+ - UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
4484
+ - \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
4485
+ - \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
4486
+
4487
+ \uC694\uCCAD\uC0AC\uD56D
4488
+ - ${ModelName}.Unit.tsx \uCF54\uB4DC \uC791\uC131
4489
+ - \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
4490
+ - \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
4491
+ - \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.
4492
+
4493
+
4494
+ Application name: ${sysName}
4495
+ Model name: ${modelName}
4496
+
4497
+ Target filename: ${ModelName}.Unit.tsx
3881
4498
  \`\`\`
3882
4499
 
3883
4500
  \`\`\`
@@ -5317,7 +5934,6 @@ var ModuleScript = class {
5317
5934
  }
5318
5935
  async createUnit(sys2) {
5319
5936
  const libs = await sys2.getModules();
5320
- const unitExampleFiles = await sys2.getUnitsSourceCode();
5321
5937
  const lib = await select4({
5322
5938
  message: "Select the lib",
5323
5939
  choices: libs
@@ -5331,10 +5947,11 @@ var ModuleScript = class {
5331
5947
  if (!name)
5332
5948
  return;
5333
5949
  const Name = capitalize(name);
5950
+ const unitExampleFiles = (await sys2.getUnitsSourceCode()).filter((f) => !f.filepath.includes(`${name}.Unit.tsx`));
5334
5951
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5335
5952
  const constant = fs12.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5336
5953
  const session = new AiSession();
5337
- const promptRst = requestView({
5954
+ const promptRst = requestUnit({
5338
5955
  sysName: sys2.name,
5339
5956
  modelName: name,
5340
5957
  ModelName: Name,
@@ -5343,8 +5960,8 @@ var ModuleScript = class {
5343
5960
  exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
5344
5961
  });
5345
5962
  const content = await session.editTypescript(promptRst);
5346
- fs12.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5347
- fs12.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
5963
+ fs12.writeFileSync(`${sys2.cwdPath}/promptUnit.txt`, promptRst);
5964
+ fs12.writeFileSync(`${sys2.cwdPath}/resultUnit.txt`, content);
5348
5965
  }
5349
5966
  async createView(sys2) {
5350
5967
  const libs = await sys2.getModules();
@@ -5360,7 +5977,7 @@ var ModuleScript = class {
5360
5977
  const name = lib.split("/").pop();
5361
5978
  if (!name)
5362
5979
  return;
5363
- const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
5980
+ const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => !f.filepath.includes(`${name}.View.tsx`));
5364
5981
  const Name = capitalize(name);
5365
5982
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5366
5983
  const constant = fs12.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
@@ -5399,7 +6016,8 @@ var ModuleCommand = class {
5399
6016
  async createView(sys2, workspace) {
5400
6017
  await this.moduleScript.createView(sys2);
5401
6018
  }
5402
- async createUnit(name, workspace) {
6019
+ async createUnit(sys2, workspace) {
6020
+ await this.moduleScript.createUnit(sys2);
5403
6021
  }
5404
6022
  };
5405
6023
  __decorateClass([
@@ -5442,7 +6060,7 @@ __decorateClass([
5442
6060
  ], ModuleCommand.prototype, "createView", 1);
5443
6061
  __decorateClass([
5444
6062
  Target.Public(),
5445
- __decorateParam(0, Option("name", { desc: "name of unit module" })),
6063
+ __decorateParam(0, Sys()),
5446
6064
  __decorateParam(1, Workspace())
5447
6065
  ], ModuleCommand.prototype, "createUnit", 1);
5448
6066
  ModuleCommand = __decorateClass([
@@ -5522,60 +6140,12 @@ PageCommand = __decorateClass([
5522
6140
  Commands()
5523
6141
  ], PageCommand);
5524
6142
 
5525
- // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
5526
- import latestVersion2 from "latest-version";
5527
- import path6 from "path";
5528
-
5529
6143
  // pkgs/@akanjs/cli/src/workspace/workspace.runner.ts
5530
6144
  import { v5 as uuid } from "uuid";
6145
+ import { capitalize as capitalize2 } from "lodash";
6146
+ import latestVersion2 from "latest-version";
6147
+ import path6 from "path";
5531
6148
  var WorkspaceRunner = class {
5532
- async createWorkspace(repoName, appName, dirname = ".") {
5533
- }
5534
- async generateMongo(workspace) {
5535
- const namespace = "00000000-0000-0000-0000-000000000000";
5536
- const appNames = await workspace.getApps();
5537
- const apps = appNames.map((appName) => AppExecutor.from(workspace, appName));
5538
- const appDatas = apps.reduce(
5539
- (acc, app) => [
5540
- ...acc,
5541
- ...["debug", "develop", "main"].map((env) => ({
5542
- appName: app.name,
5543
- env,
5544
- secret: getCredentials(app, env)
5545
- }))
5546
- ],
5547
- []
5548
- );
5549
- const mongoConnectionList = {
5550
- type: "Compass Connections",
5551
- version: { $numberInt: "1" },
5552
- connections: appDatas.map(({ appName, env, secret }) => ({
5553
- id: uuid(`${appName}-${env}`, namespace),
5554
- favorite: {
5555
- name: `${appName}-${env}`,
5556
- color: "color9"
5557
- },
5558
- savedConnectionType: "favorite",
5559
- connectionOptions: {
5560
- connectionString: `mongodb://${secret.mongo.account.user.username}:${secret.mongo.account.user.password}@mongo-0.mongo-svc.${appName}-${env}/?directConnection=true&authSource=${appName}-${env}`,
5561
- sshTunnel: {
5562
- host: `${appName}-${env}.akamir.com`,
5563
- port: "32767",
5564
- username: "root",
5565
- password: "akamir"
5566
- }
5567
- }
5568
- }))
5569
- };
5570
- workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
5571
- }
5572
- };
5573
-
5574
- // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
5575
- var WorkspaceScript = class {
5576
- #runner = new WorkspaceRunner();
5577
- applicationScript = new ApplicationScript();
5578
- libraryScript = new LibraryScript();
5579
6149
  async createWorkspace(repoName, appName, dirname = ".") {
5580
6150
  const cwdPath = process.cwd();
5581
6151
  const workspaceRoot = path6.join(cwdPath, dirname, repoName);
@@ -5585,9 +6155,9 @@ var WorkspaceScript = class {
5585
6155
  template: "workspaceRoot",
5586
6156
  dict: {
5587
6157
  repoName,
5588
- RepoName: capitalize(repoName),
6158
+ RepoName: capitalize2(repoName),
5589
6159
  appName,
5590
- AppName: capitalize(appName),
6160
+ AppName: capitalize2(appName),
5591
6161
  serveDomain: "localhost"
5592
6162
  }
5593
6163
  });
@@ -5627,9 +6197,60 @@ var WorkspaceScript = class {
5627
6197
  await workspace.spawn("pnpm", ["install", "--reporter=silent"]);
5628
6198
  workspace.log("Initializing git repository and commit...");
5629
6199
  await workspace.commit("Initial commit", { init: true });
6200
+ return workspace;
6201
+ }
6202
+ async generateMongo(workspace) {
6203
+ const namespace = "00000000-0000-0000-0000-000000000000";
6204
+ const appNames = await workspace.getApps();
6205
+ const apps = appNames.map((appName) => AppExecutor.from(workspace, appName));
6206
+ const appDatas = apps.reduce(
6207
+ (acc, app) => [
6208
+ ...acc,
6209
+ ...["debug", "develop", "main"].map((env) => ({
6210
+ appName: app.name,
6211
+ env,
6212
+ secret: getCredentials(app, env)
6213
+ }))
6214
+ ],
6215
+ []
6216
+ );
6217
+ const mongoConnectionList = {
6218
+ type: "Compass Connections",
6219
+ version: { $numberInt: "1" },
6220
+ connections: appDatas.map(({ appName, env, secret }) => ({
6221
+ id: uuid(`${appName}-${env}`, namespace),
6222
+ favorite: {
6223
+ name: `${appName}-${env}`,
6224
+ color: "color9"
6225
+ },
6226
+ savedConnectionType: "favorite",
6227
+ connectionOptions: {
6228
+ connectionString: `mongodb://${secret.mongo.account.user.username}:${secret.mongo.account.user.password}@mongo-0.mongo-svc.${appName}-${env}/?directConnection=true&authSource=${appName}-${env}`,
6229
+ sshTunnel: {
6230
+ host: `${appName}-${env}.akamir.com`,
6231
+ port: "32767",
6232
+ username: "root",
6233
+ password: "akamir"
6234
+ }
6235
+ }
6236
+ }))
6237
+ };
6238
+ workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
6239
+ }
6240
+ };
6241
+
6242
+ // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
6243
+ var WorkspaceScript = class {
6244
+ #runner = new WorkspaceRunner();
6245
+ applicationScript = new ApplicationScript();
6246
+ libraryScript = new LibraryScript();
6247
+ async createWorkspace(repoName, appName, dirname = ".") {
6248
+ const workspace = await this.#runner.createWorkspace(repoName, appName, dirname);
5630
6249
  await this.libraryScript.installLibrary(workspace, "util");
5631
6250
  await this.libraryScript.installLibrary(workspace, "shared");
5632
6251
  await this.applicationScript.createApplication(appName, workspace);
6252
+ workspace.log(`Workspace created in ${workspace.workspaceRoot}`);
6253
+ Logger.rawLog(`Run \`cd ${repoName} && akan start ${appName}\` to start the development server.`);
5633
6254
  }
5634
6255
  async generateMongo(workspace) {
5635
6256
  await this.#runner.generateMongo(workspace);
@@ -5679,4 +6300,5 @@ void runCommands(
5679
6300
  //! 2. csr폴더를 현 위치로 복사 후 압축 후 삭제
5680
6301
  //! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
5681
6302
  //! add path in tsconfig.json
6303
+ //! 파일을 {name}.Unit.tsx에 저장.
5682
6304
  //! 파일을 {name}.View.tsx에 저장.