@akanjs/cli 0.9.42 → 0.9.43
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 +16 -6
- package/cjs/src/guidelines/___library/sharedUiStructureDescription.en.md +0 -1
- package/cjs/src/guidelines/modelService/modelService.generate.json +0 -30
- package/cjs/src/guidelines/modelService/modelService.instruction.md +0 -164
- package/cjs/src/templates/app/lib/___appName__/__appName__.dictionary.js +6 -1
- package/cjs/src/templates/app/lib/___appName__/__appName__.service.js +1 -8
- package/cjs/src/templates/app/lib/___appName__/__appName__.signal.js +34 -0
- package/cjs/src/templates/app/lib/summary/Summary.Zone.js +1 -21
- package/cjs/src/templates/app/lib/user/User.Util.js +1 -26
- package/cjs/src/templates/app/lib/user/User.Zone.js +2 -30
- package/cjs/src/templates/app/lib/user/user.document.js +1 -7
- package/cjs/src/templates/app/lib/user/user.service.js +2 -8
- package/cjs/src/templates/lib/__lib/lib.service.js +1 -1
- package/cjs/src/templates/lib/cnst_.js +5 -2
- package/cjs/src/templates/lib/fetch.js +1 -1
- package/cjs/src/templates/lib/store.js +0 -1
- package/cjs/src/templates/libRoot/lib/summary/Summary.Zone.js +1 -21
- package/cjs/src/templates/libRoot/lib/user/User.Util.js +1 -26
- package/cjs/src/templates/libRoot/lib/user/User.Zone.js +2 -29
- package/cjs/src/templates/libRoot/lib/user/user.document.js +1 -7
- package/cjs/src/templates/libRoot/lib/user/user.service.js +2 -8
- package/cjs/src/templates/module/__Model__.Util.js +6 -36
- package/cjs/src/templates/module/__Model__.Zone.js +2 -26
- package/cjs/src/templates/module/__model__.document.js +1 -7
- package/cjs/src/templates/module/__model__.service.js +1 -7
- package/cjs/src/templates/workspaceRoot/.vscode/settings.json.template +0 -1
- package/esm/index.js +16 -6
- package/esm/src/guidelines/___library/sharedUiStructureDescription.en.md +0 -1
- package/esm/src/guidelines/modelService/modelService.generate.json +0 -30
- package/esm/src/guidelines/modelService/modelService.instruction.md +0 -164
- package/esm/src/templates/app/lib/___appName__/__appName__.dictionary.js +6 -1
- package/esm/src/templates/app/lib/___appName__/__appName__.service.js +1 -8
- package/esm/src/templates/app/lib/___appName__/__appName__.signal.js +14 -0
- package/esm/src/templates/app/lib/summary/Summary.Zone.js +1 -21
- package/esm/src/templates/app/lib/user/User.Util.js +1 -26
- package/esm/src/templates/app/lib/user/User.Zone.js +2 -30
- package/esm/src/templates/app/lib/user/user.document.js +1 -7
- package/esm/src/templates/app/lib/user/user.service.js +2 -8
- package/esm/src/templates/lib/__lib/lib.service.js +1 -1
- package/esm/src/templates/lib/cnst_.js +5 -2
- package/esm/src/templates/lib/fetch.js +1 -1
- package/esm/src/templates/lib/store.js +0 -1
- package/esm/src/templates/libRoot/lib/summary/Summary.Zone.js +1 -21
- package/esm/src/templates/libRoot/lib/user/User.Util.js +1 -26
- package/esm/src/templates/libRoot/lib/user/User.Zone.js +2 -29
- package/esm/src/templates/libRoot/lib/user/user.document.js +1 -7
- package/esm/src/templates/libRoot/lib/user/user.service.js +2 -8
- package/esm/src/templates/module/__Model__.Util.js +6 -36
- package/esm/src/templates/module/__Model__.Zone.js +2 -26
- package/esm/src/templates/module/__model__.document.js +1 -7
- package/esm/src/templates/module/__model__.service.js +1 -7
- package/esm/src/templates/workspaceRoot/.vscode/settings.json.template +0 -1
- package/package.json +1 -1
- package/src/guidelines/___library/sharedUiStructureDescription.en.md +0 -1
- package/src/guidelines/modelService/modelService.instruction.md +0 -164
- package/src/templates/app/{app/[lang]/admin/page.d.ts → lib/___appName__/__appName__.signal.d.ts} +2 -4
- package/ui/MultiScrollList.d.ts +4 -1
- package/cjs/src/templates/app/app/[lang]/admin/page.js +0 -63
- package/esm/src/templates/app/app/[lang]/admin/page.js +0 -43
package/cjs/index.js
CHANGED
|
@@ -3960,6 +3960,7 @@ var MultiScrollList = ({ logList, maxLength = 100 }) => {
|
|
|
3960
3960
|
const [boxHeight, setBoxHeight] = (0, import_react2.useState)(
|
|
3961
3961
|
height - HEADER_HEIGHT - OUTER_BORDER_HEIGHT - FOOTER_HEIGHT - BORDER_HEIGHT
|
|
3962
3962
|
);
|
|
3963
|
+
const [boxWidth, setBoxWidth] = (0, import_react2.useState)(width - 28);
|
|
3963
3964
|
const getLimitedLogs = (logs) => {
|
|
3964
3965
|
return logs.length > maxLength ? logs.slice(logs.length - maxLength) : logs;
|
|
3965
3966
|
};
|
|
@@ -4011,6 +4012,15 @@ var MultiScrollList = ({ logList, maxLength = 100 }) => {
|
|
|
4011
4012
|
(0, import_react2.useEffect)(() => {
|
|
4012
4013
|
const getLogsToRender = (logs, index) => {
|
|
4013
4014
|
const limitedLogs = getLimitedLogs(logs);
|
|
4015
|
+
const logWidth = limitedLogs.reduce((acc, log) => acc + log.content.length, 0);
|
|
4016
|
+
if (logWidth > boxWidth) {
|
|
4017
|
+
return limitedLogs.map((log) => {
|
|
4018
|
+
return {
|
|
4019
|
+
type: log.type,
|
|
4020
|
+
content: log.content.slice(0, boxWidth)
|
|
4021
|
+
};
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4014
4024
|
if (scrollPos > 0 && tabIndex === index) {
|
|
4015
4025
|
return limitedLogs.slice(limitedLogs.length - boxHeight - scrollPos, limitedLogs.length - scrollPos);
|
|
4016
4026
|
} else if (limitedLogs.length > boxHeight) {
|
|
@@ -4051,9 +4061,9 @@ var MultiScrollList = ({ logList, maxLength = 100 }) => {
|
|
|
4051
4061
|
height: "100%"
|
|
4052
4062
|
},
|
|
4053
4063
|
scrollPos > 0 ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, focusLog.slice(0, focusLog.length - 1).map((log, index) => {
|
|
4054
|
-
return /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { key: index }, log);
|
|
4064
|
+
return /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { color: log.type === "error" ? "red" : "white", key: index }, log.content);
|
|
4055
4065
|
}), /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "Scrolling... +", scrollPos)) : focusLog.map((log, index) => {
|
|
4056
|
-
return /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { key: index }, log);
|
|
4066
|
+
return /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { color: log.type === "error" ? "red" : "white", key: index }, log.content);
|
|
4057
4067
|
})
|
|
4058
4068
|
))), /* @__PURE__ */ import_react2.default.createElement(import_ink2.Box, { width: "100%", height: FOOTER_HEIGHT }, /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { dimColor: true }, /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, null, "You can use the following shortcuts:"), /* @__PURE__ */ import_react2.default.createElement(import_ink2.Newline, null), "* ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "tab"), " to switch tab.", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Newline, null), "* ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "up"), " and ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "down"), " to scroll.", " ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "shift"), " to scroll faster. (x10)", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Newline, null), "* ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "space"), " to scroll.", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Newline, null), "* ", /* @__PURE__ */ import_react2.default.createElement(import_ink2.Text, { backgroundColor: "green" }, "escape"), " to stop scrolling.")));
|
|
4059
4069
|
};
|
|
@@ -4176,17 +4186,17 @@ var Start = ({ appName, bcp, fcp, csr, maxLength = 100 }) => {
|
|
|
4176
4186
|
logList: [
|
|
4177
4187
|
{
|
|
4178
4188
|
title: `${appName} frontend`,
|
|
4179
|
-
logs: frontendLogs
|
|
4189
|
+
logs: frontendLogs,
|
|
4180
4190
|
color: "#ff493b"
|
|
4181
4191
|
},
|
|
4182
4192
|
{
|
|
4183
4193
|
title: `${appName} backend`,
|
|
4184
|
-
logs: backendLogs
|
|
4194
|
+
logs: backendLogs,
|
|
4185
4195
|
color: "#e535ab"
|
|
4186
4196
|
},
|
|
4187
4197
|
{
|
|
4188
4198
|
title: `${appName} react`,
|
|
4189
|
-
logs: csrLogs
|
|
4199
|
+
logs: csrLogs,
|
|
4190
4200
|
color: "#7cc5d9"
|
|
4191
4201
|
}
|
|
4192
4202
|
],
|
|
@@ -6300,7 +6310,7 @@ var WorkspaceRunner = class {
|
|
|
6300
6310
|
...Object.fromEntries(devDependencies.map((dependency) => [dependency, latestPublishedVersionOfBase]))
|
|
6301
6311
|
}
|
|
6302
6312
|
};
|
|
6303
|
-
workspace.
|
|
6313
|
+
workspace.setPackageJson(packageJson);
|
|
6304
6314
|
const installSpinner = workspace.spinning("Installing dependencies with pnpm...");
|
|
6305
6315
|
await workspace.spawn("pnpm", ["install", "--reporter=silent"]);
|
|
6306
6316
|
installSpinner.succeed("Dependencies installed with pnpm");
|
|
@@ -733,7 +733,6 @@ SlateContent
|
|
|
733
733
|
Purpose: Metadata-driven property editing
|
|
734
734
|
|
|
735
735
|
- prop: string - Property name
|
|
736
|
-
- slice: StoreOf<any, any> - Store slice
|
|
737
736
|
- renderTemplate?: (form: any) => ReactNode - Custom edit renderer
|
|
738
737
|
- renderView?: (model: any) => ReactNode - Custom view renderer
|
|
739
738
|
- modelPath?: string - Model path in store
|
|
@@ -52,34 +52,6 @@
|
|
|
52
52
|
"filterText": "@Sig",
|
|
53
53
|
"sample": 1
|
|
54
54
|
},
|
|
55
|
-
{
|
|
56
|
-
"type": "example",
|
|
57
|
-
"description": "onModuleInit method examples",
|
|
58
|
-
"path": "{apps,libs}/*/lib/*/*.service.ts",
|
|
59
|
-
"filterText": "onModuleInit",
|
|
60
|
-
"sample": 2
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"type": "example",
|
|
64
|
-
"description": "onModuleDestroy method examples",
|
|
65
|
-
"path": "{apps,libs}/*/lib/*/*.service.ts",
|
|
66
|
-
"filterText": "onModuleDestroy",
|
|
67
|
-
"sample": 1
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"type": "example",
|
|
71
|
-
"description": "@Cron decorator examples",
|
|
72
|
-
"path": "{apps,libs}/*/lib/*/*.service.ts",
|
|
73
|
-
"filterText": "@Cron",
|
|
74
|
-
"sample": 2
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"type": "example",
|
|
78
|
-
"description": "@Interval decorator examples",
|
|
79
|
-
"path": "{apps,libs}/*/lib/*/*.service.ts",
|
|
80
|
-
"filterText": "@Interval",
|
|
81
|
-
"sample": 1
|
|
82
|
-
},
|
|
83
55
|
{
|
|
84
56
|
"type": "example",
|
|
85
57
|
"description": "DbService _preCreate examples",
|
|
@@ -143,8 +115,6 @@
|
|
|
143
115
|
"Purpose and role of model.service.ts files",
|
|
144
116
|
"Service structure and inheritance (DbService, LogService, MixSrvs)",
|
|
145
117
|
"Core decorators (@Service, @Srv, @Use, @Db, @Sig)",
|
|
146
|
-
"Lifecycle methods (onModuleInit, onModuleDestroy)",
|
|
147
|
-
"Scheduled tasks (@Cron, @Interval)",
|
|
148
118
|
"Database operations (CRUD, queries, search)",
|
|
149
119
|
"Customizing database operations (_preCreate, _postCreate, _preUpdate, _postUpdate, _preRemove, _postRemove)",
|
|
150
120
|
"Working with other services (dependency injection patterns)",
|
|
@@ -136,97 +136,6 @@ Injects a websocket server instance for real-time communication:
|
|
|
136
136
|
protected readonly websocket: Websocket<ChatSignal>;
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
## Lifecycle Methods
|
|
140
|
-
|
|
141
|
-
Akan.js services can implement lifecycle hooks that are called by the NestJS framework.
|
|
142
|
-
|
|
143
|
-
### onModuleInit()
|
|
144
|
-
|
|
145
|
-
Called once the module has been initialized by NestJS. Use this for setup operations:
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
async onModuleInit() {
|
|
149
|
-
// Initialize service resources
|
|
150
|
-
await this.loadInitialData();
|
|
151
|
-
this.setupEventListeners();
|
|
152
|
-
this.logger.log('Service initialized successfully');
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Common use cases:
|
|
157
|
-
|
|
158
|
-
- Initializing in-memory cache
|
|
159
|
-
- Setting up event listeners
|
|
160
|
-
- Loading configuration data
|
|
161
|
-
- Establishing connections to external services
|
|
162
|
-
|
|
163
|
-
### onModuleDestroy()
|
|
164
|
-
|
|
165
|
-
Called just before the application shuts down. Use this for cleanup operations:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
async onModuleDestroy() {
|
|
169
|
-
// Clean up resources
|
|
170
|
-
await Promise.all(this.connections.map(conn => conn.close()));
|
|
171
|
-
this.clearTimers();
|
|
172
|
-
this.logger.log('Service resources released');
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
Common use cases:
|
|
177
|
-
|
|
178
|
-
- Closing database connections
|
|
179
|
-
- Releasing external resources
|
|
180
|
-
- Clearing timers and intervals
|
|
181
|
-
- Unregistering event listeners
|
|
182
|
-
|
|
183
|
-
## Scheduled Tasks
|
|
184
|
-
|
|
185
|
-
Akan.js provides decorators for scheduling recurring tasks.
|
|
186
|
-
|
|
187
|
-
### @Cron Decorator
|
|
188
|
-
|
|
189
|
-
Executes methods on a cron schedule:
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
@Cron("0 0 * * *") // Run at midnight every day
|
|
193
|
-
async dailyCleanup() {
|
|
194
|
-
await this.cleanupExpiredRecords();
|
|
195
|
-
this.logger.log('Daily cleanup completed');
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
@Cron("*/5 * * * *", { serverMode: "batch" }) // Run every 5 minutes, only in batch mode
|
|
199
|
-
async periodicSync() {
|
|
200
|
-
await this.syncExternalData();
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
The first parameter uses standard cron syntax:
|
|
205
|
-
|
|
206
|
-
- `* * * * *` = minute hour day-of-month month day-of-week
|
|
207
|
-
- Special patterns like `@daily`, `@hourly` are also supported
|
|
208
|
-
|
|
209
|
-
Options include:
|
|
210
|
-
|
|
211
|
-
- `serverMode`: Restrict to a specific server mode (e.g., "batch")
|
|
212
|
-
- `name`: Assign a name to the scheduled job
|
|
213
|
-
- `timeZone`: Specify the timezone for the schedule
|
|
214
|
-
|
|
215
|
-
### @Interval Decorator
|
|
216
|
-
|
|
217
|
-
Executes methods at fixed time intervals in milliseconds:
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
@Interval(60000) // Run every minute (60,000 ms)
|
|
221
|
-
async checkStatus() {
|
|
222
|
-
await this.monitorSystemHealth();
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Options:
|
|
227
|
-
|
|
228
|
-
- `name`: Assign a name to the interval
|
|
229
|
-
|
|
230
139
|
## Database Operations
|
|
231
140
|
|
|
232
141
|
When extending `DbService`, your service automatically inherits numerous methods for working with the database model.
|
|
@@ -606,34 +515,6 @@ class PaymentService extends DbService(db.paymentDb) {
|
|
|
606
515
|
}
|
|
607
516
|
```
|
|
608
517
|
|
|
609
|
-
### 3. Proper Resource Management
|
|
610
|
-
|
|
611
|
-
Clean up resources in lifecycle hooks:
|
|
612
|
-
|
|
613
|
-
```typescript
|
|
614
|
-
@Service("ExternalApiService")
|
|
615
|
-
class ExternalApiService extends LogService("ExternalApiService") {
|
|
616
|
-
private client: ApiClient;
|
|
617
|
-
private timers: NodeJS.Timeout[] = [];
|
|
618
|
-
|
|
619
|
-
async onModuleInit() {
|
|
620
|
-
this.client = new ApiClient();
|
|
621
|
-
await this.client.connect();
|
|
622
|
-
|
|
623
|
-
this.timers.push(setInterval(() => this.refreshToken(), 3600000));
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
async onModuleDestroy() {
|
|
627
|
-
// Clean up resources
|
|
628
|
-
await this.client.disconnect();
|
|
629
|
-
|
|
630
|
-
for (const timer of this.timers) {
|
|
631
|
-
clearInterval(timer);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
```
|
|
636
|
-
|
|
637
518
|
### 4. Transaction Safety
|
|
638
519
|
|
|
639
520
|
Use hooks for validating operations:
|
|
@@ -818,25 +699,6 @@ export class OrderService extends DbService(db.orderDb) {
|
|
|
818
699
|
|
|
819
700
|
return data;
|
|
820
701
|
}
|
|
821
|
-
|
|
822
|
-
// Scheduled task
|
|
823
|
-
@Cron("0 0 * * *", { serverMode: "batch" })
|
|
824
|
-
async cleanupAbandonedOrders() {
|
|
825
|
-
const cutoffDate = dayjs().subtract(7, "days");
|
|
826
|
-
const orders = await this.listPendingOrders(cutoffDate);
|
|
827
|
-
|
|
828
|
-
for (const order of orders) {
|
|
829
|
-
await this.cancelOrder(order.id);
|
|
830
|
-
this.logger.log(`Cancelled abandoned order: ${order.id}`);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// Summary method
|
|
835
|
-
async summarize(): Promise<cnst.OrderSummary> {
|
|
836
|
-
return {
|
|
837
|
-
...(await this.orderModel.getSummary()),
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
702
|
}
|
|
841
703
|
```
|
|
842
704
|
|
|
@@ -894,32 +756,6 @@ If a service isn't being injected correctly:
|
|
|
894
756
|
}
|
|
895
757
|
```
|
|
896
758
|
|
|
897
|
-
### Scheduled Tasks Not Running
|
|
898
|
-
|
|
899
|
-
1. Verify cron syntax:
|
|
900
|
-
|
|
901
|
-
```typescript
|
|
902
|
-
// Correct syntax
|
|
903
|
-
@Cron("0 * * * *") // Every hour at minute 0
|
|
904
|
-
|
|
905
|
-
// Incorrect syntax
|
|
906
|
-
@Cron("0 * * *") // Missing day-of-week field
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
2. Check server mode restrictions:
|
|
910
|
-
|
|
911
|
-
```typescript
|
|
912
|
-
// Only runs in batch mode
|
|
913
|
-
@Cron("0 * * * *", { serverMode: "batch" })
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
3. Ensure the service is properly initialized:
|
|
917
|
-
```typescript
|
|
918
|
-
onModuleInit() {
|
|
919
|
-
this.logger.log('Service initialized'); // Is this being logged?
|
|
920
|
-
}
|
|
921
|
-
```
|
|
922
|
-
|
|
923
759
|
## Summary
|
|
924
760
|
|
|
925
761
|
Model services in Akan.js are powerful components that encapsulate business logic and data operations. By following the patterns and best practices outlined in this guide, you can create maintainable, scalable services that effectively implement your application's domain logic while maintaining clean separation of concerns.
|
|
@@ -24,8 +24,13 @@ __export(appName_dictionary_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(appName_dictionary_exports);
|
|
25
25
|
function getContent(scanInfo, dict) {
|
|
26
26
|
return `
|
|
27
|
+
import type { SignalDictionary } from "@akanjs/dictionary";
|
|
28
|
+
import type { ${dict.AppName}Signal } from "./${dict.appName}.signal";
|
|
29
|
+
|
|
27
30
|
const dictionary = {} as const;
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
const signalDictionary = {} satisfies SignalDictionary<${dict.AppName}Signal>;
|
|
33
|
+
|
|
34
|
+
export const ${dict.appName}Dictionary = { ...dictionary, ...signalDictionary };
|
|
30
35
|
`;
|
|
31
36
|
}
|
|
@@ -30,13 +30,6 @@ import { LogService, Service, Srv } from "@akanjs/service";
|
|
|
30
30
|
import type * as srv from "../srv";
|
|
31
31
|
|
|
32
32
|
@Service("${dict.appName}Service", { serverMode: "batch" })
|
|
33
|
-
export class ${dict.AppName}Service extends LogService("${dict.appName}Service") {
|
|
34
|
-
@Srv() protected readonly summaryService: srv.SummaryService;
|
|
35
|
-
|
|
36
|
-
@Cron("0 * * * *")
|
|
37
|
-
async takePeriodicSnapshot() {
|
|
38
|
-
await this.summaryService.makeSummary();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
33
|
+
export class ${dict.AppName}Service extends LogService("${dict.appName}Service") {}
|
|
41
34
|
`;
|
|
42
35
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// pkgs/@akanjs/cli/src/templates/app/lib/___appName__/__appName__.signal.ts
|
|
20
|
+
var appName_signal_exports = {};
|
|
21
|
+
__export(appName_signal_exports, {
|
|
22
|
+
default: () => getContent
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(appName_signal_exports);
|
|
25
|
+
function getContent(scanInfo, dict) {
|
|
26
|
+
return `
|
|
27
|
+
import { LogSignal, Signal } from "@akanjs/signal";
|
|
28
|
+
|
|
29
|
+
import { Srvs } from "../cnst";
|
|
30
|
+
|
|
31
|
+
@Signal({ name: "${dict.AppName}" })
|
|
32
|
+
export class ${dict.AppName}Signal extends LogSignal(Srvs) {}
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
@@ -27,29 +27,9 @@ function getContent(scanInfo, dict) {
|
|
|
27
27
|
filename: "Summary.Zone.tsx",
|
|
28
28
|
content: `
|
|
29
29
|
"use client";
|
|
30
|
-
import {
|
|
31
|
-
import { DefaultOf } from "@akanjs/signal";
|
|
32
|
-
import { cnst, st, Summary } from "@${dict.appName}/client";
|
|
33
|
-
import { Data } from "@akanjs/ui";
|
|
30
|
+
import { st, Summary } from "@${dict.appName}/client";
|
|
34
31
|
import { Loading } from "@akanjs/ui";
|
|
35
32
|
|
|
36
|
-
export const Admin = ({ sliceName = "summary", init, query }: ModelsProps<cnst.Summary>) => {
|
|
37
|
-
return (
|
|
38
|
-
<Data.ListContainer
|
|
39
|
-
init={init}
|
|
40
|
-
query={query}
|
|
41
|
-
sliceName={sliceName}
|
|
42
|
-
renderItem={Summary.Unit.Card}
|
|
43
|
-
renderTemplate={Summary.Template.General}
|
|
44
|
-
renderTitle={(summary: DefaultOf<cnst.Summary>) => \`\${summary.at}\`}
|
|
45
|
-
renderView={(summary: cnst.Summary) => <Summary.View.General summary={summary} />}
|
|
46
|
-
type="list"
|
|
47
|
-
columns={["type", "status", "createdAt"]}
|
|
48
|
-
actions={(summary: cnst.LightSummary, idx) => ["remove", "edit"]}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
33
|
export const Dashboard = () => {
|
|
54
34
|
const summary = st.use.summary();
|
|
55
35
|
if (!summary) return <Loading.Skeleton active />;
|
|
@@ -27,34 +27,9 @@ function getContent(scanInfo, dict) {
|
|
|
27
27
|
filename: "User.Util.tsx",
|
|
28
28
|
content: `
|
|
29
29
|
"use client";
|
|
30
|
-
import { clsx,
|
|
31
|
-
import { getQueryMap } from "@akanjs/constant";
|
|
32
|
-
import { cnst, st } from "@${dict.appName}/client";
|
|
33
|
-
import { Data } from "@akanjs/ui";
|
|
30
|
+
import { clsx, st } from "@${dict.appName}/client";
|
|
34
31
|
import { AiOutlineEdit, AiOutlineLock, AiOutlineUnlock } from "react-icons/ai";
|
|
35
32
|
|
|
36
|
-
export const Stat = ({
|
|
37
|
-
className,
|
|
38
|
-
summary,
|
|
39
|
-
sliceName = "user",
|
|
40
|
-
queryMap = getQueryMap(cnst.UserSummary),
|
|
41
|
-
hidePresents,
|
|
42
|
-
}: ModelDashboardProps<cnst.Summary>) => {
|
|
43
|
-
return (
|
|
44
|
-
<Data.Dashboard
|
|
45
|
-
className={clsx("", className)}
|
|
46
|
-
summary={summary}
|
|
47
|
-
sliceName={sliceName}
|
|
48
|
-
queryMap={queryMap}
|
|
49
|
-
columns={["totalUser", "dau"]}
|
|
50
|
-
hidePresents={hidePresents}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
export const Insight = ({ className, insight, sliceName = "user" }: ModelInsightProps<cnst.UserInsight>) => {
|
|
55
|
-
return <Data.Insight className={clsx("", className)} insight={insight} sliceName={sliceName} columns={["count"]} />;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
33
|
interface EditSelfProps {
|
|
59
34
|
className?: string;
|
|
60
35
|
}
|
|
@@ -27,36 +27,8 @@ function getContent(scanInfo, dict) {
|
|
|
27
27
|
filename: "User.Zone.tsx",
|
|
28
28
|
content: `
|
|
29
29
|
"use client";
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import { cnst, st, User } from "@${dict.appName}/client";
|
|
33
|
-
import { Data, Model } from "@akanjs/ui";
|
|
34
|
-
|
|
35
|
-
export const Admin = ({ sliceName = "user", init, query }: ModelsProps<cnst.User>) => {
|
|
36
|
-
return (
|
|
37
|
-
<Data.ListContainer
|
|
38
|
-
init={init}
|
|
39
|
-
query={query}
|
|
40
|
-
sliceName={sliceName}
|
|
41
|
-
renderItem={User.Unit.Card}
|
|
42
|
-
renderDashboard={User.Util.Stat}
|
|
43
|
-
renderInsight={User.Util.Insight}
|
|
44
|
-
renderTemplate={User.Template.General}
|
|
45
|
-
renderTitle={(user: DefaultOf<cnst.User>) => \`\${user.nickname}\`}
|
|
46
|
-
renderView={(user: cnst.User) => <User.View.General user={user} />}
|
|
47
|
-
type="list"
|
|
48
|
-
columns={["nickname", "status", "lastLoginAt", "createdAt"]}
|
|
49
|
-
actions={(user: cnst.LightUser, idx) => [
|
|
50
|
-
"remove",
|
|
51
|
-
"edit",
|
|
52
|
-
"view",
|
|
53
|
-
user.status === "active"
|
|
54
|
-
? { type: "restrict", render: () => <User.Util.Restrict id={user.id} /> }
|
|
55
|
-
: { type: "release", render: () => <User.Util.Release id={user.id} /> },
|
|
56
|
-
]}
|
|
57
|
-
/>
|
|
58
|
-
);
|
|
59
|
-
};
|
|
30
|
+
import { st, User } from "@${dict.appName}/client";
|
|
31
|
+
import { Model } from "@akanjs/ui";
|
|
60
32
|
|
|
61
33
|
interface SelfProps {
|
|
62
34
|
className?: string;
|
|
@@ -36,13 +36,7 @@ export class UserInput extends by(rootUser.Input, cnst.UserInput) {}
|
|
|
36
36
|
export class User extends by(rootUser.Doc, cnst.User) {}
|
|
37
37
|
|
|
38
38
|
@Database.Model(() => cnst.User)
|
|
39
|
-
export class UserModel extends into(User, cnst.userCnst) {
|
|
40
|
-
async getSummary(): Promise<cnst.UserSummary> {
|
|
41
|
-
return {
|
|
42
|
-
...(await this.getDefaultSummary()),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
39
|
+
export class UserModel extends into(User, cnst.userCnst) {}
|
|
46
40
|
|
|
47
41
|
@Database.Middleware(() => cnst.User)
|
|
48
42
|
export class UserMiddleware extends beyond(UserModel, User) {
|
|
@@ -31,12 +31,6 @@ import { cnst } from "../cnst";
|
|
|
31
31
|
import * as db from "../db";
|
|
32
32
|
|
|
33
33
|
@Service("UserService")
|
|
34
|
-
export class UserService extends ExtendedUserService(db.userDb, LibUserService) {
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
...(await this.userModel.getSummary()),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
`;
|
|
34
|
+
export class UserService extends ExtendedUserService(db.userDb, LibUserService) {}
|
|
35
|
+
`;
|
|
42
36
|
}
|
|
@@ -60,7 +60,7 @@ ${databaseModulesWithoutExtendModels.map((module2) => ` @Srv() protected readon
|
|
|
60
60
|
async get${capitalize(scanInfo.name)}Summary() {
|
|
61
61
|
return {
|
|
62
62
|
${databaseModulesWithoutExtendModels.map((module2) => ` ...(await this.${module2}Service.summarize()),`).join("\n")}
|
|
63
|
-
...(await this.userService.summarize
|
|
63
|
+
...(await this.userService.summarize()),
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
${scanInfo.exec.type === "app" ? `
|
|
@@ -22,6 +22,7 @@ __export(cnst_exports, {
|
|
|
22
22
|
default: () => getContent
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(cnst_exports);
|
|
25
|
+
var capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
25
26
|
function getContent(scanInfo, dict = {}) {
|
|
26
27
|
if (!scanInfo)
|
|
27
28
|
return null;
|
|
@@ -29,10 +30,11 @@ function getContent(scanInfo, dict = {}) {
|
|
|
29
30
|
const scalarModules = scanInfo.getScalarModules();
|
|
30
31
|
const rootLib = scanInfo.akanConfig.rootLib;
|
|
31
32
|
return `
|
|
32
|
-
import { cnstOf } from "@akanjs/constant";
|
|
33
|
+
import { cnstOf, scalarCnstOf } from "@akanjs/constant";
|
|
33
34
|
|
|
34
35
|
${rootLib ? `import { root } from "./__lib/lib.constant";` : ""}
|
|
35
36
|
${databaseModules.map((module2) => `import * as ${module2} from "./${module2}/${module2}.constant";`).join("\n")}
|
|
37
|
+
${scalarModules.map((module2) => `import { ${capitalize(module2)} } from "./__scalar/${module2}/${module2}.constant";`).join("\n")}
|
|
36
38
|
|
|
37
39
|
export * from "./__lib/lib.constant";
|
|
38
40
|
${databaseModules.map((module2) => `export * from "./${module2}/${module2}.constant";`).join("\n")}
|
|
@@ -40,12 +42,13 @@ ${scalarModules.map((module2) => `export * from "./__scalar/${module2}/${module2
|
|
|
40
42
|
|
|
41
43
|
${databaseModules.map((module2) => {
|
|
42
44
|
const names = {
|
|
43
|
-
Module:
|
|
45
|
+
Module: capitalize(module2)
|
|
44
46
|
};
|
|
45
47
|
if (module2 === "setting" || module2 === "summary")
|
|
46
48
|
return `export const ${module2}Cnst = cnstOf("${module2}" as const, ${module2}.${names.Module}Input, ${module2}.${names.Module}, ${module2}.Light${names.Module}, ${rootLib ? "root" : module2}.${names.Module}Insight, ${rootLib ? "root" : module2}.${names.Module}Filter);`;
|
|
47
49
|
else
|
|
48
50
|
return `export const ${module2}Cnst = cnstOf("${module2}" as const, ${module2}.${names.Module}Input, ${module2}.${names.Module}, ${module2}.Light${names.Module}, ${module2}.${names.Module}Insight, ${module2}.${names.Module}Filter, ${module2}.${names.Module}Summary);`;
|
|
49
51
|
}).join("\n")}
|
|
52
|
+
${scalarModules.map((module2) => `export const ${module2}Cnst = scalarCnstOf("${module2}" as const, ${capitalize(module2)});`).join("\n")}
|
|
50
53
|
`;
|
|
51
54
|
}
|
|
@@ -40,7 +40,7 @@ ${databaseModules.map((module2) => `${["user", "setting", "summary"].includes(mo
|
|
|
40
40
|
|
|
41
41
|
export const fetch = makeFetch(...libFetches, {
|
|
42
42
|
${databaseModules.map((module2) => `...${module2}Gql,`).join("\n")}
|
|
43
|
-
${scalarConstantModules.map((module2) => `...scalarUtilOf(
|
|
43
|
+
${scalarConstantModules.map((module2) => `...scalarUtilOf(cnst.${module2}Cnst),`).join("\n")}
|
|
44
44
|
${serviceModules.map((module2) => `...fetchOf(sig.${capitalize(module2)}Signal),`).join("\n")}
|
|
45
45
|
${databaseModules.map((module2) => `${module2}Gql,`).join("\n")}
|
|
46
46
|
});
|
|
@@ -41,7 +41,6 @@ ${databaseModules.map((module2) => `import { ${capitalize(module2)}Store } from
|
|
|
41
41
|
${serviceModules.map((module2) => `import { ${capitalize(module2)}Store } from "./_${module2}/${module2}.store";`).join("\n")}
|
|
42
42
|
export class RootStore extends MixStore(
|
|
43
43
|
...libStores,
|
|
44
|
-
${names.Name}Store,
|
|
45
44
|
${[...databaseModules, ...serviceModules].map((module2) => `${capitalize(module2)}Store`).join(",\n ")}
|
|
46
45
|
) {}
|
|
47
46
|
|
|
@@ -27,29 +27,9 @@ function getContent(scanInfo, dict) {
|
|
|
27
27
|
filename: "Summary.Zone.tsx",
|
|
28
28
|
content: `
|
|
29
29
|
"use client";
|
|
30
|
-
import {
|
|
31
|
-
import { DefaultOf } from "@akanjs/signal";
|
|
32
|
-
import { cnst, st, Summary } from "@${dict.libName}/client";
|
|
33
|
-
import { Data } from "@akanjs/ui";
|
|
30
|
+
import { st, Summary } from "@${dict.libName}/client";
|
|
34
31
|
import { Loading } from "@akanjs/ui";
|
|
35
32
|
|
|
36
|
-
export const Admin = ({ sliceName = "summary", init, query }: ModelsProps<cnst.Summary>) => {
|
|
37
|
-
return (
|
|
38
|
-
<Data.ListContainer
|
|
39
|
-
init={init}
|
|
40
|
-
query={query}
|
|
41
|
-
sliceName={sliceName}
|
|
42
|
-
renderItem={Summary.Unit.Card}
|
|
43
|
-
renderTemplate={Summary.Template.General}
|
|
44
|
-
renderTitle={(summary: DefaultOf<cnst.Summary>) => \`\${summary.at}\`}
|
|
45
|
-
renderView={(summary: cnst.Summary) => <Summary.View.General summary={summary} />}
|
|
46
|
-
type="list"
|
|
47
|
-
columns={["type", "status", "createdAt"]}
|
|
48
|
-
actions={(summary: cnst.LightSummary, idx) => ["remove", "edit"]}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
};
|
|
52
|
-
|
|
53
33
|
export const Dashboard = () => {
|
|
54
34
|
const summary = st.use.summary();
|
|
55
35
|
if (!summary) return <Loading.Skeleton active />;
|
|
@@ -27,34 +27,9 @@ function getContent(scanInfo, dict) {
|
|
|
27
27
|
filename: "User.Util.tsx",
|
|
28
28
|
content: `
|
|
29
29
|
"use client";
|
|
30
|
-
import { clsx,
|
|
31
|
-
import { getQueryMap } from "@akanjs/constant";
|
|
32
|
-
import { cnst, st } from "@${dict.libName}/client";
|
|
33
|
-
import { Data } from "@akanjs/ui";
|
|
30
|
+
import { clsx, st } from "@${dict.libName}/client";
|
|
34
31
|
import { AiOutlineEdit, AiOutlineLock, AiOutlineUnlock } from "react-icons/ai";
|
|
35
32
|
|
|
36
|
-
export const Stat = ({
|
|
37
|
-
className,
|
|
38
|
-
summary,
|
|
39
|
-
sliceName = "user",
|
|
40
|
-
queryMap = getQueryMap(cnst.UserSummary),
|
|
41
|
-
hidePresents,
|
|
42
|
-
}: ModelDashboardProps<cnst.Summary>) => {
|
|
43
|
-
return (
|
|
44
|
-
<Data.Dashboard
|
|
45
|
-
className={clsx("", className)}
|
|
46
|
-
summary={summary}
|
|
47
|
-
sliceName={sliceName}
|
|
48
|
-
queryMap={queryMap}
|
|
49
|
-
columns={["totalUser", "dau"]}
|
|
50
|
-
hidePresents={hidePresents}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
export const Insight = ({ className, insight, sliceName = "user" }: ModelInsightProps<cnst.UserInsight>) => {
|
|
55
|
-
return <Data.Insight className={clsx("", className)} insight={insight} sliceName={sliceName} columns={["count"]} />;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
33
|
interface EditSelfProps {
|
|
59
34
|
className?: string;
|
|
60
35
|
}
|