@akanjs/cli 0.0.134 → 0.0.136
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/index.js +992 -1221
- package/cjs/src/templates/app/middleware.js +1 -1
- package/cjs/src/templates/module/_server.js +2 -2
- package/esm/index.js +992 -1221
- package/esm/src/templates/app/middleware.js +1 -1
- package/esm/src/templates/module/_server.js +2 -2
- package/package.json +1 -1
- package/src/module/module.command.d.ts +1 -0
- package/src/module/module.prompt.d.ts +19 -2
- package/src/module/module.runner.d.ts +6 -0
- package/src/module/module.script.d.ts +1 -0
package/esm/index.js
CHANGED
|
@@ -446,6 +446,11 @@ var Logger = class _Logger {
|
|
|
446
446
|
}
|
|
447
447
|
};
|
|
448
448
|
|
|
449
|
+
// pkgs/@akanjs/common/lowerlize.ts
|
|
450
|
+
var lowerlize = (str) => {
|
|
451
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
452
|
+
};
|
|
453
|
+
|
|
449
454
|
// pkgs/@akanjs/common/sleep.ts
|
|
450
455
|
var sleep = async (ms) => {
|
|
451
456
|
return new Promise((resolve) => {
|
|
@@ -2095,6 +2100,9 @@ var getArgumentValue = async (argMeta, value, workspace) => {
|
|
|
2095
2100
|
throw new Error(`Invalid system type: ${argMeta.type}`);
|
|
2096
2101
|
};
|
|
2097
2102
|
var runCommands = async (...commands) => {
|
|
2103
|
+
process.on("unhandledRejection", (error) => {
|
|
2104
|
+
console.error(chalk2.red("[fatal]"), error);
|
|
2105
|
+
});
|
|
2098
2106
|
const hasPackageJson = fs9.existsSync(`${__dirname}/../package.json`);
|
|
2099
2107
|
const version = hasPackageJson ? JSON.parse(fs9.readFileSync(`${__dirname}/../package.json`, "utf8")).version : "0.0.1";
|
|
2100
2108
|
program.version(version).description("Akan CLI");
|
|
@@ -2505,1031 +2513,6 @@ import tsconfigPaths from "vite-tsconfig-paths";
|
|
|
2505
2513
|
|
|
2506
2514
|
// pkgs/@akanjs/cli/src/module/module.prompt.ts
|
|
2507
2515
|
var frameworkDescription = `
|
|
2508
|
-
\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.
|
|
2509
|
-
|
|
2510
|
-
\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.
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
\uAC00\uC7A5 \uC678\uBD80\uC758 \uAD6C\uC870\uB294
|
|
2515
|
-
|
|
2516
|
-
- app
|
|
2517
|
-
|
|
2518
|
-
- project1
|
|
2519
|
-
|
|
2520
|
-
- project2
|
|
2521
|
-
|
|
2522
|
-
- project3
|
|
2523
|
-
|
|
2524
|
-
- project4
|
|
2525
|
-
|
|
2526
|
-
- lib
|
|
2527
|
-
|
|
2528
|
-
- core
|
|
2529
|
-
|
|
2530
|
-
- external
|
|
2531
|
-
|
|
2532
|
-
- game
|
|
2533
|
-
|
|
2534
|
-
- mint
|
|
2535
|
-
|
|
2536
|
-
- platform
|
|
2537
|
-
|
|
2538
|
-
- shared
|
|
2539
|
-
|
|
2540
|
-
- social
|
|
2541
|
-
|
|
2542
|
-
- util
|
|
2543
|
-
|
|
2544
|
-
app\uC740 \uAC01 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uB294 \uACF3\uC774\uC57C
|
|
2545
|
-
|
|
2546
|
-
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.
|
|
2547
|
-
|
|
2548
|
-
\uB2E4\uC74C\uC740 app/project \uB0B4\uBD80\uC758 \uAD6C\uC870\uB97C \uC54C\uB824\uC904\uAC8C.
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
project
|
|
2553
|
-
|
|
2554
|
-
- app
|
|
2555
|
-
|
|
2556
|
-
- [lang]
|
|
2557
|
-
|
|
2558
|
-
- (projectName)
|
|
2559
|
-
|
|
2560
|
-
- (user)
|
|
2561
|
-
|
|
2562
|
-
- page.tsx
|
|
2563
|
-
|
|
2564
|
-
- layout.tsx
|
|
2565
|
-
|
|
2566
|
-
- (public)
|
|
2567
|
-
|
|
2568
|
-
- page.tsx
|
|
2569
|
-
|
|
2570
|
-
- layout.tsx
|
|
2571
|
-
|
|
2572
|
-
- (admin)
|
|
2573
|
-
|
|
2574
|
-
- page.tsx
|
|
2575
|
-
|
|
2576
|
-
- layout.tsx
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
- lib
|
|
2581
|
-
|
|
2582
|
-
- dataName1
|
|
2583
|
-
|
|
2584
|
-
- dataName2
|
|
2585
|
-
|
|
2586
|
-
- dataName3
|
|
2587
|
-
|
|
2588
|
-
- dataName4
|
|
2589
|
-
|
|
2590
|
-
- dataName5
|
|
2591
|
-
|
|
2592
|
-
- dataName6
|
|
2593
|
-
|
|
2594
|
-
- dataName7
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
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.
|
|
2599
|
-
|
|
2600
|
-
public/page.tsx\uAC00 \uAC00\uC7A5 \uCD5C\uCD08\uB85C \uC811\uADFC\uB418\uB294 Index \uD398\uC774\uC9C0\uAC00 \uB420 \uAC70\uC57C.
|
|
2601
|
-
|
|
2602
|
-
\uC544\uB798\uB294 public/page.tsx\uC758 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC18C\uC2A4\uCF54\uB4DC\uC57C.
|
|
2603
|
-
|
|
2604
|
-
\`\`\`
|
|
2605
|
-
|
|
2606
|
-
import {{ Image, Link }} from "@util/ui";
|
|
2607
|
-
|
|
2608
|
-
import {{ getSelf }} from "@akanjs/client";
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
export default function Page() {{
|
|
2613
|
-
|
|
2614
|
-
const self = getSelf();
|
|
2615
|
-
|
|
2616
|
-
return (
|
|
2617
|
-
|
|
2618
|
-
<div className="relative w-full h-screen overflow-hidden flex items-center justify-center">
|
|
2619
|
-
|
|
2620
|
-
<Image
|
|
2621
|
-
|
|
2622
|
-
className="absolute left-0 right-0 top-0 bottom-0 w-full h-screen -z-50"
|
|
2623
|
-
|
|
2624
|
-
width={{1920}}
|
|
2625
|
-
|
|
2626
|
-
height={{1080}}
|
|
2627
|
-
|
|
2628
|
-
src="/back.jpg"
|
|
2629
|
-
|
|
2630
|
-
/>
|
|
2631
|
-
|
|
2632
|
-
<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">
|
|
2633
|
-
|
|
2634
|
-
<h1 className="text-4xl mt-2"><%= project %></h1>
|
|
2635
|
-
|
|
2636
|
-
<h2 className="text-lg"><%= project %> description</h2>
|
|
2637
|
-
|
|
2638
|
-
<Link className="w-full" href={{self ? "/home" : "/signin"}}>
|
|
2639
|
-
|
|
2640
|
-
<button className="btn w-full btn-primary">Go to dashboard</button>
|
|
2641
|
-
|
|
2642
|
-
</Link>
|
|
2643
|
-
|
|
2644
|
-
</div>
|
|
2645
|
-
|
|
2646
|
-
</div>
|
|
2647
|
-
|
|
2648
|
-
);
|
|
2649
|
-
|
|
2650
|
-
}}
|
|
2651
|
-
|
|
2652
|
-
\`\`\`
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
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.
|
|
2657
|
-
|
|
2658
|
-
\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.
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
\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.
|
|
2663
|
-
|
|
2664
|
-
\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.
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
\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.
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
\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.
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
pencil
|
|
2677
|
-
|
|
2678
|
-
- pencil.constant.ts ( pencil\uC5D0 \uB300\uD55C db schema, query, sort \uAD6C\uBB38\uC744 \uC815\uC758 )
|
|
2679
|
-
|
|
2680
|
-
- 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.)
|
|
2681
|
-
|
|
2682
|
-
- 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. )
|
|
2683
|
-
|
|
2684
|
-
- 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 )
|
|
2685
|
-
|
|
2686
|
-
- 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.)
|
|
2687
|
-
|
|
2688
|
-
- pencil.store.ts (pencil field\uC5D0 \uB300\uD55C \uC0C1\uD0DC\uAD00\uB9AC \uC800\uC7A5\uC18C.)
|
|
2689
|
-
|
|
2690
|
-
- 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. )
|
|
2691
|
-
|
|
2692
|
-
- 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. )
|
|
2693
|
-
|
|
2694
|
-
- 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. )
|
|
2695
|
-
|
|
2696
|
-
- pencil.Util.tsx (Action \uBC84\uD2BC\uC744 \uC815\uC758\uD558\uB294 \uACF3. client component\uB85C \uC815\uC758\uB428. )
|
|
2697
|
-
|
|
2698
|
-
- pencil.View.tsx (\uB2E8\uC77C view \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uC815\uC758\uD558\uB294 \uACF3. server component\uB85C \uC815\uC758\uB428. )
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
\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.
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
document, signal, service\uB294 \uBC31\uC5D4\uB4DC\uC640 \uC5F0\uAD00\uB418\uC5B4\uC788\uB294 \uC18C\uC2A4\uCF54\uB4DC\uC57C.
|
|
2708
|
-
|
|
2709
|
-
\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.
|
|
2710
|
-
|
|
2711
|
-
signal - document
|
|
2712
|
-
|
|
2713
|
-
signal - service - document
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
store\uB294 \uD504\uB860\uD2B8\uC5D4\uB4DC\uC5D0\uC11C \uC0C1\uD0DC\uAD00\uB9AC\uB97C \uD560 \uB54C \uC0AC\uC6A9\uB3FC.
|
|
2718
|
-
|
|
2719
|
-
\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.
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
\uC774\uB807\uAC8C 11\uAC1C\uC758 \uD30C\uC77C\uB85C \uAD6C\uBD84\uD574\uC11C \uC815\uC758\uAC00 \uB3FC.
|
|
2724
|
-
|
|
2725
|
-
\uC9C0\uAE08\uBD80\uD134 \uD55C \uD30C\uC77C\uB4E4\uB9C8\uB2E4 \uC0C1\uC138\uD55C \uC124\uBA85\uC744 \uD574\uC904\uAC8C.
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
model.constant.ts
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
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.
|
|
2734
|
-
|
|
2735
|
-
\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
|
|
2736
|
-
|
|
2737
|
-
\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.
|
|
2738
|
-
|
|
2739
|
-
\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.
|
|
2740
|
-
|
|
2741
|
-
\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.
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
\`\`\`
|
|
2746
|
-
|
|
2747
|
-
import { enumOf, Int } from "@akanjs/base";
|
|
2748
|
-
|
|
2749
|
-
import { Field, Filter, Model, sortOf, via } from "@akanjs/constant";
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
export const \${dict.Model}Statuses = ["active"] as const;
|
|
2754
|
-
|
|
2755
|
-
export type \${dict.Model}Status = (typeof \${dict.Model}Statuses)[number];
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
//\uB370\uC774\uD130\uB97C \uB9CC\uB4E4 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130 \uD0C0\uC785\uC744 \uC815\uC758\uD558\uB294 \uACF3
|
|
2760
|
-
|
|
2761
|
-
@Model.Input("\${dict.Model}Input")
|
|
2762
|
-
|
|
2763
|
-
export class \${dict.Model}Input {{
|
|
2764
|
-
|
|
2765
|
-
@Field.Prop(() => String)
|
|
2766
|
-
|
|
2767
|
-
field: string;
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
@Field.Prop(() => Int, {{ nullable: true }})
|
|
2772
|
-
|
|
2773
|
-
fieldInt: number | null;
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
@Field.Prop(() => Date, {{default: dayjs()}})
|
|
2778
|
-
|
|
2779
|
-
fieldInt: Dayjs;
|
|
2780
|
-
|
|
2781
|
-
}}
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
//\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
|
|
2786
|
-
|
|
2787
|
-
@Model.Object("\${dict.Model}Object")
|
|
2788
|
-
|
|
2789
|
-
export class \${dict.Model}Object extends via(\${dict.Model}Input) {
|
|
2790
|
-
|
|
2791
|
-
@Field.Prop(() => String, {{ enum: \${dict.Model}Statuses, default: "active" }})
|
|
2792
|
-
|
|
2793
|
-
status: \${dict.Model}Status;
|
|
2794
|
-
|
|
2795
|
-
}}
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
//\uB370\uC774\uD130\uB97C \uB9AC\uC2A4\uD2B8\uB85C \uBCF4\uC5EC\uC904 \uB54C \uD544\uC694\uD55C \uB370\uC774\uD130\uB9CC \uC81C\uACF5\uD558\uB294 \uACF3
|
|
2800
|
-
|
|
2801
|
-
@Model.Light("Light\${dict.Model}")
|
|
2802
|
-
|
|
2803
|
-
export class Light\${dict.Model} extends via(\${dict.Model}Object, [
|
|
2804
|
-
|
|
2805
|
-
"field",
|
|
2806
|
-
|
|
2807
|
-
"status",
|
|
2808
|
-
|
|
2809
|
-
] as const) {}
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
//\uCD5C\uC885 \uB370\uC774\uD130\uC758 Full \uD0C0\uC785\uC774 \uC815\uC758\uB418\uB294 \uACF3
|
|
2814
|
-
|
|
2815
|
-
@Model.Full("\${dict.Model}")
|
|
2816
|
-
|
|
2817
|
-
export class \${dict.Model} extends via(\${dict.Model}Object, Light\${dict.Model}) {}
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
//\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
|
|
2822
|
-
|
|
2823
|
-
@Model.Insight("\${dict.Model}Insight")
|
|
2824
|
-
|
|
2825
|
-
export class \${dict.Model}Insight {{
|
|
2826
|
-
|
|
2827
|
-
@Field.Prop(() => Int, {{ default: 0, accumulate: {{ $sum: 1 }} }})
|
|
2828
|
-
|
|
2829
|
-
count: number;
|
|
2830
|
-
|
|
2831
|
-
}}
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
//\uB370\uC774\uD130\uC758 \uD1B5\uACC4\uB97C \uACC4\uC0B0\uD558\uB294 \uACF3
|
|
2836
|
-
|
|
2837
|
-
@Model.Summary("\${dict.Model}Summary")
|
|
2838
|
-
|
|
2839
|
-
export class \${dict.Model}Summary {{
|
|
2840
|
-
|
|
2841
|
-
@Field.Prop(() => Int, {{ min: 0, default: 0, query: {{ status: {{}} }} }})
|
|
2842
|
-
|
|
2843
|
-
total\${dict.Model}: number;
|
|
2844
|
-
|
|
2845
|
-
}}
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
@Model.Filter("\${dict.Model}Filter")
|
|
2850
|
-
|
|
2851
|
-
export class \${dict.Model}Filter extends sortOf(\${dict.Model}, {}) {}
|
|
2852
|
-
|
|
2853
|
-
\`\`\`
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
model.dictonary.ts
|
|
2859
|
-
|
|
2860
|
-
\`\`\`
|
|
2861
|
-
|
|
2862
|
-
import {
|
|
2863
|
-
|
|
2864
|
-
baseTrans,
|
|
2865
|
-
|
|
2866
|
-
getBaseSignalTrans,
|
|
2867
|
-
|
|
2868
|
-
ModelDictionary,
|
|
2869
|
-
|
|
2870
|
-
SignalDictionary,
|
|
2871
|
-
|
|
2872
|
-
SummaryDictionary,
|
|
2873
|
-
|
|
2874
|
-
} from "@akanjs/dictionary";
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
import type { \${dict.Model}, \${dict.Model}Filter, \${dict.Model}Insight, \${dict.Model}Summary } from "./\${dict.model}.constant";
|
|
2879
|
-
|
|
2880
|
-
import type { \${dict.Model}Signal } from "./\${dict.model}.signal";
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
const modelDictionary = {{
|
|
2885
|
-
|
|
2886
|
-
...baseTrans,
|
|
2887
|
-
|
|
2888
|
-
modelName: ["\${dict.Model}", "\${dict.Model}"],
|
|
2889
|
-
|
|
2890
|
-
modelDesc: [
|
|
2891
|
-
|
|
2892
|
-
"\${dict.Model} description",
|
|
2893
|
-
|
|
2894
|
-
"\${dict.Model} \uC124\uBA85",
|
|
2895
|
-
|
|
2896
|
-
],
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
// * ==================== Model ==================== * //
|
|
2901
|
-
|
|
2902
|
-
field: ["Field", "\uD544\uB4DC"],
|
|
2903
|
-
|
|
2904
|
-
"desc-field": ["Field", "\uD544\uB4DC"],
|
|
2905
|
-
|
|
2906
|
-
// * ==================== Model ==================== * //
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
// * ==================== Insight ==================== * //
|
|
2911
|
-
|
|
2912
|
-
count: ["Count", "\uAC1C\uC218"],
|
|
2913
|
-
|
|
2914
|
-
"desc-count": ["\${dict.Model} count in current query settting", "\uD604\uC7AC \uCFFC\uB9AC \uC124\uC815\uC5D0 \uB9DE\uB294 \${dict.Model} \uC218"],
|
|
2915
|
-
|
|
2916
|
-
// * ==================== Insight ==================== * //
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
// * ==================== Filter ==================== * //
|
|
2921
|
-
|
|
2922
|
-
// * ==================== Filter ==================== * //
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
// * ==================== Etc ==================== * //
|
|
2927
|
-
|
|
2928
|
-
"enum-status-active": ["Active", "\uD65C\uC131"],
|
|
2929
|
-
|
|
2930
|
-
"enumdesc-status-active": ["Active status", "\uD65C\uC131 \uC0C1\uD0DC"],
|
|
2931
|
-
|
|
2932
|
-
// * ==================== Etc ==================== * //
|
|
2933
|
-
|
|
2934
|
-
}} satisfies ModelDictionary<\${dict.Model}, \${dict.Model}Insight, typeof \${dict.Model}Sort>;
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
export const \${dict.Model}SummaryDictionary = {{
|
|
2939
|
-
|
|
2940
|
-
// * ==================== Summary ==================== * //
|
|
2941
|
-
|
|
2942
|
-
total\${dict.Model}: ["Total \${dict.Model}", "\uCD1D \${dict.Model} \uC218"],
|
|
2943
|
-
|
|
2944
|
-
"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"],
|
|
2945
|
-
|
|
2946
|
-
// * ==================== Summary ==================== * //
|
|
2947
|
-
|
|
2948
|
-
}} satisfies SummaryDictionary<\${dict.Model}Summary>;
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
const signalDictionary = {{
|
|
2953
|
-
|
|
2954
|
-
...getBaseSignalTrans("\${dict.Model}" as const),
|
|
2955
|
-
|
|
2956
|
-
// * ==================== Endpoint ==================== * //
|
|
2957
|
-
|
|
2958
|
-
"api-\${dict.Model}ListInPublic": ["\${dict.Model} List In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uB9AC\uC2A4\uD2B8"],
|
|
2959
|
-
|
|
2960
|
-
"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"],
|
|
2961
|
-
|
|
2962
|
-
"arg-\${dict.Model}ListInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
|
|
2963
|
-
|
|
2964
|
-
"argdesc-\${dict.Model}ListInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
|
|
2965
|
-
|
|
2966
|
-
"arg-\${dict.Model}ListInPublic-skip": ["Skip", "\uAC74\uB108\uB6F0\uAE30"],
|
|
2967
|
-
|
|
2968
|
-
"argdesc-\${dict.Model}ListInPublic-skip": ["Number of items to skip", "\uAC74\uB108\uB6F8 \uC544\uC774\uD15C \uC218"],
|
|
2969
|
-
|
|
2970
|
-
"arg-\${dict.Model}ListInPublic-limit": ["Limit", "\uC81C\uD55C"],
|
|
2971
|
-
|
|
2972
|
-
"argdesc-\${dict.Model}ListInPublic-limit": ["Maximum number of items to return", "\uBC18\uD658\uD560 \uCD5C\uB300 \uC544\uC774\uD15C \uC218"],
|
|
2973
|
-
|
|
2974
|
-
"arg-\${dict.Model}ListInPublic-sort": ["Sort", "\uC815\uB82C"],
|
|
2975
|
-
|
|
2976
|
-
"argdesc-\${dict.Model}ListInPublic-sort": ["Sort order of the items", "\uC544\uC774\uD15C\uC758 \uC815\uB82C \uC21C\uC11C"],
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
"api-\${dict.Model}InsightInPublic": ["\${dict.Model} Insight In Public", "\uACF5\uAC1C\uB41C \${dict.Model} \uC778\uC0AC\uC774\uD2B8"],
|
|
2981
|
-
|
|
2982
|
-
"apidesc-\${dict.Model}InsightInPublic": [
|
|
2983
|
-
|
|
2984
|
-
"Get insight data for public \${dict.Model}",
|
|
2985
|
-
|
|
2986
|
-
"\uACF5\uAC1C\uB41C \${dict.Model}\uC5D0 \uB300\uD55C \uC778\uC0AC\uC774\uD2B8 \uB370\uC774\uD130\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4",
|
|
2987
|
-
|
|
2988
|
-
],
|
|
2989
|
-
|
|
2990
|
-
"arg-\${dict.Model}InsightInPublic-statuses": ["Statuses", "\uC0C1\uD0DC"],
|
|
2991
|
-
|
|
2992
|
-
"argdesc-\${dict.Model}InsightInPublic-statuses": ["Statuses to filter", "\uD544\uD130\uB9C1\uD560 \uC0C1\uD0DC"],
|
|
2993
|
-
|
|
2994
|
-
// * ==================== Endpoint ==================== * //
|
|
2995
|
-
|
|
2996
|
-
}} satisfies SignalDictionary<\${dict.Model}Signal, \${dict.Model}>;
|
|
2997
|
-
|
|
2998
|
-
\`\`\`
|
|
2999
|
-
|
|
3000
|
-
export const \${dict.model}Dictionary = {{ ...modelDictionary, ...signalDictionary }};
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
model.document.ts
|
|
3007
|
-
|
|
3008
|
-
\`\`\`
|
|
3009
|
-
|
|
3010
|
-
import { beyond, by, Database, into, type SchemaOf } from "@akanjs/document";
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
import { cnst } from "../cnst";
|
|
3015
|
-
|
|
3016
|
-
@Database.Input(() => cnst.\${dict.Model}Input)
|
|
3017
|
-
|
|
3018
|
-
export class \${dict.Model}Input extends by(cnst.\${dict.Model}Input) {}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
@Database.Document(() => cnst.\${dict.Model})
|
|
3023
|
-
|
|
3024
|
-
export class \${dict.Model} extends by(cnst.\${dict.Model}) {}
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
@Database.Model(() => cnst.\${dict.Model})
|
|
3029
|
-
|
|
3030
|
-
export class \${dict.Model}Model extends into(\${dict.Model}, cnst.\${dict.Model}Cnst) {
|
|
3031
|
-
|
|
3032
|
-
async getSummary(): Promise<cnst.\${dict.Model}Summary> {
|
|
3033
|
-
|
|
3034
|
-
return {
|
|
3035
|
-
|
|
3036
|
-
...(await this.getDefaultSummary()),
|
|
3037
|
-
|
|
3038
|
-
};
|
|
3039
|
-
|
|
3040
|
-
}
|
|
3041
|
-
|
|
3042
|
-
}
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
@Database.Middleware(() => cnst.\${dict.Model})
|
|
3047
|
-
|
|
3048
|
-
export class \${dict.Model}Middleware extends beyond(\${dict.Model}Model, \${dict.Model}) {
|
|
3049
|
-
|
|
3050
|
-
onSchema(schema: SchemaOf<\${dict.Model}Model, \${dict.Model}>) {
|
|
3051
|
-
|
|
3052
|
-
// schema.index({ status: 1 })
|
|
3053
|
-
|
|
3054
|
-
}
|
|
3055
|
-
|
|
3056
|
-
}
|
|
3057
|
-
|
|
3058
|
-
\`\`\`
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
model.signal.ts
|
|
3064
|
-
|
|
3065
|
-
\`\`\`
|
|
3066
|
-
|
|
3067
|
-
import { Int } from "@akanjs/base";
|
|
3068
|
-
|
|
3069
|
-
import { SortOf } from "@akanjs/constant";
|
|
3070
|
-
|
|
3071
|
-
import { Arg, DbSignal, Mutation, Query, resolve, Signal } from "@akanjs/signal";
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
import { cnst, Srvs } from "../cnst";
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
@Signal(() => cnst.\${dict.Model})
|
|
3080
|
-
|
|
3081
|
-
export class \${dict.Model}Signal extends DbSignal(cnst.\${dict.model}Cnst, Srvs, {
|
|
3082
|
-
|
|
3083
|
-
guards: { get: Query.Public, cru: Mutation.Public },
|
|
3084
|
-
|
|
3085
|
-
}) {
|
|
3086
|
-
|
|
3087
|
-
// * /////////////////////////////////////
|
|
3088
|
-
|
|
3089
|
-
// * Public Slice
|
|
3090
|
-
|
|
3091
|
-
@Query.Public(() => [cnst.\${dict.Model}])
|
|
3092
|
-
|
|
3093
|
-
async \${dict.model}ListInPublic(
|
|
3094
|
-
|
|
3095
|
-
@Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null,
|
|
3096
|
-
|
|
3097
|
-
@Arg.Query("skip", () => Int, { nullable: true }) skip: number | null,
|
|
3098
|
-
|
|
3099
|
-
@Arg.Query("limit", () => Int, { nullable: true }) limit: number | null,
|
|
3100
|
-
|
|
3101
|
-
@Arg.Query("sort", () => String, { nullable: true }) sort: SortOf<cnst.\${dict.Model}Filter> | null
|
|
3102
|
-
|
|
3103
|
-
) {
|
|
3104
|
-
|
|
3105
|
-
const \${dict.models} = await this.\${dict.model}Service.listByStatuses(statuses, { skip, limit, sort });
|
|
3106
|
-
|
|
3107
|
-
return resolve<cnst.\${dict.Model}[]>(\${dict.models});
|
|
3108
|
-
|
|
3109
|
-
}
|
|
3110
|
-
|
|
3111
|
-
@Query.Public(() => cnst.\${dict.Model}Insight)
|
|
3112
|
-
|
|
3113
|
-
async \${dict.model}InsightInPublic(
|
|
3114
|
-
|
|
3115
|
-
@Arg.Query("statuses", () => [String], { nullable: true }) statuses: cnst.\${dict.Model}Status[] | null
|
|
3116
|
-
|
|
3117
|
-
) {
|
|
3118
|
-
|
|
3119
|
-
const \${dict.model}Insight = await this.\${dict.model}Service.insightByStatuses(statuses);
|
|
3120
|
-
|
|
3121
|
-
return resolve<cnst.\${dict.Model}Insight>(\${dict.model}Insight);
|
|
3122
|
-
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
// * Public Slice
|
|
3126
|
-
|
|
3127
|
-
// * /////////////////////////////////////
|
|
3128
|
-
|
|
3129
|
-
}
|
|
3130
|
-
|
|
3131
|
-
\`\`\`
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
model.service.ts
|
|
3137
|
-
|
|
3138
|
-
\`\`\`
|
|
3139
|
-
|
|
3140
|
-
import { DbService, Service } from "@akanjs/service";
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
import { cnst } from "../cnst";
|
|
3145
|
-
|
|
3146
|
-
import * as db from "../db";
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
@Service("\${dict.Model}Service")
|
|
3151
|
-
|
|
3152
|
-
export class \${dict.Model}Service extends DbService(db.\${dict.Model}Db) {
|
|
3153
|
-
|
|
3154
|
-
async summarize(): Promise<cnst.\${dict.Model}Summary> {
|
|
3155
|
-
|
|
3156
|
-
return {
|
|
3157
|
-
|
|
3158
|
-
...(await this.\${dict.Model}Model.getSummary()),
|
|
3159
|
-
|
|
3160
|
-
};
|
|
3161
|
-
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
|
-
}
|
|
3165
|
-
|
|
3166
|
-
\`\`\`
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
model.store.ts
|
|
3172
|
-
|
|
3173
|
-
\`\`\`
|
|
3174
|
-
|
|
3175
|
-
import { stateOf, Store } from "@akanjs/store";
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
import { cnst } from "../cnst";
|
|
3180
|
-
|
|
3181
|
-
import { fetch } from "../fetch";
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
@Store(() => cnst.\${dict.Model})
|
|
3186
|
-
|
|
3187
|
-
export class \${dict.Model}Store extends stateOf(fetch.\${dict.model}Gql, {
|
|
3188
|
-
|
|
3189
|
-
// state
|
|
3190
|
-
|
|
3191
|
-
}) {
|
|
3192
|
-
|
|
3193
|
-
// action
|
|
3194
|
-
|
|
3195
|
-
}
|
|
3196
|
-
|
|
3197
|
-
\`\`\`
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
model.Zone.tsx
|
|
3203
|
-
|
|
3204
|
-
\`\`\`
|
|
3205
|
-
|
|
3206
|
-
"use client";
|
|
3207
|
-
|
|
3208
|
-
import { Data, Load } from "@shared/ui";
|
|
3209
|
-
|
|
3210
|
-
import { ModelsProps } from "@akanjs/client";
|
|
3211
|
-
|
|
3212
|
-
import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
|
|
3213
|
-
|
|
3214
|
-
import { ClientInit, ClientView, DefaultOf } from "@akanjs/signal";
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
export const Admin = ({ sliceName = "\${dict.model}", init, query }: ModelsProps<cnst.\${dict.Model}>>) => {
|
|
3219
|
-
|
|
3220
|
-
return (
|
|
3221
|
-
|
|
3222
|
-
<Data.ListContainer
|
|
3223
|
-
|
|
3224
|
-
init={init}
|
|
3225
|
-
|
|
3226
|
-
query={query}
|
|
3227
|
-
|
|
3228
|
-
sliceName={sliceName}
|
|
3229
|
-
|
|
3230
|
-
renderItem={\${dict.Model}.Unit.Card}
|
|
3231
|
-
|
|
3232
|
-
renderDashboard={\${dict.Model}.Util.Stat}
|
|
3233
|
-
|
|
3234
|
-
renderInsight={\${dict.Model}.Util.Insight}
|
|
3235
|
-
|
|
3236
|
-
renderTemplate={\${dict.Model}.Template.General}
|
|
3237
|
-
|
|
3238
|
-
renderTitle={(\${dict.model}: DefaultOf<cnst.\${dict.Model}>>) => \`\${dict.Model} - \${\${dict.model}.id ? \${dict.model}.id : "New"}\`}
|
|
3239
|
-
|
|
3240
|
-
renderView={(\${dict.model}: cnst.\${dict.Model}>) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />}
|
|
3241
|
-
|
|
3242
|
-
columns={[
|
|
3243
|
-
|
|
3244
|
-
"id",
|
|
3245
|
-
|
|
3246
|
-
"status",
|
|
3247
|
-
|
|
3248
|
-
"createdAt",
|
|
3249
|
-
|
|
3250
|
-
"updatedAt",
|
|
3251
|
-
|
|
3252
|
-
]}
|
|
3253
|
-
|
|
3254
|
-
actions={(\${dict.model}: cnst.Light\${dict.Model}, idx) => ["remove", "edit", "view"]}
|
|
3255
|
-
|
|
3256
|
-
/>
|
|
3257
|
-
|
|
3258
|
-
);
|
|
3259
|
-
|
|
3260
|
-
};
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
interface CardProps {
|
|
3265
|
-
|
|
3266
|
-
className?: string;
|
|
3267
|
-
|
|
3268
|
-
init: ClientInit<"\${dict.model}", cnst.Light\${dict.Model}>;
|
|
3269
|
-
|
|
3270
|
-
}
|
|
3271
|
-
|
|
3272
|
-
export const Card = ({ className, init }: CardProps) => {
|
|
3273
|
-
|
|
3274
|
-
return (
|
|
3275
|
-
|
|
3276
|
-
<Load.Units
|
|
3277
|
-
|
|
3278
|
-
className={className}
|
|
3279
|
-
|
|
3280
|
-
init={init}
|
|
3281
|
-
|
|
3282
|
-
renderItem={(\${dict.model}: cnst.Light\${dict.Model}) => (
|
|
3283
|
-
|
|
3284
|
-
<\${dict.Model}.Unit.Card key={\${dict.model}.id} href={\`/\${dict.model}/\${\${dict.model}.id}\`} \${dict.model}={\${dict.model}} />
|
|
3285
|
-
|
|
3286
|
-
)}
|
|
3287
|
-
|
|
3288
|
-
/>
|
|
3289
|
-
|
|
3290
|
-
);
|
|
3291
|
-
|
|
3292
|
-
};
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
interface ViewProps {
|
|
3297
|
-
|
|
3298
|
-
className?: string;
|
|
3299
|
-
|
|
3300
|
-
view: ClientView<"\${dict.model}", cnst.\${dict.Model}>;
|
|
3301
|
-
|
|
3302
|
-
}
|
|
3303
|
-
|
|
3304
|
-
export const View = ({ view }: ViewProps) => {
|
|
3305
|
-
|
|
3306
|
-
return <Load.View view={view} renderView={(\${dict.model}) => <\${dict.Model}.View.General \${dict.model}={\${dict.model}} />} />;
|
|
3307
|
-
|
|
3308
|
-
};
|
|
3309
|
-
|
|
3310
|
-
\`\`\`
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
model.Templete.tsx
|
|
3315
|
-
|
|
3316
|
-
\`\`\`
|
|
3317
|
-
|
|
3318
|
-
"use client";
|
|
3319
|
-
|
|
3320
|
-
import { cnst, st, usePage } from "@\${dict.appName}/client";
|
|
3321
|
-
|
|
3322
|
-
import { Field } from "@shared/ui";
|
|
3323
|
-
|
|
3324
|
-
import { Layout } from "@util/ui";
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
interface \${dict.Model}EditProps {
|
|
3329
|
-
|
|
3330
|
-
\${dict.model}Id?: string | null;
|
|
3331
|
-
|
|
3332
|
-
}
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
export const General = ({ \${dict.model}Id = undefined }: \${dict.Model}EditProps) => {
|
|
3337
|
-
|
|
3338
|
-
const \${dict.model}Form = st.use.\${dict.model}Form();
|
|
3339
|
-
|
|
3340
|
-
const { l } = usePage();
|
|
3341
|
-
|
|
3342
|
-
return (
|
|
3343
|
-
|
|
3344
|
-
<Layout.Template>
|
|
3345
|
-
|
|
3346
|
-
<Field.Text
|
|
3347
|
-
|
|
3348
|
-
label={l.field("\${dict.model}", "id")}
|
|
3349
|
-
|
|
3350
|
-
desc={l.desc("\${dict.model}", "id")}
|
|
3351
|
-
|
|
3352
|
-
value={\${dict.model}Form.id}
|
|
3353
|
-
|
|
3354
|
-
onChange={st.do.setIdOn\${dict.Model}}
|
|
3355
|
-
|
|
3356
|
-
/>
|
|
3357
|
-
|
|
3358
|
-
</Layout.Template>
|
|
3359
|
-
|
|
3360
|
-
);
|
|
3361
|
-
|
|
3362
|
-
};
|
|
3363
|
-
|
|
3364
|
-
\`\`\`
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
model.Unit.tsx
|
|
3370
|
-
|
|
3371
|
-
\`\`\`
|
|
3372
|
-
|
|
3373
|
-
import { ModelProps } from "@akanjs/client";
|
|
3374
|
-
|
|
3375
|
-
import { cnst, \${dict.Model} } from "@\${dict.appName}/client";
|
|
3376
|
-
|
|
3377
|
-
import { Link } from "@util/ui";
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
export const Card = ({ \${dict.model}, href }: ModelProps<"\${dict.model}", cnst.Light\${dict.Model}>>) => {
|
|
3382
|
-
|
|
3383
|
-
return (
|
|
3384
|
-
|
|
3385
|
-
<Link href={href} className="animate-fadeIn w-full h-36 flex rounded-lg shadow-sm hover:shadow-lg duration-300">
|
|
3386
|
-
|
|
3387
|
-
<div>{\${dict.model}.id}</div>
|
|
3388
|
-
|
|
3389
|
-
</Link>
|
|
3390
|
-
|
|
3391
|
-
);
|
|
3392
|
-
|
|
3393
|
-
};
|
|
3394
|
-
|
|
3395
|
-
\`\`\`
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
model.Util.tsx
|
|
3401
|
-
|
|
3402
|
-
\`\`\`
|
|
3403
|
-
|
|
3404
|
-
"use client";
|
|
3405
|
-
|
|
3406
|
-
import { ModelDashboardProps, ModelInsightProps } from "@akanjs/client";
|
|
3407
|
-
|
|
3408
|
-
import { getQueryMap } from "@akanjs/constant";
|
|
3409
|
-
|
|
3410
|
-
import { cnst } from "@\${dict.appName}/client";
|
|
3411
|
-
|
|
3412
|
-
import { Data } from "@shared/ui";
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
export const Stat = ({
|
|
3417
|
-
|
|
3418
|
-
className,
|
|
3419
|
-
|
|
3420
|
-
summary,
|
|
3421
|
-
|
|
3422
|
-
sliceName = "\${dict.model}",
|
|
3423
|
-
|
|
3424
|
-
queryMap = getQueryMap(cnst.\${dict.Model}Summary),
|
|
3425
|
-
|
|
3426
|
-
hidePresents,
|
|
3427
|
-
|
|
3428
|
-
}: ModelDashboardProps<cnst.Summary>) => {
|
|
3429
|
-
|
|
3430
|
-
return (
|
|
3431
|
-
|
|
3432
|
-
<Data.Dashboard
|
|
3433
|
-
|
|
3434
|
-
className={className}
|
|
3435
|
-
|
|
3436
|
-
summary={summary}
|
|
3437
|
-
|
|
3438
|
-
sliceName={sliceName}
|
|
3439
|
-
|
|
3440
|
-
queryMap={queryMap}
|
|
3441
|
-
|
|
3442
|
-
columns={["total\${dict.Model}"]}
|
|
3443
|
-
|
|
3444
|
-
hidePresents={hidePresents}
|
|
3445
|
-
|
|
3446
|
-
/>
|
|
3447
|
-
|
|
3448
|
-
);
|
|
3449
|
-
|
|
3450
|
-
};
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
export const Insight = ({
|
|
3455
|
-
|
|
3456
|
-
className,
|
|
3457
|
-
|
|
3458
|
-
insight,
|
|
3459
|
-
|
|
3460
|
-
sliceName = "\${dict.model}",
|
|
3461
|
-
|
|
3462
|
-
}: ModelInsightProps<cnst.\${dict.Model}Insight>) => {
|
|
3463
|
-
|
|
3464
|
-
return (
|
|
3465
|
-
|
|
3466
|
-
<Data.Insight
|
|
3467
|
-
|
|
3468
|
-
className={className}
|
|
3469
|
-
|
|
3470
|
-
insight={insight}
|
|
3471
|
-
|
|
3472
|
-
sliceName={sliceName}
|
|
3473
|
-
|
|
3474
|
-
columns={["count"]}
|
|
3475
|
-
|
|
3476
|
-
/>
|
|
3477
|
-
|
|
3478
|
-
);
|
|
3479
|
-
|
|
3480
|
-
};
|
|
3481
|
-
|
|
3482
|
-
\`\`\`
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
model.View.tsx
|
|
3488
|
-
|
|
3489
|
-
\`\`\`
|
|
3490
|
-
|
|
3491
|
-
import { clsx } from "@akanjs/client";
|
|
3492
|
-
|
|
3493
|
-
import { cnst } from "@\${dict.appName}/client";
|
|
3494
|
-
|
|
3495
|
-
import { Image } from "@util/ui";
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
interface \${dict.Model}ViewProps {
|
|
3500
|
-
|
|
3501
|
-
className?: string;
|
|
3502
|
-
|
|
3503
|
-
\${dict.model}: cnst.\${dict.Model};
|
|
3504
|
-
|
|
3505
|
-
self?: { id?: string } | null;
|
|
3506
|
-
|
|
3507
|
-
}
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
export const General = ({ className, \${dict.model}, self }: \${dict.Model}ViewProps) => {
|
|
3512
|
-
|
|
3513
|
-
return (
|
|
3514
|
-
|
|
3515
|
-
<div className={clsx(className, "animate-fadeIn w-full")}>
|
|
3516
|
-
|
|
3517
|
-
<div>{\${dict.model}.id}</div>
|
|
3518
|
-
|
|
3519
|
-
</div>
|
|
3520
|
-
|
|
3521
|
-
);
|
|
3522
|
-
|
|
3523
|
-
};
|
|
3524
|
-
|
|
3525
|
-
\`\`\`
|
|
3526
|
-
|
|
3527
|
-
\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.
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
\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.
|
|
3532
|
-
|
|
3533
2516
|
`;
|
|
3534
2517
|
var moduleDesription = `
|
|
3535
2518
|
|
|
@@ -3965,6 +2948,767 @@ var utilUiDescription = `
|
|
|
3965
2948
|
- Modern React patterns (hooks, context, providers)
|
|
3966
2949
|
- Error handling and validation systems
|
|
3967
2950
|
`;
|
|
2951
|
+
var shardUiDescription = `
|
|
2952
|
+
Shared UI Library Analysis
|
|
2953
|
+
|
|
2954
|
+
Library Overview
|
|
2955
|
+
|
|
2956
|
+
The shared UI library in the akansoft project is a comprehensive React component collection designed for building data-driven
|
|
2957
|
+
applications. It provides a complete toolkit with consistent patterns, extensive customization options, and deep integration with the
|
|
2958
|
+
application's store system.
|
|
2959
|
+
|
|
2960
|
+
Key Characteristics
|
|
2961
|
+
|
|
2962
|
+
- Store-Centric Architecture: Deep integration with standardized store slices and naming conventions
|
|
2963
|
+
- Type-Safe Components: Extensive TypeScript generic usage for compile-time safety
|
|
2964
|
+
- Internationalization Ready: Built-in multi-language support throughout all components
|
|
2965
|
+
- Responsive Design: Mobile-first approach with adaptive breakpoints
|
|
2966
|
+
- Performance Optimized: Memoization, lazy loading, and efficient re-rendering
|
|
2967
|
+
- Accessibility Compliant: Proper ARIA attributes and keyboard navigation
|
|
2968
|
+
- Extensible Architecture: Plugin systems and customizable renderers
|
|
2969
|
+
- Unidirectional Data Flow: Predictable state management patterns
|
|
2970
|
+
|
|
2971
|
+
Component Categories
|
|
2972
|
+
|
|
2973
|
+
1. Field Components (Field.tsx)
|
|
2974
|
+
|
|
2975
|
+
Field.tsx is a core form component library for the akansoft project, providing more than 25 specialized input fields.
|
|
2976
|
+
|
|
2977
|
+
## Basic Structure and Common Features
|
|
2978
|
+
|
|
2979
|
+
### Label Component
|
|
2980
|
+
|
|
2981
|
+
\`\`\`typescript
|
|
2982
|
+
interface LabelProps {
|
|
2983
|
+
className?: string;
|
|
2984
|
+
label: string;
|
|
2985
|
+
desc?: string;
|
|
2986
|
+
unit?: string;
|
|
2987
|
+
nullable?: boolean;
|
|
2988
|
+
mode?: "view" | "edit";
|
|
2989
|
+
}
|
|
2990
|
+
\`\`\`
|
|
2991
|
+
- Purpose: Consistent label display for all fields
|
|
2992
|
+
- Features:
|
|
2993
|
+
- Help tooltip support (desc)
|
|
2994
|
+
- Unit display (unit)
|
|
2995
|
+
- Optional field display (nullable)
|
|
2996
|
+
- Required indicator is commented out (design decision)
|
|
2997
|
+
|
|
2998
|
+
## Text Input Components
|
|
2999
|
+
|
|
3000
|
+
### 1. Field.Text
|
|
3001
|
+
|
|
3002
|
+
\`\`\`typescript
|
|
3003
|
+
interface TextProps {
|
|
3004
|
+
label?: string;
|
|
3005
|
+
desc?: string;
|
|
3006
|
+
value: string | null;
|
|
3007
|
+
onChange: (value: string) => void;
|
|
3008
|
+
placeholder?: string;
|
|
3009
|
+
nullable?: boolean;
|
|
3010
|
+
disabled?: boolean;
|
|
3011
|
+
minlength?: number; // Default: nullable ? 0 : 2
|
|
3012
|
+
maxlength?: number; // Default: 200
|
|
3013
|
+
transform?: (value: string) => string;
|
|
3014
|
+
validate?: (text: string) => boolean | string;
|
|
3015
|
+
cache?: boolean; // Form caching support
|
|
3016
|
+
onPressEnter?: () => void;
|
|
3017
|
+
inputStyleType?: "bordered" | "borderless" | "underline";
|
|
3018
|
+
}
|
|
3019
|
+
\`\`\`
|
|
3020
|
+
Key features:
|
|
3021
|
+
- Real-time transformation (transform)
|
|
3022
|
+
- Automatic cache key generation: \${label}-\${desc}-text
|
|
3023
|
+
- Length validation and custom validation
|
|
3024
|
+
- Various input styles supported
|
|
3025
|
+
|
|
3026
|
+
### 2. Field.TextArea
|
|
3027
|
+
|
|
3028
|
+
\`\`\`typescript
|
|
3029
|
+
interface TextAreaProps {
|
|
3030
|
+
// Same basic props as Text +
|
|
3031
|
+
rows?: number; // Default: 3
|
|
3032
|
+
maxlength?: number; // Default: 1000
|
|
3033
|
+
}
|
|
3034
|
+
\`\`\`
|
|
3035
|
+
Key features:
|
|
3036
|
+
- Multi-line text input
|
|
3037
|
+
- Adjustable height (rows)
|
|
3038
|
+
- Longer maximum length than Text
|
|
3039
|
+
|
|
3040
|
+
### 3. Field.Price (to be deprecated)
|
|
3041
|
+
|
|
3042
|
+
\`\`\`typescript
|
|
3043
|
+
interface PriceProps {
|
|
3044
|
+
// Similar to Text but specialized for prices
|
|
3045
|
+
maxlength?: number; // Default: 80
|
|
3046
|
+
placeholder?: string; // Default: "~ \${l('shared.priceUnit')}"
|
|
3047
|
+
}
|
|
3048
|
+
\`\`\`
|
|
3049
|
+
Key features:
|
|
3050
|
+
- Automatic removal of commas and spaces
|
|
3051
|
+
- Automatic price unit placeholder
|
|
3052
|
+
- Marked as "delete" in comments - legacy component
|
|
3053
|
+
|
|
3054
|
+
## List Management Components
|
|
3055
|
+
|
|
3056
|
+
### 4. Field.List
|
|
3057
|
+
|
|
3058
|
+
\`\`\`typescript
|
|
3059
|
+
interface ListProps<Item> {
|
|
3060
|
+
label?: string;
|
|
3061
|
+
value: Item[];
|
|
3062
|
+
onChange: (value: Item[]) => void;
|
|
3063
|
+
onAdd: () => void;
|
|
3064
|
+
renderItem: (item: Item, idx: number) => ReactNode;
|
|
3065
|
+
}
|
|
3066
|
+
\`\`\`
|
|
3067
|
+
Key features:
|
|
3068
|
+
- Generic type supporting all item types
|
|
3069
|
+
- Custom rendering for each item
|
|
3070
|
+
- Automatic delete button addition
|
|
3071
|
+
- Automatic divider insertion
|
|
3072
|
+
|
|
3073
|
+
### 5. Field.TextList
|
|
3074
|
+
|
|
3075
|
+
\`\`\`typescript
|
|
3076
|
+
interface TextListProps {
|
|
3077
|
+
value: string[];
|
|
3078
|
+
onChange: (value: string[]) => void;
|
|
3079
|
+
minlength?: number; // Minimum array length, Default: 0
|
|
3080
|
+
maxlength?: number; // Maximum array length, Default: 50
|
|
3081
|
+
minTextlength?: number; // Minimum individual text length, Default: 2
|
|
3082
|
+
maxTextlength?: number; // Maximum individual text length, Default: 200
|
|
3083
|
+
transform?: (value: string) => string;
|
|
3084
|
+
validate?: (text: string) => boolean | string;
|
|
3085
|
+
cache?: boolean;
|
|
3086
|
+
}
|
|
3087
|
+
\`\`\`
|
|
3088
|
+
Key features:
|
|
3089
|
+
- Drag and drop for order changes
|
|
3090
|
+
- Individual text input validation
|
|
3091
|
+
- Cache key: \${label}-\${desc}-textList-[\${idx}]
|
|
3092
|
+
- Conditional "New" button display based on maximum length limit
|
|
3093
|
+
|
|
3094
|
+
### 6. Field.Tags
|
|
3095
|
+
|
|
3096
|
+
\`\`\`typescript
|
|
3097
|
+
interface TagsProps {
|
|
3098
|
+
value: string[];
|
|
3099
|
+
onChange: (value: string[]) => void;
|
|
3100
|
+
minlength?: number; // Default: 0
|
|
3101
|
+
maxlength?: number; // Default: 50
|
|
3102
|
+
minTextlength?: number; // Default: 2
|
|
3103
|
+
maxTextlength?: number; // Default: 10 (tags are shorter)
|
|
3104
|
+
transform?: (value: string) => string;
|
|
3105
|
+
validate?: (text: string) => boolean | string;
|
|
3106
|
+
}
|
|
3107
|
+
\`\`\`
|
|
3108
|
+
Key features:
|
|
3109
|
+
- Tag style UI (includes # prefix)
|
|
3110
|
+
- Inline editing mode
|
|
3111
|
+
- Creates additional input field when clicked
|
|
3112
|
+
- Cancel editing with ESC key
|
|
3113
|
+
- Complete tag addition with Enter/Blur
|
|
3114
|
+
|
|
3115
|
+
## Numeric Input Components
|
|
3116
|
+
|
|
3117
|
+
### 7. Field.Number
|
|
3118
|
+
|
|
3119
|
+
\`\`\`typescript
|
|
3120
|
+
interface NumberProps {
|
|
3121
|
+
value: number | null;
|
|
3122
|
+
onChange: (value: number) => void;
|
|
3123
|
+
min?: number;
|
|
3124
|
+
max?: number;
|
|
3125
|
+
unit?: string;
|
|
3126
|
+
transform?: (value: number) => number;
|
|
3127
|
+
validate?: (text: number) => boolean | string;
|
|
3128
|
+
formatter?: (value: string) => string; // Display format
|
|
3129
|
+
parser?: (value: string) => string; // Parsing format
|
|
3130
|
+
cache?: boolean;
|
|
3131
|
+
}
|
|
3132
|
+
\`\`\`
|
|
3133
|
+
Key features:
|
|
3134
|
+
- Automatic number validation and min/max checks
|
|
3135
|
+
- Customizable display format with formatter/parser
|
|
3136
|
+
- Unit display support
|
|
3137
|
+
- Cache key: \${label}-\${desc}-number
|
|
3138
|
+
|
|
3139
|
+
### 8. Field.DoubleNumber
|
|
3140
|
+
|
|
3141
|
+
\`\`\`typescript
|
|
3142
|
+
interface DoubleNumberProps {
|
|
3143
|
+
value: [number, number] | null;
|
|
3144
|
+
onChange: (value: [number, number]) => void;
|
|
3145
|
+
min?: [number, number] | null;
|
|
3146
|
+
max?: [number, number] | null;
|
|
3147
|
+
separator?: ReactNode | string; // Separator between inputs
|
|
3148
|
+
}
|
|
3149
|
+
\`\`\`
|
|
3150
|
+
Key features:
|
|
3151
|
+
- Range input (start-end values)
|
|
3152
|
+
- Independent min/max validation for each
|
|
3153
|
+
- Custom separator (e.g., "~", "-")
|
|
3154
|
+
- Cache keys: \${label}-\${desc}-number-[0], \${label}-\${desc}-number-[1]
|
|
3155
|
+
|
|
3156
|
+
## Selection Components
|
|
3157
|
+
|
|
3158
|
+
### 9. Field.Switch
|
|
3159
|
+
|
|
3160
|
+
\`\`\`typescript
|
|
3161
|
+
interface SwitchProps {
|
|
3162
|
+
value: boolean;
|
|
3163
|
+
onChange: (value: boolean) => void;
|
|
3164
|
+
onDesc?: string; // Description when true
|
|
3165
|
+
offDesc?: string; // Description when false
|
|
3166
|
+
disabled?: boolean;
|
|
3167
|
+
}
|
|
3168
|
+
\`\`\`
|
|
3169
|
+
Key features:
|
|
3170
|
+
- DaisyUI toggle style
|
|
3171
|
+
- State-specific description text
|
|
3172
|
+
- Uses toggle-accent class
|
|
3173
|
+
|
|
3174
|
+
### 10. Field.ToggleSelect
|
|
3175
|
+
|
|
3176
|
+
\`\`\`typescript
|
|
3177
|
+
interface ToggleSelectProps<I> {
|
|
3178
|
+
items: { label: string; value: I }[] | readonly I[] | I[] | Enum<I>;
|
|
3179
|
+
value: I | null;
|
|
3180
|
+
onChange: (value: I) => void;
|
|
3181
|
+
model?: string; // Model name for internationalization
|
|
3182
|
+
field?: string; // Field name for internationalization
|
|
3183
|
+
validate?: (value: I) => boolean | string;
|
|
3184
|
+
btnClassName?: string;
|
|
3185
|
+
}
|
|
3186
|
+
\`\`\`
|
|
3187
|
+
Key features:
|
|
3188
|
+
- Button-style single selection
|
|
3189
|
+
- Direct Enum type support
|
|
3190
|
+
- Automatic internationalization (l.enum(model, field, item))
|
|
3191
|
+
- Custom button styling
|
|
3192
|
+
|
|
3193
|
+
### 11. Field.MultiToggleSelect
|
|
3194
|
+
|
|
3195
|
+
\`\`\`typescript
|
|
3196
|
+
interface MultiToggleSelectProps<I> {
|
|
3197
|
+
items: Enum<I> | { label: string; value: I }[] | readonly I[] | I[];
|
|
3198
|
+
value: I[];
|
|
3199
|
+
onChange: (value: I[]) => void;
|
|
3200
|
+
minlength?: number;
|
|
3201
|
+
maxlength?: number;
|
|
3202
|
+
validate?: (value: I[]) => boolean | string;
|
|
3203
|
+
}
|
|
3204
|
+
\`\`\`
|
|
3205
|
+
Key features:
|
|
3206
|
+
- Multiple selection button UI
|
|
3207
|
+
- Minimum/maximum selection limit
|
|
3208
|
+
- Array length validation
|
|
3209
|
+
|
|
3210
|
+
## Relational Data Selection Components
|
|
3211
|
+
|
|
3212
|
+
### 12. Field.Parent & Field.ParentId
|
|
3213
|
+
|
|
3214
|
+
\`\`\`typescript
|
|
3215
|
+
interface ParentProps<T, State, Input, Full, Light, Sort, QueryArgs> {
|
|
3216
|
+
sliceName: string; // Target slice name
|
|
3217
|
+
value: Light | null; // Parent returns object
|
|
3218
|
+
onChange: (value?: Light | null) => void;
|
|
3219
|
+
initArgs?: any[]; // Initialization arguments
|
|
3220
|
+
sortOption?: (a: Light, b: Light) => number;
|
|
3221
|
+
renderOption: (model: Light) => ReactNode; // Option renderer
|
|
3222
|
+
renderSelected?: (value: Light) => ReactNode; // Selected item renderer
|
|
3223
|
+
onSearch?: (text: string) => void; // Search handler
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
interface ParentIdProps extends ParentProps {
|
|
3227
|
+
value: string | null; // ParentId returns only ID
|
|
3228
|
+
onChange: (id?: string | null, model?: Light | null) => void;
|
|
3229
|
+
}
|
|
3230
|
+
\`\`\`
|
|
3231
|
+
Key features:
|
|
3232
|
+
- Dynamic store slice integration
|
|
3233
|
+
- Automatic naming convention: \${modelName}List, init\${ModelName}, etc.
|
|
3234
|
+
- Searchable dropdown
|
|
3235
|
+
- Lazy loading (data fetched on onOpen)
|
|
3236
|
+
- Parent: returns full object, ParentId: returns only ID
|
|
3237
|
+
|
|
3238
|
+
### 13. Field.Children & Field.ChildrenId
|
|
3239
|
+
|
|
3240
|
+
\`\`\`typescript
|
|
3241
|
+
interface ChildrenProps extends ParentProps {
|
|
3242
|
+
value: Light[]; // Multiple selection
|
|
3243
|
+
onChange: (value?: Light[] | null) => void;
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3246
|
+
interface ChildrenIdProps extends ChildrenProps {
|
|
3247
|
+
value: string[]; // ID array
|
|
3248
|
+
onChange: (value: string[]) => void;
|
|
3249
|
+
}
|
|
3250
|
+
\`\`\`
|
|
3251
|
+
Key features:
|
|
3252
|
+
- Multiple relationship selection
|
|
3253
|
+
- Same store integration logic as Parent
|
|
3254
|
+
- Automatic initialization (useEffect)
|
|
3255
|
+
|
|
3256
|
+
## Date/Time Components
|
|
3257
|
+
|
|
3258
|
+
### 14. Field.Date
|
|
3259
|
+
|
|
3260
|
+
\`\`\`typescript
|
|
3261
|
+
interface DateProps<Nullable extends boolean> {
|
|
3262
|
+
value: Nullable extends true ? Dayjs | null : Dayjs;
|
|
3263
|
+
onChange: (value: Dayjs) => void;
|
|
3264
|
+
min?: Dayjs;
|
|
3265
|
+
max?: Dayjs;
|
|
3266
|
+
showTime?: boolean; // datetime-local vs date
|
|
3267
|
+
nullable?: boolean;
|
|
3268
|
+
}
|
|
3269
|
+
\`\`\`
|
|
3270
|
+
Key features:
|
|
3271
|
+
- Uses Dayjs objects
|
|
3272
|
+
- Conditional nullable type (using TypeScript generics)
|
|
3273
|
+
- Automatic format change based on showTime
|
|
3274
|
+
- Uses HTML5 date/datetime-local inputs
|
|
3275
|
+
- Includes comment about DaisyUI max value bug
|
|
3276
|
+
|
|
3277
|
+
### 15. Field.DateRange
|
|
3278
|
+
|
|
3279
|
+
\`\`\`typescript
|
|
3280
|
+
interface DateRangeProps<Nullable extends boolean> {
|
|
3281
|
+
from: Nullable extends true ? Dayjs | null : Dayjs;
|
|
3282
|
+
to: Nullable extends true ? Dayjs | null : Dayjs;
|
|
3283
|
+
onChangeFrom: (value: Dayjs) => void;
|
|
3284
|
+
onChangeTo: (value: Dayjs) => void;
|
|
3285
|
+
onChange?: (from: Dayjs, to: Dayjs) => void; // Optional unified handler
|
|
3286
|
+
showTime?: boolean;
|
|
3287
|
+
}
|
|
3288
|
+
\`\`\`
|
|
3289
|
+
Key features:
|
|
3290
|
+
- Individual management of start/end dates
|
|
3291
|
+
- Optional unified change handler
|
|
3292
|
+
- Automatic "From"/"To" label display
|
|
3293
|
+
- Responsive layout (vertical on mobile)
|
|
3294
|
+
|
|
3295
|
+
## File Upload Components
|
|
3296
|
+
|
|
3297
|
+
### 16. Field.Img
|
|
3298
|
+
|
|
3299
|
+
\`\`\`typescript
|
|
3300
|
+
interface ImageProps {
|
|
3301
|
+
sliceName: string; // Determines file upload API
|
|
3302
|
+
value: cnst.File | null;
|
|
3303
|
+
onChange: (file: cnst.File | null) => void;
|
|
3304
|
+
styleType?: "circle" | "square"; // Default: "circle"
|
|
3305
|
+
aspectRatio?: number[]; // Aspect ratio restriction
|
|
3306
|
+
render?: (file: cnst.File) => ReactNode;
|
|
3307
|
+
disabled?: boolean;
|
|
3308
|
+
}
|
|
3309
|
+
\`\`\`
|
|
3310
|
+
Key features:
|
|
3311
|
+
- Dynamic upload API: add\${capitalize(sliceName)}Files
|
|
3312
|
+
- Upload status polling (1-second interval)
|
|
3313
|
+
- Aspect ratio restriction support
|
|
3314
|
+
- Circular/square preview
|
|
3315
|
+
|
|
3316
|
+
### 17. Field.Imgs
|
|
3317
|
+
|
|
3318
|
+
\`\`\`typescript
|
|
3319
|
+
interface ImagesProps {
|
|
3320
|
+
sliceName: string;
|
|
3321
|
+
value: cnst.File[];
|
|
3322
|
+
onChange: (files: cnst.File[]) => void;
|
|
3323
|
+
minlength?: number; // Default: 1
|
|
3324
|
+
maxlength?: number; // Default: 30
|
|
3325
|
+
render?: (file: cnst.File) => ReactNode;
|
|
3326
|
+
}
|
|
3327
|
+
\`\`\`
|
|
3328
|
+
Key features:
|
|
3329
|
+
- Multiple image upload
|
|
3330
|
+
- Batch polling of upload status
|
|
3331
|
+
- Minimum/maximum file count limit
|
|
3332
|
+
- Fixed square style
|
|
3333
|
+
|
|
3334
|
+
### 18. Field.File & Field.Files
|
|
3335
|
+
|
|
3336
|
+
\`\`\`typescript
|
|
3337
|
+
interface FileProps {
|
|
3338
|
+
sliceName: string;
|
|
3339
|
+
value: cnst.File | null; // File is single
|
|
3340
|
+
onChange: (file: cnst.File | null) => void;
|
|
3341
|
+
render?: (file: cnst.File) => ReactNode;
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
interface FilesProps {
|
|
3345
|
+
sliceName: string;
|
|
3346
|
+
value: cnst.File[]; // Files is multiple
|
|
3347
|
+
onChange: (files: cnst.File[]) => void;
|
|
3348
|
+
minlength?: number; // Default: 1
|
|
3349
|
+
maxlength?: number; // Default: 30
|
|
3350
|
+
}
|
|
3351
|
+
\`\`\`
|
|
3352
|
+
Key features:
|
|
3353
|
+
- Support for all file types (beyond images)
|
|
3354
|
+
- Same upload logic as Img/Imgs
|
|
3355
|
+
- Custom file renderer support
|
|
3356
|
+
|
|
3357
|
+
## Rich Text Editor
|
|
3358
|
+
|
|
3359
|
+
### 19. Field.Slate
|
|
3360
|
+
|
|
3361
|
+
\`\`\`typescript
|
|
3362
|
+
interface SlateProps {
|
|
3363
|
+
sliceName: string; // Determines file upload API
|
|
3364
|
+
valuePath: string; // Store path
|
|
3365
|
+
onChange: (value: unknown) => void;
|
|
3366
|
+
addFile: (file: cnst.File | cnst.File[], options?) => void;
|
|
3367
|
+
placeholder?: string;
|
|
3368
|
+
disabled?: boolean;
|
|
3369
|
+
editorHeight?: string;
|
|
3370
|
+
}
|
|
3371
|
+
\`\`\`
|
|
3372
|
+
Key features:
|
|
3373
|
+
- Slate.js-based rich text editor
|
|
3374
|
+
- File drag and drop support
|
|
3375
|
+
- Dynamic store path access
|
|
3376
|
+
- Adjustable height
|
|
3377
|
+
|
|
3378
|
+
### 20. Field.Yoopta
|
|
3379
|
+
|
|
3380
|
+
\`\`\`typescript
|
|
3381
|
+
interface YooptaProps {
|
|
3382
|
+
value: JSON;
|
|
3383
|
+
onChange: (value: JSON) => void;
|
|
3384
|
+
readonly?: boolean;
|
|
3385
|
+
}
|
|
3386
|
+
\`\`\`
|
|
3387
|
+
Key features:
|
|
3388
|
+
- Yoopta editor integration
|
|
3389
|
+
- JSON data format
|
|
3390
|
+
- Read-only mode support
|
|
3391
|
+
|
|
3392
|
+
## Authentication and Contact Components
|
|
3393
|
+
|
|
3394
|
+
### 21. Field.Email
|
|
3395
|
+
|
|
3396
|
+
\`\`\`typescript
|
|
3397
|
+
interface EmailProps {
|
|
3398
|
+
value: string | null;
|
|
3399
|
+
onChange: (value: string) => void;
|
|
3400
|
+
placeholder?: string; // Default: "example@email.com"
|
|
3401
|
+
minlength?: number; // Default: nullable ? 0 : 2
|
|
3402
|
+
maxlength?: number; // Default: 80
|
|
3403
|
+
inputStyleType?: "bordered" | "borderless" | "underline";
|
|
3404
|
+
cache?: boolean;
|
|
3405
|
+
}
|
|
3406
|
+
\`\`\`
|
|
3407
|
+
Key features:
|
|
3408
|
+
- Automatic email format validation
|
|
3409
|
+
- Uses Input.Email component
|
|
3410
|
+
- Cache key: \${label}-\${desc}-email
|
|
3411
|
+
|
|
3412
|
+
### 22. Field.Phone
|
|
3413
|
+
|
|
3414
|
+
\`\`\`typescript
|
|
3415
|
+
interface PhoneProps {
|
|
3416
|
+
value: string | null;
|
|
3417
|
+
onChange: (value: string) => void;
|
|
3418
|
+
maxlength?: number; // Default: 13
|
|
3419
|
+
transform?: (value: string) => string; // Default: formatPhone
|
|
3420
|
+
cache?: boolean;
|
|
3421
|
+
}
|
|
3422
|
+
\`\`\`
|
|
3423
|
+
Key features:
|
|
3424
|
+
- Automatic phone number formatting (formatPhone)
|
|
3425
|
+
- isPhoneNumber validation
|
|
3426
|
+
- Cache key: \${label}-\${desc}-phone
|
|
3427
|
+
|
|
3428
|
+
### 23. Field.Password
|
|
3429
|
+
|
|
3430
|
+
\`\`\`typescript
|
|
3431
|
+
interface PasswordProps {
|
|
3432
|
+
value: string | null;
|
|
3433
|
+
onChange: (value: string) => void;
|
|
3434
|
+
confirmValue?: string | null; // Confirmation input
|
|
3435
|
+
onChangeConfirm?: (value: string) => void;
|
|
3436
|
+
showConfirm?: boolean; // Show confirmation input
|
|
3437
|
+
minlength?: number; // Default: nullable ? 0 : 8
|
|
3438
|
+
maxlength?: number; // Default: 20
|
|
3439
|
+
cache?: boolean;
|
|
3440
|
+
}
|
|
3441
|
+
\`\`\`
|
|
3442
|
+
Key features:
|
|
3443
|
+
- Optional password confirmation input
|
|
3444
|
+
- Automatic match validation
|
|
3445
|
+
- Secure input (masking)
|
|
3446
|
+
- Cache key: \${label}-\${desc}-password
|
|
3447
|
+
|
|
3448
|
+
## Geographic Location Components
|
|
3449
|
+
|
|
3450
|
+
### 24. Field.Coordinate
|
|
3451
|
+
|
|
3452
|
+
\`\`\`typescript
|
|
3453
|
+
interface CoordinateProps {
|
|
3454
|
+
coordinate: cnst.util.Coordinate | null;
|
|
3455
|
+
onChange: (coordinate: cnst.util.Coordinate) => void;
|
|
3456
|
+
mapKey: string; // Google Maps API key
|
|
3457
|
+
mapClassName?: string;
|
|
3458
|
+
disabled?: boolean;
|
|
3459
|
+
}
|
|
3460
|
+
\`\`\`
|
|
3461
|
+
Key features:
|
|
3462
|
+
- Google Maps integration
|
|
3463
|
+
- Coordinate selection by clicking
|
|
3464
|
+
- Automatic marker display (AiTwotoneEnvironment icon)
|
|
3465
|
+
- Default zoom level 3
|
|
3466
|
+
|
|
3467
|
+
### 25. Field.Postcode
|
|
3468
|
+
|
|
3469
|
+
\`\`\`typescript
|
|
3470
|
+
interface PostcodeProps {
|
|
3471
|
+
kakaoKey: string; // Kakao API key
|
|
3472
|
+
address: string | null;
|
|
3473
|
+
onChange: ({
|
|
3474
|
+
address: string;
|
|
3475
|
+
addressEn: string;
|
|
3476
|
+
zipcode: string;
|
|
3477
|
+
coordinate: cnst.util.Coordinate;
|
|
3478
|
+
}) => void;
|
|
3479
|
+
}
|
|
3480
|
+
\`\`\`
|
|
3481
|
+
Key features:
|
|
3482
|
+
- Daum postcode service (react-daum-postcode)
|
|
3483
|
+
- Coordinate conversion using Kakao Maps API
|
|
3484
|
+
- Simultaneous Korean/English address provision
|
|
3485
|
+
- Modal address search
|
|
3486
|
+
|
|
3487
|
+
### 26. Field.KoreanCityDistrict
|
|
3488
|
+
|
|
3489
|
+
\`\`\`typescript
|
|
3490
|
+
interface KoreanCityDistrictProps {
|
|
3491
|
+
city: string | null;
|
|
3492
|
+
onChangeCity: (city: string | null) => void;
|
|
3493
|
+
district: string | null;
|
|
3494
|
+
onChangeDistrict: (district: string | null) => void;
|
|
3495
|
+
disabled?: boolean;
|
|
3496
|
+
}
|
|
3497
|
+
\`\`\`
|
|
3498
|
+
Key features:
|
|
3499
|
+
- Hardcoded Korean region data
|
|
3500
|
+
- Two-level selection (city/province \u2192 district/county)
|
|
3501
|
+
- Includes detailed regions: 25 districts in Seoul, 16 in Busan, etc.
|
|
3502
|
+
- Linked selection (district activates after city selection)
|
|
3503
|
+
|
|
3504
|
+
## Common Patterns and Features
|
|
3505
|
+
|
|
3506
|
+
### 1. Caching System
|
|
3507
|
+
|
|
3508
|
+
Most input components support form data persistence with the cache prop:
|
|
3509
|
+
cacheKey={cache ? \`\${label}-\${desc}-\${componentType}\` : undefined}
|
|
3510
|
+
|
|
3511
|
+
### 2. Validation System
|
|
3512
|
+
|
|
3513
|
+
All components support multi-layer validation:
|
|
3514
|
+
- Basic validation (length, type, format)
|
|
3515
|
+
- Custom validation functions
|
|
3516
|
+
- Internationalized error messages
|
|
3517
|
+
|
|
3518
|
+
### 3. Internationalization
|
|
3519
|
+
|
|
3520
|
+
- Labels, placeholders, error messages all use l() function
|
|
3521
|
+
- Automatic translation for Enum types
|
|
3522
|
+
- Multi-language error message templates
|
|
3523
|
+
|
|
3524
|
+
### 4. Store Integration
|
|
3525
|
+
|
|
3526
|
+
Relational components automatically connect to the store through naming conventions:
|
|
3527
|
+
\`\`\`javascript
|
|
3528
|
+
const names = {
|
|
3529
|
+
model: modelName,
|
|
3530
|
+
modelList: \`\${modelName}List\`,
|
|
3531
|
+
initModel: \`init\${ModelName}\`,
|
|
3532
|
+
};
|
|
3533
|
+
\`\`\`
|
|
3534
|
+
|
|
3535
|
+
### 5. Type Safety
|
|
3536
|
+
|
|
3537
|
+
- Type safety ensured with TypeScript generics
|
|
3538
|
+
- Conditional types for handling nullable properties
|
|
3539
|
+
- Strict props interface definitions
|
|
3540
|
+
|
|
3541
|
+
This comprehensive field library provides a consistent user experience and developer convenience, designed to make complex form compositions simple and safe.
|
|
3542
|
+
2. Data Components (/Data/)
|
|
3543
|
+
|
|
3544
|
+
Purpose: Complete data visualization and management interfaces
|
|
3545
|
+
|
|
3546
|
+
ListContainer
|
|
3547
|
+
|
|
3548
|
+
- type?: "card" | "list" - Display mode selection
|
|
3549
|
+
- columns?: DataColumn<any>[] - Column configuration
|
|
3550
|
+
- tools?: DataTool[] - Toolbar actions
|
|
3551
|
+
- renderDashboard?: (props) => ReactNode - Dashboard customization
|
|
3552
|
+
- renderItem?: (props) => ReactNode - Item renderer
|
|
3553
|
+
|
|
3554
|
+
CardList
|
|
3555
|
+
|
|
3556
|
+
- sliceName: string - Store slice identifier
|
|
3557
|
+
- columns: DataColumn<any>[] - Data column definitions
|
|
3558
|
+
- actions?: DataAction<Light>[] - Item actions
|
|
3559
|
+
- renderItem: (args) => ReactNode - Card renderer
|
|
3560
|
+
- renderLoading?: () => ReactNode - Loading state
|
|
3561
|
+
|
|
3562
|
+
Dashboard
|
|
3563
|
+
|
|
3564
|
+
- summary: { [key: string]: any } - Statistics data
|
|
3565
|
+
- queryMap: { [key: string]: any } - Filter mappings
|
|
3566
|
+
- columns?: string[] - Clickable statistics
|
|
3567
|
+
- hidePresents?: boolean - Display control
|
|
3568
|
+
|
|
3569
|
+
3. Load Components (/Load/)
|
|
3570
|
+
|
|
3571
|
+
Purpose: Data loading and state management with SSR/CSR support
|
|
3572
|
+
|
|
3573
|
+
Page
|
|
3574
|
+
|
|
3575
|
+
- loader: () => Promise<Return> - Data fetching function
|
|
3576
|
+
- render: (data: Return) => ReactNode - Content renderer
|
|
3577
|
+
- loading?: () => ReactNode - Loading state
|
|
3578
|
+
|
|
3579
|
+
Edit
|
|
3580
|
+
|
|
3581
|
+
- edit: ClientEdit<T, Full> | Partial<Full> - Edit data
|
|
3582
|
+
- type?: "modal" | "form" | "empty" - Display mode
|
|
3583
|
+
- sliceName: string - Store slice
|
|
3584
|
+
- onSubmit?: string | ((model: Full) => void) - Submit handler
|
|
3585
|
+
|
|
3586
|
+
Units
|
|
3587
|
+
|
|
3588
|
+
- init: ClientInit<T, L> - Initial data
|
|
3589
|
+
- filter?: (item: L, idx: number) => boolean - Item filtering
|
|
3590
|
+
- sort?: (a: L, b: L) => number - Sorting function
|
|
3591
|
+
- renderItem?: (item: L, idx: number) => ReactNode - Item renderer
|
|
3592
|
+
- pagination?: boolean - Pagination control
|
|
3593
|
+
|
|
3594
|
+
4. Model Components (/Model/)
|
|
3595
|
+
|
|
3596
|
+
Purpose: CRUD operations with modal and inline editing
|
|
3597
|
+
|
|
3598
|
+
EditModal
|
|
3599
|
+
|
|
3600
|
+
- sliceName: string - Store slice identifier
|
|
3601
|
+
- id?: string - Model ID for editing
|
|
3602
|
+
- renderTitle?: ((model: Full) => ReactNode) | string - Title customization
|
|
3603
|
+
- onSubmit?: string | ((model: Full) => void) - Submit handler
|
|
3604
|
+
- onCancel?: string | ((form?: any) => any) - Cancel handler
|
|
3605
|
+
|
|
3606
|
+
ViewModal
|
|
3607
|
+
|
|
3608
|
+
- id: string - Model identifier
|
|
3609
|
+
- renderView: (model: any) => ReactNode - View content renderer
|
|
3610
|
+
- renderAction?: (model: any) => ReactNode - Action buttons
|
|
3611
|
+
|
|
3612
|
+
NewWrapper
|
|
3613
|
+
|
|
3614
|
+
- sliceName: string - Store slice
|
|
3615
|
+
- partial?: Partial<Full> - Default values
|
|
3616
|
+
- modal?: string | null - Modal type
|
|
3617
|
+
|
|
3618
|
+
5. System Components (/System/)
|
|
3619
|
+
|
|
3620
|
+
Purpose: Application-level providers and system utilities
|
|
3621
|
+
|
|
3622
|
+
Provider (CSR)
|
|
3623
|
+
|
|
3624
|
+
- fonts: ReactFont[] - Font configurations
|
|
3625
|
+
- gaTrackingId?: string - Analytics tracking
|
|
3626
|
+
- layoutStyle?: "mobile" | "web" - Layout mode
|
|
3627
|
+
|
|
3628
|
+
Provider (SSR)
|
|
3629
|
+
|
|
3630
|
+
- fonts?: NextFont[] - Next.js font configurations
|
|
3631
|
+
|
|
3632
|
+
SelectLanguage
|
|
3633
|
+
|
|
3634
|
+
- languages?: string[] - Available languages
|
|
3635
|
+
|
|
3636
|
+
6. Only Components (/Only/)
|
|
3637
|
+
|
|
3638
|
+
Purpose: Conditional rendering based on user state and device
|
|
3639
|
+
|
|
3640
|
+
Admin
|
|
3641
|
+
|
|
3642
|
+
- roles?: cnst.AdminRole[] - Required admin roles
|
|
3643
|
+
|
|
3644
|
+
User
|
|
3645
|
+
|
|
3646
|
+
- roles?: cnst.UserRole[] - Required user roles
|
|
3647
|
+
|
|
3648
|
+
Show
|
|
3649
|
+
|
|
3650
|
+
- show?: boolean | cnst.util.Responsive[] - Show conditions
|
|
3651
|
+
|
|
3652
|
+
Mobile/Web
|
|
3653
|
+
|
|
3654
|
+
- No props - Device-based rendering
|
|
3655
|
+
|
|
3656
|
+
7. Editor Components (/Editor/)
|
|
3657
|
+
|
|
3658
|
+
Purpose: Rich text editing capabilities
|
|
3659
|
+
|
|
3660
|
+
Slate
|
|
3661
|
+
|
|
3662
|
+
- addFilesGql: (fileList: FileList, id?: string) => Promise<File[]> - File upload
|
|
3663
|
+
- addFile: (file: cnst.File | cnst.File[], options?) => void - File management
|
|
3664
|
+
- onChange: (value: unknown) => void - Content change handler
|
|
3665
|
+
- defaultValue?: unknown - Initial content
|
|
3666
|
+
- placeholder?: string - Placeholder text
|
|
3667
|
+
- disabled?: boolean - Read-only mode
|
|
3668
|
+
|
|
3669
|
+
SlateContent
|
|
3670
|
+
|
|
3671
|
+
- content: unknown - Slate content to display
|
|
3672
|
+
|
|
3673
|
+
8. Property Component (Property.tsx)
|
|
3674
|
+
|
|
3675
|
+
Purpose: Metadata-driven property editing
|
|
3676
|
+
|
|
3677
|
+
- prop: string - Property name
|
|
3678
|
+
- slice: StoreOf<any, any> - Store slice
|
|
3679
|
+
- renderTemplate?: (form: any) => ReactNode - Custom edit renderer
|
|
3680
|
+
- renderView?: (model: any) => ReactNode - Custom view renderer
|
|
3681
|
+
- modelPath?: string - Model path in store
|
|
3682
|
+
|
|
3683
|
+
Integration Patterns
|
|
3684
|
+
|
|
3685
|
+
Store Integration
|
|
3686
|
+
|
|
3687
|
+
- Components use standardized naming conventions for store slices
|
|
3688
|
+
- Automatic state management through slice integration
|
|
3689
|
+
- Consistent error handling and loading states
|
|
3690
|
+
|
|
3691
|
+
Validation System
|
|
3692
|
+
|
|
3693
|
+
- Built-in validation for all field types
|
|
3694
|
+
- Custom validation function support
|
|
3695
|
+
- Internationalized error messages
|
|
3696
|
+
|
|
3697
|
+
File Management
|
|
3698
|
+
|
|
3699
|
+
- Integrated file upload system
|
|
3700
|
+
- Progress tracking and status management
|
|
3701
|
+
- Multiple file type support with preview
|
|
3702
|
+
|
|
3703
|
+
Responsive Behavior
|
|
3704
|
+
|
|
3705
|
+
- Mobile-first design approach
|
|
3706
|
+
- Adaptive layouts based on screen size
|
|
3707
|
+
- Touch-friendly interactions
|
|
3708
|
+
|
|
3709
|
+
This comprehensive UI library provides everything needed to build sophisticated data management interfaces with consistent user
|
|
3710
|
+
experience and maintainable code architecture.
|
|
3711
|
+
`;
|
|
3968
3712
|
var frameworkAbstract = `
|
|
3969
3713
|
Intro
|
|
3970
3714
|
- Build an all-stack application at once.
|
|
@@ -4044,6 +3788,87 @@ Core ESLint Extensions
|
|
|
4044
3788
|
This configuration creates a robust linting setup that enforces Next.js App Router best practices, maintains clean code
|
|
4045
3789
|
organization, and ensures proper server/client code separation.
|
|
4046
3790
|
`;
|
|
3791
|
+
var componentDefaultDescription = ({
|
|
3792
|
+
modelName,
|
|
3793
|
+
ModelName,
|
|
3794
|
+
exampleFiles,
|
|
3795
|
+
constant,
|
|
3796
|
+
properties
|
|
3797
|
+
}) => `
|
|
3798
|
+
|
|
3799
|
+
|
|
3800
|
+
1. Akan.js \uD504\uB808\uC784\uC6CC\uD06C\uC5D0 \uB300\uD55C \uAC1C\uC694
|
|
3801
|
+
${frameworkAbstract}
|
|
3802
|
+
|
|
3803
|
+
2. Akan.js\uD504\uB808\uC784\uC6CC\uD06C \uB370\uC774\uD130 \uAE30\uBC18 \uBAA8\uB4C8\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
3804
|
+
${moduleDesription}
|
|
3805
|
+
|
|
3806
|
+
3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
3807
|
+
${eslintDescription}
|
|
3808
|
+
|
|
3809
|
+
4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
3810
|
+
${utilUiDescription}
|
|
3811
|
+
|
|
3812
|
+
5. shared/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
3813
|
+
${shardUiDescription}
|
|
3814
|
+
|
|
3815
|
+
6. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
|
|
3816
|
+
${constant}
|
|
3817
|
+
|
|
3818
|
+
7. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
|
|
3819
|
+
${properties.map(
|
|
3820
|
+
(property) => `
|
|
3821
|
+
\`\`\`
|
|
3822
|
+
${property.key}.constant.ts
|
|
3823
|
+
|
|
3824
|
+
|
|
3825
|
+
${property.source}
|
|
3826
|
+
\`\`\`
|
|
3827
|
+
`
|
|
3828
|
+
).join("\n\n")}
|
|
3829
|
+
|
|
3830
|
+
|
|
3831
|
+
8. \uC608\uC2DC \uD30C\uC77C\uB4E4
|
|
3832
|
+
${exampleFiles.map(
|
|
3833
|
+
(example) => `
|
|
3834
|
+
Example filename: ${example.filepath}
|
|
3835
|
+
\`\`\`
|
|
3836
|
+
${example.content}
|
|
3837
|
+
\`\`\`
|
|
3838
|
+
`
|
|
3839
|
+
).join("\n\n")}
|
|
3840
|
+
|
|
3841
|
+
|
|
3842
|
+
|
|
3843
|
+
|
|
3844
|
+
|
|
3845
|
+
|
|
3846
|
+
\uC5ED\uD560\uBD80\uC5EC
|
|
3847
|
+
- Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uC2DC\uB2C8\uC5B4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
|
|
3848
|
+
|
|
3849
|
+
\uCF54\uB529 \uADDC\uCE59
|
|
3850
|
+
- \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
3851
|
+
- \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
3852
|
+
- CSS: tailwind, 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 X) \uC0AC\uC6A9
|
|
3853
|
+
- Ui Component: @util/ui \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
3854
|
+
- \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
3855
|
+
\uCF54\uB4DC \uC2A4\uD0C0\uC77C
|
|
3856
|
+
- \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
|
|
3857
|
+
- \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
|
|
3858
|
+
- \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
|
|
3859
|
+
- \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
|
|
3860
|
+
\uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
|
|
3861
|
+
|
|
3862
|
+
\uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
|
|
3863
|
+
- UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
|
|
3864
|
+
- \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
|
|
3865
|
+
- \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
|
|
3866
|
+
- dayjs \uB77C\uC774\uBE0C\uB7EC\uB9AC\uB294 @akanjs/base\uC5D0\uC11C \uB798\uD551\uD558\uC5EC \uC81C\uACF5\uD558\uACE0 \uC788\uC74C.
|
|
3867
|
+
|
|
3868
|
+
|
|
3869
|
+
|
|
3870
|
+
|
|
3871
|
+
`;
|
|
4047
3872
|
var scalarConstantDescription = `
|
|
4048
3873
|
Purpose and Structure
|
|
4049
3874
|
|
|
@@ -4427,7 +4252,7 @@ Target filename: ${modelName}.constant.ts
|
|
|
4427
4252
|
${boilerplate}
|
|
4428
4253
|
\`\`\`
|
|
4429
4254
|
`;
|
|
4430
|
-
var
|
|
4255
|
+
var requestTemplate = ({
|
|
4431
4256
|
sysName,
|
|
4432
4257
|
modelName,
|
|
4433
4258
|
ModelName,
|
|
@@ -4436,78 +4261,56 @@ var requestView = ({
|
|
|
4436
4261
|
properties,
|
|
4437
4262
|
exampleFiles
|
|
4438
4263
|
}) => `
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
|
|
4456
|
-
${constant}
|
|
4264
|
+
${componentDefaultDescription({
|
|
4265
|
+
sysName,
|
|
4266
|
+
modelName,
|
|
4267
|
+
ModelName,
|
|
4268
|
+
exampleFiles,
|
|
4269
|
+
constant,
|
|
4270
|
+
properties
|
|
4271
|
+
})}
|
|
4272
|
+
\uC694\uCCAD\uC0AC\uD56D
|
|
4273
|
+
- \uC544\uB798 \uC81C\uACF5\uD560 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uCF54\uB4DC\uC5D0 \uCD94\uAC00\uB85C \uCEF4\uD3EC\uB10C\uD2B8 \uAC1C\uBC1C
|
|
4274
|
+
- ${ModelName}.Template.tsx \uCF54\uB4DC \uC791\uC131
|
|
4275
|
+
- \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC740 \uBAA8\uB378 \uC774\uB984\uC740 \uC2A4\uD0A4\uB9C8\uC5D0 \uAE30\uBC18\uD55C \uAE30\uB2A5\uC5D0 \uCD08\uC810\uC744 \uB450\uACE0 \uC791\uC131
|
|
4276
|
+
- \uC544\uB798 \uC81C\uACF5\uD560 \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uC788\uB294 General \uCEF4\uD3EC\uB10C\uD2B8 1\uAC1C\uB97C \uC81C\uC678\uD55C \uB514\uC790\uC778 \uCEF4\uD3EC\uB10C\uD2B8 4\uAC1C \uAC1C\uBC1C
|
|
4277
|
+
- \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.
|
|
4278
|
+
- \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uB9DE\uAC8C \uC815\uB9AC\uD574\uC11C \uC81C\uACF5
|
|
4279
|
+
-
|
|
4457
4280
|
|
|
4458
|
-
|
|
4459
|
-
${
|
|
4460
|
-
|
|
4281
|
+
Application name: ${sysName}
|
|
4282
|
+
Model name: ${modelName}
|
|
4283
|
+
Target filename: ${ModelName}.Template.tsx
|
|
4461
4284
|
\`\`\`
|
|
4462
|
-
${property.key}.constant.ts
|
|
4463
4285
|
|
|
4464
|
-
|
|
4465
|
-
${property.source}
|
|
4466
4286
|
\`\`\`
|
|
4467
|
-
`
|
|
4468
|
-
).join("\n\n")}
|
|
4469
4287
|
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
\uCF54\uB529 \uADDC\uCE59
|
|
4490
|
-
- \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4491
|
-
- \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4492
|
-
- 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)
|
|
4493
|
-
- \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4494
|
-
\uCF54\uB4DC \uC2A4\uD0C0\uC77C
|
|
4495
|
-
- \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
|
|
4496
|
-
- \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
|
|
4497
|
-
- \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
|
|
4498
|
-
- \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
|
|
4499
|
-
\uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
|
|
4500
|
-
|
|
4501
|
-
\uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
|
|
4502
|
-
- UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
|
|
4503
|
-
- \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
|
|
4504
|
-
- \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
|
|
4505
|
-
|
|
4288
|
+
|
|
4289
|
+
`;
|
|
4290
|
+
var requestView = ({
|
|
4291
|
+
sysName,
|
|
4292
|
+
modelName,
|
|
4293
|
+
ModelName,
|
|
4294
|
+
boilerplate,
|
|
4295
|
+
constant,
|
|
4296
|
+
properties,
|
|
4297
|
+
exampleFiles
|
|
4298
|
+
}) => `
|
|
4299
|
+
${componentDefaultDescription({
|
|
4300
|
+
sysName,
|
|
4301
|
+
modelName,
|
|
4302
|
+
ModelName,
|
|
4303
|
+
exampleFiles,
|
|
4304
|
+
constant,
|
|
4305
|
+
properties
|
|
4306
|
+
})}
|
|
4506
4307
|
\uC694\uCCAD\uC0AC\uD56D
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
\
|
|
4308
|
+
- \uC544\uB798 \uC81C\uACF5\uD560 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uCF54\uB4DC\uC5D0 \uCD94\uAC00\uB85C \uCEF4\uD3EC\uB10C\uD2B8 \uAC1C\uBC1C
|
|
4309
|
+
- ${ModelName}.View.tsx \uCF54\uB4DC \uC791\uC131
|
|
4310
|
+
- \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC5D0 ${ModelName}\uC740 \uC0DD\uB7B5\uD558\uBA70, \uB514\uC790\uC778 \uC911\uC810\uC758 \uC774\uB984\uC73C\uB85C \uC791\uC131
|
|
4311
|
+
- \uC544\uB798 \uC81C\uACF5\uD560 \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uC788\uB294 General \uCEF4\uD3EC\uB10C\uD2B8 1\uAC1C\uB97C \uC81C\uC678\uD55C \uB514\uC790\uC778 \uCEF4\uD3EC\uB10C\uD2B8 4\uAC1C \uAC1C\uBC1C
|
|
4312
|
+
- \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.
|
|
4313
|
+
- \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uB9DE\uAC8C \uC815\uB9AC\uD574\uC11C \uC81C\uACF5
|
|
4511
4314
|
|
|
4512
4315
|
|
|
4513
4316
|
Application name: ${sysName}
|
|
@@ -4515,7 +4318,7 @@ Model name: ${modelName}
|
|
|
4515
4318
|
|
|
4516
4319
|
Target filename: ${ModelName}.View.tsx
|
|
4517
4320
|
\`\`\`
|
|
4518
|
-
|
|
4321
|
+
${boilerplate}
|
|
4519
4322
|
\`\`\`
|
|
4520
4323
|
|
|
4521
4324
|
|
|
@@ -4526,78 +4329,25 @@ var requestUnit = ({
|
|
|
4526
4329
|
ModelName,
|
|
4527
4330
|
constant,
|
|
4528
4331
|
properties,
|
|
4332
|
+
boilerplate,
|
|
4529
4333
|
exampleFiles
|
|
4530
4334
|
}) => `
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
3. Akan.js eslint \uC124\uC815\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
4540
|
-
${eslintDescription}
|
|
4541
|
-
|
|
4542
|
-
4. util/ui \uB0B4 ui\uD0B7\uC5D0 \uB300\uD55C \uC124\uBA85
|
|
4543
|
-
${utilUiDescription}
|
|
4544
|
-
|
|
4545
|
-
5. ${ModelName}.constant.ts \uD30C\uC77C\uC5D0 \uB300\uD55C \uC815\uBCF4
|
|
4546
|
-
${constant}
|
|
4547
|
-
|
|
4548
|
-
6. ${modelName}\uC5D0\uC11C \uC885\uC18D\uB418\uB294 \uB2E4\uB978 \uBAA8\uB378\uB4E4\uC758 \uD0C0\uC785 \uC815\uC758
|
|
4549
|
-
${properties.map(
|
|
4550
|
-
(property) => `
|
|
4551
|
-
\`\`\`
|
|
4552
|
-
${property.key}.constant.ts
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
${property.source}
|
|
4556
|
-
\`\`\`
|
|
4557
|
-
`
|
|
4558
|
-
).join("\n\n")}
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
7. \uC608\uC2DC \uD30C\uC77C\uB4E4
|
|
4562
|
-
${exampleFiles.map(
|
|
4563
|
-
(example) => `
|
|
4564
|
-
Example filename: ${example.filepath}
|
|
4565
|
-
\`\`\`
|
|
4566
|
-
${example.content}
|
|
4567
|
-
\`\`\`
|
|
4568
|
-
`
|
|
4569
|
-
).join("\n\n")}
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
\uC5ED\uD560\uBD80\uC5EC
|
|
4577
|
-
- Akan.js \uC0AC\uB0B4 \uD504\uB808\uC784\uC6CC\uD06C \uAE30\uBC18 Typescript \uC2DC\uB2C8\uC5B4 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C\uC790.
|
|
4335
|
+
${componentDefaultDescription({
|
|
4336
|
+
sysName,
|
|
4337
|
+
modelName,
|
|
4338
|
+
ModelName,
|
|
4339
|
+
exampleFiles,
|
|
4340
|
+
constant,
|
|
4341
|
+
properties
|
|
4342
|
+
})}
|
|
4578
4343
|
|
|
4579
|
-
\uCF54\uB529 \uADDC\uCE59
|
|
4580
|
-
- \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4581
|
-
- \uC544\uC774\uCF58: react-icons \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4582
|
-
- 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)
|
|
4583
|
-
- \uC870\uAC74\uBD80 \uD074\uB798\uC2A4: clsx \uB77C\uC774\uBE0C\uB7EC\uB9AC \uC0AC\uC6A9
|
|
4584
|
-
\uCF54\uB4DC \uC2A4\uD0C0\uC77C
|
|
4585
|
-
- \uC0C9\uC0C1: \uD558\uB4DC\uCF54\uB529(bg-red) \uB300\uC2E0 \uD14C\uB9C8 \uC0C9\uC0C1(bg-primary) \uC0AC\uC6A9
|
|
4586
|
-
- \uC870\uAC74\uBD80 \uB80C\uB354\uB9C1: field && <div>... \uB300\uC2E0 field ? <div>... : null \uC0AC\uC6A9
|
|
4587
|
-
- \uBAA8\uB378 \uC811\uADFC: \uAD6C\uC870\uBD84\uD574\uD560\uB2F9 \uB300\uC2E0 ${modelName}.field \uD615\uC2DD\uC73C\uB85C \uC811\uADFC
|
|
4588
|
-
- \uD0C0\uC785 \uC548\uC804: ${modelName}.constant.ts\uC758 \uC2A4\uD0A4\uB9C8 \uCC38\uC870\uD558\uC5EC \uC5D0\uB7EC \uBC29\uC9C0
|
|
4589
|
-
\uD544\uB4DC \uC811\uADFC \uC804: \uC2A4\uD0A4\uB9C8\uC758 \uC2E4\uC81C \uD544\uB4DC \uB9AC\uC2A4\uD2B8 \uC791\uC131 \uBC0F \uAC80\uD1A0 \uD544\uC218
|
|
4590
|
-
|
|
4591
|
-
\uC5C4\uACA9\uD55C \uC8FC\uC758\uC0AC\uD56D
|
|
4592
|
-
- UI \uD0B7\uC740 \uBB38\uC11C\uC5D0 \uBA85\uC2DC\uB41C \uCEF4\uD3EC\uB10C\uD2B8\uB9CC \uC0AC\uC6A9
|
|
4593
|
-
- \uCEF4\uD3EC\uB10C\uD2B8 \uC0AC\uC6A9 \uC804 \uBB38\uC11C \uD655\uC778 \uBC0F props \uC815\uD655\uD788 \uAC80\uC99D
|
|
4594
|
-
- \uBA85\uC2DC\uB41C \uB8F0 \uC678 \uC784\uC758 \uCD94\uC0C1\uD654 \uAE08\uC9C0
|
|
4595
|
-
|
|
4596
4344
|
\uC694\uCCAD\uC0AC\uD56D
|
|
4345
|
+
- \uC544\uB798 \uC81C\uACF5\uD560 \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uCF54\uB4DC\uC5D0 \uCD94\uAC00\uB85C \uCEF4\uD3EC\uB10C\uD2B8 \uAC1C\uBC1C
|
|
4597
4346
|
- ${ModelName}.Unit.tsx \uCF54\uB4DC \uC791\uC131
|
|
4598
|
-
- \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC5D0 ModelName\uC740 \uC0DD\uB7B5\uD558\uBA70, \
|
|
4347
|
+
- \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984\uC5D0 ${ModelName}\uC740 \uC0DD\uB7B5\uD558\uBA70, \uB514\uC790\uC778 \uC911\uC810\uC758 \uC774\uB984\uC73C\uB85C \uC791\uC131
|
|
4599
4348
|
- \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
|
|
4600
4349
|
- \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.
|
|
4350
|
+
- \uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8\uC5D0 \uB9DE\uAC8C \uC815\uB9AC\uD574\uC11C \uC81C\uACF5
|
|
4601
4351
|
|
|
4602
4352
|
|
|
4603
4353
|
Application name: ${sysName}
|
|
@@ -4605,7 +4355,7 @@ Model name: ${modelName}
|
|
|
4605
4355
|
|
|
4606
4356
|
Target filename: ${ModelName}.Unit.tsx
|
|
4607
4357
|
\`\`\`
|
|
4608
|
-
|
|
4358
|
+
${boilerplate}
|
|
4609
4359
|
\`\`\`
|
|
4610
4360
|
|
|
4611
4361
|
|
|
@@ -5856,6 +5606,31 @@ var ModuleRunner = class {
|
|
|
5856
5606
|
}
|
|
5857
5607
|
};
|
|
5858
5608
|
}
|
|
5609
|
+
async createComponentTemplate(sys2, name, type) {
|
|
5610
|
+
const akanConfig = await sys2.getConfig();
|
|
5611
|
+
const scanResult = await sys2.scan({ akanConfig });
|
|
5612
|
+
await sys2.applyTemplate({
|
|
5613
|
+
basePath: `./lib/${name}__`,
|
|
5614
|
+
template: `module/__Model__.${capitalize(type)}.ts`,
|
|
5615
|
+
scanResult,
|
|
5616
|
+
dict: { model: name, Model: capitalize(name), appName: sys2.name }
|
|
5617
|
+
});
|
|
5618
|
+
await sys2.scan({ akanConfig });
|
|
5619
|
+
return {
|
|
5620
|
+
component: {
|
|
5621
|
+
filename: `${name}.${capitalize(type)}.tsx`,
|
|
5622
|
+
content: sys2.readFile(`lib/${name}__/${capitalize(name)}.${capitalize(type)}.tsx`)
|
|
5623
|
+
}
|
|
5624
|
+
// constant: {
|
|
5625
|
+
// filename: `${name}.constant.ts`,
|
|
5626
|
+
// content: sys.readFile(`lib/__scalar/${name}/${name}.constant.ts`),
|
|
5627
|
+
// },
|
|
5628
|
+
// dictionary: {
|
|
5629
|
+
// filename: `${name}.dictionary.ts`,
|
|
5630
|
+
// content: sys.readFile(`lib/__scalar/${name}/${name}.dictionary.ts`),
|
|
5631
|
+
// },
|
|
5632
|
+
};
|
|
5633
|
+
}
|
|
5859
5634
|
async createModuleTemplate(sys2, name) {
|
|
5860
5635
|
const akanConfig = await sys2.getConfig();
|
|
5861
5636
|
const scanResult = await sys2.scan({ akanConfig });
|
|
@@ -5910,64 +5685,6 @@ var ModuleRunner = class {
|
|
|
5910
5685
|
}
|
|
5911
5686
|
};
|
|
5912
5687
|
}
|
|
5913
|
-
// async createUnit(sys: App | Lib, modelName: string) {
|
|
5914
|
-
// const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5915
|
-
// const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
|
|
5916
|
-
// const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
|
|
5917
|
-
// const prompt = `
|
|
5918
|
-
// 너는 React, Typescript, TailwindCSS를 기반으로 코딩하는 프론트엔드 개발자야.
|
|
5919
|
-
// ${names.Model}이라는 도메인에 대해서 ${names.LightModel} 스키마를 대상으로 react component를 디자인하려고 해. 아래는 현재 보일러플레이트 형태의 컴포넌트야.
|
|
5920
|
-
// \`\`\`
|
|
5921
|
-
// ${modelFileData.unitFileStr}
|
|
5922
|
-
// \`\`\`
|
|
5923
|
-
// ${names.LightModel}은 다음과 같이 ${names.Model} 스키마에서 일부 필드를 추출해서 lightweight fetch된 형태로 설계되어있어.
|
|
5924
|
-
// \`\`\`
|
|
5925
|
-
// ${modelFileData.constantFileStr}
|
|
5926
|
-
// \`\`\`
|
|
5927
|
-
// 아래는 현재 스키마와 연관된 스키마 파일들이야. 스키마 파일들의 코드들을 보고 서로 어떻게 연계 되어있는지 이해하도록 해.
|
|
5928
|
-
// ${
|
|
5929
|
-
// paths
|
|
5930
|
-
// ? new Array(paths.size).fill(0).map((_, index) => {
|
|
5931
|
-
// //순서대로 paths key 추출
|
|
5932
|
-
// const key = Array.from(paths.keys())[index];
|
|
5933
|
-
// const filePath = paths.get(key)?.filePath;
|
|
5934
|
-
// if (!filePath) throw new Error("filePath is undefined");
|
|
5935
|
-
// return `${key}\n\`\`\`${fs.readFileSync(filePath, "utf8")}\`\`\`\`\n\n`;
|
|
5936
|
-
// })
|
|
5937
|
-
// : ""
|
|
5938
|
-
// }
|
|
5939
|
-
// 추가로, 만약에 아이콘 사용이 필요하면 react-icons/bi 라이브러리에서 사용해줘.
|
|
5940
|
-
// 또, 색상을 사용하려고 하면 하드코딩된 색상(bg-red)이 아닌 테마 색상(bg-primary)을 사용해서 작성해줘.
|
|
5941
|
-
// 그리고 optional한 필드는 field && <div>... 가 아닌, field ? <div>... : null 형태로 작성해줘.
|
|
5942
|
-
// css라이브러리는 DaisyUI를 기반으로 작성해주는데, btn, input, badge와 같은 단순한 기본 css는 사용해도 괜찮아. 그런데 card, hero같이 복잡한 컴포넌트는 사용하면 안돼.
|
|
5943
|
-
// 조건부 className이 필요한 경우에는 clsx 라이브러리를 사용해서 작성해야해.
|
|
5944
|
-
// 모델에 대해서 object destructuring은 하지말고 ${modelName}.field 형태로 접근하게 코드를 작성해야해.
|
|
5945
|
-
// ${names.Model}.Unit.Card의 리액트 컴포넌트를 디자인해서 작성해줘.
|
|
5946
|
-
// `;
|
|
5947
|
-
// try {
|
|
5948
|
-
// fs.writeFileSync("./local/prompt.txt", prompt);
|
|
5949
|
-
// const { content } = await streamAi(prompt, (chunk) => {
|
|
5950
|
-
// process.stdout.write(chunk);
|
|
5951
|
-
// });
|
|
5952
|
-
// fs.writeFileSync("./local/result.txt", content);
|
|
5953
|
-
// } catch (error) {
|
|
5954
|
-
// // console.error("Application error:", error);
|
|
5955
|
-
// }
|
|
5956
|
-
// }
|
|
5957
|
-
// async createView(sys: App | Lib, modelName: string) {
|
|
5958
|
-
// const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5959
|
-
// // const modelFileData = getModelFileData(sys.cwdPath, modelName);
|
|
5960
|
-
// // const { paths } = getRelatedCnsts(modelFileData.constantFilePath);
|
|
5961
|
-
// // const names = { model: modelName, Model: capitalize(modelName), LightModel: `Light${capitalize(modelName)}` };
|
|
5962
|
-
// // const prompt = prompt.requestView({
|
|
5963
|
-
// // sysName: sys.name,
|
|
5964
|
-
// // modelName,
|
|
5965
|
-
// // modelDesc: modelFileData.modelDesc,
|
|
5966
|
-
// // modelSchemaDesign: modelFileData.modelSchemaDesign,
|
|
5967
|
-
// // boilerplate: modelFileData.viewFileStr,
|
|
5968
|
-
// // paths,
|
|
5969
|
-
// // });
|
|
5970
|
-
// }
|
|
5971
5688
|
};
|
|
5972
5689
|
|
|
5973
5690
|
// pkgs/@akanjs/cli/src/module/module.script.ts
|
|
@@ -5997,6 +5714,7 @@ var ModuleScript = class {
|
|
|
5997
5714
|
async removeModule(workspace, name) {
|
|
5998
5715
|
}
|
|
5999
5716
|
async createScalar(sys2, name, description, schemaDescription) {
|
|
5717
|
+
await AiSession.init();
|
|
6000
5718
|
await AiSession.init();
|
|
6001
5719
|
const scalarConstantExampleFiles = await sys2.workspace.getScalarConstantFiles();
|
|
6002
5720
|
const { constant, dictionary } = await this.#runner.createScalarTemplate(sys2, name);
|
|
@@ -6017,7 +5735,45 @@ var ModuleScript = class {
|
|
|
6017
5735
|
}
|
|
6018
5736
|
async createTest(workspace, name) {
|
|
6019
5737
|
}
|
|
5738
|
+
async createTemplate(sys2) {
|
|
5739
|
+
await AiSession.init();
|
|
5740
|
+
const libs = await sys2.getModules();
|
|
5741
|
+
const lib = await select4({
|
|
5742
|
+
message: "Select the lib",
|
|
5743
|
+
choices: libs
|
|
5744
|
+
}).catch((e) => {
|
|
5745
|
+
Logger.error("canceled");
|
|
5746
|
+
return null;
|
|
5747
|
+
});
|
|
5748
|
+
if (!lib)
|
|
5749
|
+
return;
|
|
5750
|
+
const name = lib.split("/").pop();
|
|
5751
|
+
if (!name)
|
|
5752
|
+
return;
|
|
5753
|
+
const { component: template } = await this.#runner.createComponentTemplate(sys2, name, "template");
|
|
5754
|
+
const templateExampleFiles = (await sys2.getTemplatesSourceCode()).filter(
|
|
5755
|
+
(f) => !f.filepath.includes(`${name}.Template.tsx`)
|
|
5756
|
+
);
|
|
5757
|
+
const Name = capitalize(name);
|
|
5758
|
+
const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
|
|
5759
|
+
const constant = fs12.readFileSync(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`, "utf-8");
|
|
5760
|
+
const session = new AiSession();
|
|
5761
|
+
const promptRst = requestTemplate({
|
|
5762
|
+
sysName: sys2.name,
|
|
5763
|
+
modelName: name,
|
|
5764
|
+
ModelName: Name,
|
|
5765
|
+
constant,
|
|
5766
|
+
boilerplate: template.content,
|
|
5767
|
+
properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
|
|
5768
|
+
exampleFiles: randomPicks(templateExampleFiles, Math.min(20, templateExampleFiles.length))
|
|
5769
|
+
});
|
|
5770
|
+
const content = await session.editTypescript(promptRst);
|
|
5771
|
+
fs12.writeFileSync(`${sys2.cwdPath}/promptTemplate.txt`, promptRst);
|
|
5772
|
+
fs12.writeFileSync(`${sys2.cwdPath}/resultTemplate.txt`, content);
|
|
5773
|
+
sys2.writeFile(`lib/${name}__/${Name}.Template.tsx`, content);
|
|
5774
|
+
}
|
|
6020
5775
|
async createUnit(sys2) {
|
|
5776
|
+
await AiSession.init();
|
|
6021
5777
|
const libs = await sys2.getModules();
|
|
6022
5778
|
const lib = await select4({
|
|
6023
5779
|
message: "Select the lib",
|
|
@@ -6031,6 +5787,7 @@ var ModuleScript = class {
|
|
|
6031
5787
|
const name = lib.split("/").pop();
|
|
6032
5788
|
if (!name)
|
|
6033
5789
|
return;
|
|
5790
|
+
const { component: unit } = await this.#runner.createComponentTemplate(sys2, name, "unit");
|
|
6034
5791
|
const Name = capitalize(name);
|
|
6035
5792
|
const unitExampleFiles = (await sys2.getUnitsSourceCode()).filter((f) => !f.filepath.includes(`${name}.Unit.tsx`));
|
|
6036
5793
|
const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
|
|
@@ -6042,13 +5799,16 @@ var ModuleScript = class {
|
|
|
6042
5799
|
ModelName: Name,
|
|
6043
5800
|
constant,
|
|
6044
5801
|
properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
|
|
6045
|
-
exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length))
|
|
5802
|
+
exampleFiles: randomPicks(unitExampleFiles, Math.min(10, unitExampleFiles.length)),
|
|
5803
|
+
boilerplate: unit.content
|
|
6046
5804
|
});
|
|
6047
5805
|
const content = await session.editTypescript(promptRst);
|
|
6048
5806
|
fs12.writeFileSync(`${sys2.cwdPath}/promptUnit.txt`, promptRst);
|
|
6049
5807
|
fs12.writeFileSync(`${sys2.cwdPath}/resultUnit.txt`, content);
|
|
5808
|
+
sys2.writeFile(`lib/${name}__/${Name}.Unit.tsx`, content);
|
|
6050
5809
|
}
|
|
6051
5810
|
async createView(sys2) {
|
|
5811
|
+
await AiSession.init();
|
|
6052
5812
|
const libs = await sys2.getModules();
|
|
6053
5813
|
const lib = await select4({
|
|
6054
5814
|
message: "Select the lib",
|
|
@@ -6062,6 +5822,7 @@ var ModuleScript = class {
|
|
|
6062
5822
|
const name = lib.split("/").pop();
|
|
6063
5823
|
if (!name)
|
|
6064
5824
|
return;
|
|
5825
|
+
const { component: view } = await this.#runner.createComponentTemplate(sys2, name, "view");
|
|
6065
5826
|
const viewExampleFiles = (await sys2.getViewsSourceCode()).filter((f) => !f.filepath.includes(`${name}.View.tsx`));
|
|
6066
5827
|
const Name = capitalize(name);
|
|
6067
5828
|
const relatedCnsts = getRelatedCnsts(`${sys2.cwdPath}/lib/${name}/${name}.constant.ts`);
|
|
@@ -6072,12 +5833,14 @@ var ModuleScript = class {
|
|
|
6072
5833
|
modelName: name,
|
|
6073
5834
|
ModelName: Name,
|
|
6074
5835
|
constant,
|
|
5836
|
+
boilerplate: view.content,
|
|
6075
5837
|
properties: relatedCnsts.map((r) => ({ key: r.key, source: r.source })),
|
|
6076
5838
|
exampleFiles: randomPicks(viewExampleFiles, Math.min(20, viewExampleFiles.length))
|
|
6077
5839
|
});
|
|
6078
5840
|
const content = await session.editTypescript(promptRst);
|
|
6079
5841
|
fs12.writeFileSync(`${sys2.cwdPath}/prompt.txt`, promptRst);
|
|
6080
5842
|
fs12.writeFileSync(`${sys2.cwdPath}/result.txt`, content);
|
|
5843
|
+
sys2.writeFile(`lib/${name}__/${Name}.View.tsx`, content);
|
|
6081
5844
|
}
|
|
6082
5845
|
};
|
|
6083
5846
|
|
|
@@ -6085,14 +5848,14 @@ var ModuleScript = class {
|
|
|
6085
5848
|
var ModuleCommand = class {
|
|
6086
5849
|
moduleScript = new ModuleScript();
|
|
6087
5850
|
async createModule(sys2, name, workspace) {
|
|
6088
|
-
await this.moduleScript.createModuleTemplate(sys2, name);
|
|
5851
|
+
await this.moduleScript.createModuleTemplate(sys2, lowerlize(name));
|
|
6089
5852
|
}
|
|
6090
5853
|
async removeModule(name, workspace) {
|
|
6091
5854
|
}
|
|
6092
5855
|
async scanModule(name, workspace) {
|
|
6093
5856
|
}
|
|
6094
5857
|
async createScalar(sys2, name, description, schemaDescription, workspace) {
|
|
6095
|
-
await this.moduleScript.createScalar(sys2, name, description, schemaDescription);
|
|
5858
|
+
await this.moduleScript.createScalar(sys2, lowerlize(name), description, schemaDescription);
|
|
6096
5859
|
}
|
|
6097
5860
|
async createService(name, workspace) {
|
|
6098
5861
|
}
|
|
@@ -6104,6 +5867,9 @@ var ModuleCommand = class {
|
|
|
6104
5867
|
async createUnit(sys2, workspace) {
|
|
6105
5868
|
await this.moduleScript.createUnit(sys2);
|
|
6106
5869
|
}
|
|
5870
|
+
async createTemplate(sys2, workspace) {
|
|
5871
|
+
await this.moduleScript.createTemplate(sys2);
|
|
5872
|
+
}
|
|
6107
5873
|
};
|
|
6108
5874
|
__decorateClass([
|
|
6109
5875
|
Target.Public(),
|
|
@@ -6149,6 +5915,11 @@ __decorateClass([
|
|
|
6149
5915
|
__decorateParam(0, Sys()),
|
|
6150
5916
|
__decorateParam(1, Workspace())
|
|
6151
5917
|
], ModuleCommand.prototype, "createUnit", 1);
|
|
5918
|
+
__decorateClass([
|
|
5919
|
+
Target.Public(),
|
|
5920
|
+
__decorateParam(0, Sys()),
|
|
5921
|
+
__decorateParam(1, Workspace())
|
|
5922
|
+
], ModuleCommand.prototype, "createTemplate", 1);
|
|
6152
5923
|
ModuleCommand = __decorateClass([
|
|
6153
5924
|
Commands()
|
|
6154
5925
|
], ModuleCommand);
|
|
@@ -6425,5 +6196,5 @@ void runCommands(
|
|
|
6425
6196
|
//! 2. csr폴더를 현 위치로 복사 후 압축 후 삭제
|
|
6426
6197
|
//! execSync를 가져오기 싫으니 일단 2번 방법으로 해보자
|
|
6427
6198
|
//! add path in tsconfig.json
|
|
6428
|
-
//! 파일을 {name}.Unit.tsx에 저장.
|
|
6429
6199
|
//! 파일을 {name}.View.tsx에 저장.
|
|
6200
|
+
//! 파일을 {name}.Unit.tsx에 저장.
|