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