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