@akanjs/cli 0.0.121 → 0.0.123

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/cjs/index.js +1243 -615
  2. package/cjs/src/templates/module/__Model__.Template.js +1 -1
  3. package/cjs/src/templates/module/__Model__.Unit.js +1 -1
  4. package/cjs/src/templates/module/__Model__.Util.js +1 -1
  5. package/cjs/src/templates/module/__Model__.View.js +2 -2
  6. package/cjs/src/templates/module/__Model__.Zone.js +1 -1
  7. package/cjs/src/templates/module/__model__.document.js +1 -1
  8. package/cjs/src/templates/module/__model__.service.js +2 -2
  9. package/cjs/src/templates/module/__model__.signal.spec.js +1 -1
  10. package/cjs/src/templates/module/__model__.signal.test.js +2 -2
  11. package/cjs/src/templates/workspaceRoot/package.json.template +1 -1
  12. package/esm/index.js +1243 -615
  13. package/esm/src/templates/module/__Model__.Template.js +1 -1
  14. package/esm/src/templates/module/__Model__.Unit.js +1 -1
  15. package/esm/src/templates/module/__Model__.Util.js +1 -1
  16. package/esm/src/templates/module/__Model__.View.js +2 -2
  17. package/esm/src/templates/module/__Model__.Zone.js +1 -1
  18. package/esm/src/templates/module/__model__.document.js +1 -1
  19. package/esm/src/templates/module/__model__.service.js +2 -2
  20. package/esm/src/templates/module/__model__.signal.spec.js +1 -1
  21. package/esm/src/templates/module/__model__.signal.test.js +2 -2
  22. package/esm/src/templates/workspaceRoot/package.json.template +1 -1
  23. package/package.json +2 -1
  24. package/src/module/module.command.d.ts +2 -2
  25. package/src/module/module.prompt.d.ts +19 -4
  26. package/src/module/module.script.d.ts +1 -0
  27. package/src/templates/module/__Model__.Template.d.ts +1 -1
  28. package/src/templates/module/__Model__.Unit.d.ts +1 -1
  29. package/src/templates/module/__Model__.Util.d.ts +1 -1
  30. package/src/templates/module/__Model__.View.d.ts +4 -2
  31. package/src/templates/module/__Model__.Zone.d.ts +1 -1
  32. package/src/templates/module/__model__.constant.d.ts +1 -1
  33. package/src/templates/module/__model__.dictionary.d.ts +1 -1
  34. package/src/templates/module/__model__.signal.d.ts +1 -1
  35. package/src/templates/module/__model__.signal.spec.d.ts +1 -1
  36. package/src/templates/module/__model__.signal.test.d.ts +1 -1
  37. package/src/templates/module/__model__.store.d.ts +1 -1
  38. package/src/templates/module/_server.d.ts +1 -1
  39. package/src/workspace/workspace.runner.d.ts +2 -1
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
  \`\`\`
@@ -5166,50 +5783,50 @@ var ModuleRunner = class {
5166
5783
  basePath: `./lib/${name}`,
5167
5784
  template: "module",
5168
5785
  scanResult,
5169
- dict: { model: name, Model: capitalize(name) }
5786
+ dict: { model: name, Model: capitalize(name), sysName: sys2.name, SysName: capitalize(sys2.name) }
5170
5787
  });
5171
5788
  await sys2.scan({ akanConfig });
5172
5789
  return {
5173
- constant: { filename: `${name}.constant.ts`, content: sys2.readFile(`lib/module/${name}/${name}.constant.ts`) },
5790
+ constant: { filename: `${name}.constant.ts`, content: sys2.readFile(`lib/${name}/${name}.constant.ts`) },
5174
5791
  dictionary: {
5175
5792
  filename: `${name}.dictionary.ts`,
5176
- content: sys2.readFile(`lib/module/${name}/${name}.dictionary.ts`)
5793
+ content: sys2.readFile(`lib/${name}/${name}.dictionary.ts`)
5177
5794
  },
5178
5795
  service: {
5179
5796
  filename: `${name}.service.ts`,
5180
- content: sys2.readFile(`lib/module/${name}/${name}.service.ts`)
5797
+ content: sys2.readFile(`lib/${name}/${name}.service.ts`)
5181
5798
  },
5182
5799
  store: {
5183
5800
  filename: `${name}.store.ts`,
5184
- content: sys2.readFile(`lib/module/${name}/${name}.store.ts`)
5801
+ content: sys2.readFile(`lib/${name}/${name}.store.ts`)
5185
5802
  },
5186
5803
  signal: {
5187
5804
  filename: `${name}.signal.ts`,
5188
- content: sys2.readFile(`lib/module/${name}/${name}.signal.ts`)
5805
+ content: sys2.readFile(`lib/${name}/${name}.signal.spec.ts`)
5189
5806
  },
5190
5807
  test: {
5191
5808
  filename: `${name}.test.ts`,
5192
- content: sys2.readFile(`lib/module/${name}/${name}.test.ts`)
5809
+ content: sys2.readFile(`lib/${name}/${name}.signal.test.ts`)
5193
5810
  },
5194
5811
  unit: {
5195
5812
  filename: `${name}.Unit.tsx`,
5196
- content: sys2.readFile(`lib/module/${name}/${name}.Unit.tsx`)
5813
+ content: sys2.readFile(`lib/${name}/${name}.Unit.tsx`)
5197
5814
  },
5198
5815
  view: {
5199
5816
  filename: `${name}.View.tsx`,
5200
- content: sys2.readFile(`lib/module/${name}/${name}.View.tsx`)
5817
+ content: sys2.readFile(`lib/${name}/${name}.View.tsx`)
5201
5818
  },
5202
5819
  template: {
5203
5820
  filename: `${name}.Template.tsx`,
5204
- content: sys2.readFile(`lib/module/${name}/${name}.Template.tsx`)
5821
+ content: sys2.readFile(`lib/${name}/${name}.Template.tsx`)
5205
5822
  },
5206
5823
  zone: {
5207
5824
  filename: `${name}.Zone.tsx`,
5208
- content: sys2.readFile(`lib/module/${name}/${name}.Zone.tsx`)
5825
+ content: sys2.readFile(`lib/${name}/${name}.Zone.tsx`)
5209
5826
  },
5210
5827
  util: {
5211
5828
  filename: `${name}.Util.tsx`,
5212
- content: sys2.readFile(`lib/module/${name}/${name}.Util.tsx`)
5829
+ content: sys2.readFile(`lib/${name}/${name}.Util.tsx`)
5213
5830
  }
5214
5831
  };
5215
5832
  }
@@ -5276,6 +5893,10 @@ var ModuleRunner = class {
5276
5893
  // pkgs/@akanjs/cli/src/module/module.script.ts
5277
5894
  var ModuleScript = class {
5278
5895
  #runner = new ModuleRunner();
5896
+ async createModuleTemplate(sys2, name) {
5897
+ await this.#runner.createModuleTemplate(sys2, name);
5898
+ sys2.log(`Module ${name} created in ${sys2.type}s/${sys2.name}/lib/${name}`);
5899
+ }
5279
5900
  async createModule(sys2) {
5280
5901
  const [appNames, libNames] = await sys2.workspace.getSyss();
5281
5902
  const constantExampleFiles = [
@@ -5296,6 +5917,7 @@ var ModuleScript = class {
5296
5917
  async removeModule(workspace, name) {
5297
5918
  }
5298
5919
  async createScalar(sys2, name, description, schemaDescription) {
5920
+ await AiSession.init();
5299
5921
  const scalarConstantExampleFiles = await sys2.workspace.getScalarConstantFiles();
5300
5922
  const { constant, dictionary } = await this.#runner.createScalarTemplate(sys2, name);
5301
5923
  const session = new AiSession();
@@ -5317,7 +5939,6 @@ var ModuleScript = class {
5317
5939
  }
5318
5940
  async createUnit(sys2) {
5319
5941
  const libs = await sys2.getModules();
5320
- const unitExampleFiles = await sys2.getUnitsSourceCode();
5321
5942
  const lib = await select4({
5322
5943
  message: "Select the lib",
5323
5944
  choices: libs
@@ -5331,10 +5952,11 @@ var ModuleScript = class {
5331
5952
  if (!name)
5332
5953
  return;
5333
5954
  const Name = capitalize(name);
5955
+ const unitExampleFiles = (await sys2.getUnitsSourceCode()).filter((f) => !f.filepath.includes(`${name}.Unit.tsx`));
5334
5956
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5335
5957
  const constant = fs12.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
5336
5958
  const session = new AiSession();
5337
- const promptRst = requestView({
5959
+ const promptRst = requestUnit({
5338
5960
  sysName: sys2.name,
5339
5961
  modelName: name,
5340
5962
  ModelName: Name,
@@ -5343,8 +5965,8 @@ var ModuleScript = class {
5343
5965
  exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
5344
5966
  });
5345
5967
  const content = await session.editTypescript(promptRst);
5346
- fs12.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
5347
- fs12.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
5968
+ fs12.writeFileSync(`${sys2.cwdPath}/promptUnit.txt`, promptRst);
5969
+ fs12.writeFileSync(`${sys2.cwdPath}/resultUnit.txt`, content);
5348
5970
  }
5349
5971
  async createView(sys2) {
5350
5972
  const libs = await sys2.getModules();
@@ -5360,7 +5982,7 @@ var ModuleScript = class {
5360
5982
  const name = lib.split("/").pop();
5361
5983
  if (!name)
5362
5984
  return;
5363
- const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => f.filepath.includes(`${name}.View.tsx`));
5985
+ const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => !f.filepath.includes(`${name}.View.tsx`));
5364
5986
  const Name = capitalize(name);
5365
5987
  const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
5366
5988
  const constant = fs12.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
@@ -5382,8 +6004,8 @@ var ModuleScript = class {
5382
6004
  // pkgs/@akanjs/cli/src/module/module.command.ts
5383
6005
  var ModuleCommand = class {
5384
6006
  moduleScript = new ModuleScript();
5385
- async createModule(sys2, workspace) {
5386
- await this.moduleScript.createModule(sys2);
6007
+ async createModule(sys2, name, workspace) {
6008
+ await this.moduleScript.createModuleTemplate(sys2, name);
5387
6009
  }
5388
6010
  async removeModule(name, workspace) {
5389
6011
  }
@@ -5399,13 +6021,15 @@ var ModuleCommand = class {
5399
6021
  async createView(sys2, workspace) {
5400
6022
  await this.moduleScript.createView(sys2);
5401
6023
  }
5402
- async createUnit(name, workspace) {
6024
+ async createUnit(sys2, workspace) {
6025
+ await this.moduleScript.createUnit(sys2);
5403
6026
  }
5404
6027
  };
5405
6028
  __decorateClass([
5406
6029
  Target.Public(),
5407
6030
  __decorateParam(0, Sys()),
5408
- __decorateParam(1, Workspace())
6031
+ __decorateParam(1, Option("name", { desc: "name of module" })),
6032
+ __decorateParam(2, Workspace())
5409
6033
  ], ModuleCommand.prototype, "createModule", 1);
5410
6034
  __decorateClass([
5411
6035
  Target.Public(),
@@ -5442,7 +6066,7 @@ __decorateClass([
5442
6066
  ], ModuleCommand.prototype, "createView", 1);
5443
6067
  __decorateClass([
5444
6068
  Target.Public(),
5445
- __decorateParam(0, Option("name", { desc: "name of unit module" })),
6069
+ __decorateParam(0, Sys()),
5446
6070
  __decorateParam(1, Workspace())
5447
6071
  ], ModuleCommand.prototype, "createUnit", 1);
5448
6072
  ModuleCommand = __decorateClass([
@@ -5522,60 +6146,12 @@ PageCommand = __decorateClass([
5522
6146
  Commands()
5523
6147
  ], PageCommand);
5524
6148
 
5525
- // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
6149
+ // pkgs/@akanjs/cli/src/workspace/workspace.runner.ts
5526
6150
  import latestVersion2 from "latest-version";
6151
+ import { capitalize as capitalize2 } from "lodash";
5527
6152
  import path6 from "path";
5528
-
5529
- // pkgs/@akanjs/cli/src/workspace/workspace.runner.ts
5530
6153
  import { v5 as uuid } from "uuid";
5531
6154
  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
6155
  async createWorkspace(repoName, appName, dirname = ".") {
5580
6156
  const cwdPath = process.cwd();
5581
6157
  const workspaceRoot = path6.join(cwdPath, dirname, repoName);
@@ -5585,9 +6161,9 @@ var WorkspaceScript = class {
5585
6161
  template: "workspaceRoot",
5586
6162
  dict: {
5587
6163
  repoName,
5588
- RepoName: capitalize(repoName),
6164
+ RepoName: capitalize2(repoName),
5589
6165
  appName,
5590
- AppName: capitalize(appName),
6166
+ AppName: capitalize2(appName),
5591
6167
  serveDomain: "localhost"
5592
6168
  }
5593
6169
  });
@@ -5627,9 +6203,60 @@ var WorkspaceScript = class {
5627
6203
  await workspace.spawn("pnpm", ["install", "--reporter=silent"]);
5628
6204
  workspace.log("Initializing git repository and commit...");
5629
6205
  await workspace.commit("Initial commit", { init: true });
6206
+ return workspace;
6207
+ }
6208
+ async generateMongo(workspace) {
6209
+ const namespace = "00000000-0000-0000-0000-000000000000";
6210
+ const appNames = await workspace.getApps();
6211
+ const apps = appNames.map((appName) => AppExecutor.from(workspace, appName));
6212
+ const appDatas = apps.reduce(
6213
+ (acc, app) => [
6214
+ ...acc,
6215
+ ...["debug", "develop", "main"].map((env) => ({
6216
+ appName: app.name,
6217
+ env,
6218
+ secret: getCredentials(app, env)
6219
+ }))
6220
+ ],
6221
+ []
6222
+ );
6223
+ const mongoConnectionList = {
6224
+ type: "Compass Connections",
6225
+ version: { $numberInt: "1" },
6226
+ connections: appDatas.map(({ appName, env, secret }) => ({
6227
+ id: uuid(`${appName}-${env}`, namespace),
6228
+ favorite: {
6229
+ name: `${appName}-${env}`,
6230
+ color: "color9"
6231
+ },
6232
+ savedConnectionType: "favorite",
6233
+ connectionOptions: {
6234
+ connectionString: `mongodb://${secret.mongo.account.user.username}:${secret.mongo.account.user.password}@mongo-0.mongo-svc.${appName}-${env}/?directConnection=true&authSource=${appName}-${env}`,
6235
+ sshTunnel: {
6236
+ host: `${appName}-${env}.akamir.com`,
6237
+ port: "32767",
6238
+ username: "root",
6239
+ password: "akamir"
6240
+ }
6241
+ }
6242
+ }))
6243
+ };
6244
+ workspace.writeJson(`infra/master/mongo-connections.json`, mongoConnectionList);
6245
+ }
6246
+ };
6247
+
6248
+ // pkgs/@akanjs/cli/src/workspace/workspace.script.ts
6249
+ var WorkspaceScript = class {
6250
+ #runner = new WorkspaceRunner();
6251
+ applicationScript = new ApplicationScript();
6252
+ libraryScript = new LibraryScript();
6253
+ async createWorkspace(repoName, appName, dirname = ".") {
6254
+ const workspace = await this.#runner.createWorkspace(repoName, appName, dirname);
5630
6255
  await this.libraryScript.installLibrary(workspace, "util");
5631
6256
  await this.libraryScript.installLibrary(workspace, "shared");
5632
6257
  await this.applicationScript.createApplication(appName, workspace);
6258
+ workspace.log(`Workspace created in ${workspace.workspaceRoot}`);
6259
+ Logger.rawLog(`Run \`cd ${repoName} && akan start ${appName}\` to start the development server.`);
5633
6260
  }
5634
6261
  async generateMongo(workspace) {
5635
6262
  await this.#runner.generateMongo(workspace);
@@ -5679,4 +6306,5 @@ void runCommands(
5679
6306
  //! 2. csr폴더를 현 위치로 복사 후 압축 후 삭제
5680
6307
  //! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
5681
6308
  //! add path in tsconfig.json
6309
+ //! 파일을 {name}.Unit.tsx에 저장.
5682
6310
  //! 파일을 {name}.View.tsx에 저장.