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