@alepha/devtools 0.11.3 → 0.11.4
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/dist/index.d.mts +370 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +360 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +26 -16
- package/src/DevCollectorProvider.ts +29 -29
- package/src/index.ts +4 -1
- package/src/ui/AppRouter.tsx +61 -0
- package/src/ui/DevLogs.tsx +143 -0
- package/src/ui/main.ts +4 -0
- package/src/ui/styles.css +7 -0
- package/src/ui/wotfardregular/stylesheet.css +12 -0
- package/src/ui/wotfardregular/wotfard-regular-webfont.eot +0 -0
- package/src/ui/wotfardregular/wotfard-regular-webfont.ttf +0 -0
- package/src/ui/wotfardregular/wotfard-regular-webfont.woff2 +0 -0
- package/dist/index.d.ts +0 -368
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1678
- package/dist/index.js.map +0 -1
- package/src/constants/ui.ts +0 -1317
- package/src/schemas/DevLogEntry.ts +0 -11
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { $hook, $inject, $module, Alepha, t } from "@alepha/core";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { $bucket } from "@alepha/bucket";
|
|
5
|
+
import { $cache } from "@alepha/cache";
|
|
6
|
+
import { $logger, logEntrySchema } from "@alepha/logger";
|
|
7
|
+
import { $queue } from "@alepha/queue";
|
|
8
|
+
import { $page } from "@alepha/react";
|
|
9
|
+
import { $scheduler } from "@alepha/scheduler";
|
|
10
|
+
import { $realm } from "@alepha/security";
|
|
11
|
+
import { $action, $route, ServerProvider } from "@alepha/server";
|
|
12
|
+
import { $serve } from "@alepha/server-static";
|
|
13
|
+
import { $topic } from "@alepha/topic";
|
|
14
|
+
|
|
15
|
+
//#region src/schemas/DevActionMetadata.ts
|
|
16
|
+
const devActionMetadataSchema = t.object({
|
|
17
|
+
name: t.text(),
|
|
18
|
+
group: t.text(),
|
|
19
|
+
method: t.text(),
|
|
20
|
+
path: t.text(),
|
|
21
|
+
prefix: t.text(),
|
|
22
|
+
fullPath: t.text(),
|
|
23
|
+
description: t.optional(t.text()),
|
|
24
|
+
summary: t.optional(t.text()),
|
|
25
|
+
disabled: t.optional(t.boolean()),
|
|
26
|
+
secure: t.optional(t.boolean()),
|
|
27
|
+
hide: t.optional(t.boolean()),
|
|
28
|
+
body: t.optional(t.any()),
|
|
29
|
+
params: t.optional(t.any()),
|
|
30
|
+
query: t.optional(t.any()),
|
|
31
|
+
response: t.optional(t.any()),
|
|
32
|
+
bodyContentType: t.optional(t.text())
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/schemas/DevBucketMetadata.ts
|
|
37
|
+
const devBucketMetadataSchema = t.object({
|
|
38
|
+
name: t.text(),
|
|
39
|
+
description: t.optional(t.text()),
|
|
40
|
+
mimeTypes: t.optional(t.array(t.text())),
|
|
41
|
+
maxSize: t.optional(t.number()),
|
|
42
|
+
provider: t.text()
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/schemas/DevCacheMetadata.ts
|
|
47
|
+
const devCacheMetadataSchema = t.object({
|
|
48
|
+
name: t.text(),
|
|
49
|
+
ttl: t.optional(t.any()),
|
|
50
|
+
disabled: t.optional(t.boolean()),
|
|
51
|
+
provider: t.text()
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/schemas/DevModuleMetadata.ts
|
|
56
|
+
const devModuleMetadataSchema = t.object({
|
|
57
|
+
name: t.text(),
|
|
58
|
+
providers: t.array(t.text())
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/schemas/DevPageMetadata.ts
|
|
63
|
+
const devPageMetadataSchema = t.object({
|
|
64
|
+
name: t.text(),
|
|
65
|
+
description: t.optional(t.text()),
|
|
66
|
+
path: t.optional(t.text()),
|
|
67
|
+
params: t.optional(t.any()),
|
|
68
|
+
query: t.optional(t.any()),
|
|
69
|
+
hasComponent: t.boolean(),
|
|
70
|
+
hasLazy: t.boolean(),
|
|
71
|
+
hasResolve: t.boolean(),
|
|
72
|
+
hasChildren: t.boolean(),
|
|
73
|
+
hasParent: t.boolean(),
|
|
74
|
+
hasErrorHandler: t.boolean(),
|
|
75
|
+
static: t.optional(t.boolean()),
|
|
76
|
+
cache: t.optional(t.any()),
|
|
77
|
+
client: t.optional(t.any()),
|
|
78
|
+
animation: t.optional(t.any())
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/schemas/DevProviderMetadata.ts
|
|
83
|
+
const devProviderMetadataSchema = t.object({
|
|
84
|
+
name: t.text(),
|
|
85
|
+
module: t.optional(t.text()),
|
|
86
|
+
dependencies: t.array(t.text()),
|
|
87
|
+
aliases: t.optional(t.array(t.text()))
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/schemas/DevQueueMetadata.ts
|
|
92
|
+
const devQueueMetadataSchema = t.object({
|
|
93
|
+
name: t.text(),
|
|
94
|
+
description: t.optional(t.text()),
|
|
95
|
+
schema: t.optional(t.any()),
|
|
96
|
+
provider: t.text()
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/schemas/DevRealmMetadata.ts
|
|
101
|
+
const devRealmMetadataSchema = t.object({
|
|
102
|
+
name: t.text(),
|
|
103
|
+
description: t.optional(t.text()),
|
|
104
|
+
roles: t.optional(t.array(t.any())),
|
|
105
|
+
type: t.enum(["internal", "external"]),
|
|
106
|
+
settings: t.optional(t.object({
|
|
107
|
+
accessTokenExpiration: t.optional(t.any()),
|
|
108
|
+
refreshTokenExpiration: t.optional(t.any()),
|
|
109
|
+
hasOnCreateSession: t.boolean(),
|
|
110
|
+
hasOnRefreshSession: t.boolean(),
|
|
111
|
+
hasOnDeleteSession: t.boolean()
|
|
112
|
+
}))
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/schemas/DevSchedulerMetadata.ts
|
|
117
|
+
const devSchedulerMetadataSchema = t.object({
|
|
118
|
+
name: t.text(),
|
|
119
|
+
description: t.optional(t.text()),
|
|
120
|
+
cron: t.optional(t.text()),
|
|
121
|
+
interval: t.optional(t.any()),
|
|
122
|
+
lock: t.optional(t.boolean())
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/schemas/DevTopicMetadata.ts
|
|
127
|
+
const devTopicMetadataSchema = t.object({
|
|
128
|
+
name: t.text(),
|
|
129
|
+
description: t.optional(t.text()),
|
|
130
|
+
schema: t.optional(t.any()),
|
|
131
|
+
provider: t.text()
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/schemas/DevMetadata.ts
|
|
136
|
+
const devMetadataSchema = t.object({
|
|
137
|
+
actions: t.array(devActionMetadataSchema),
|
|
138
|
+
queues: t.array(devQueueMetadataSchema),
|
|
139
|
+
schedulers: t.array(devSchedulerMetadataSchema),
|
|
140
|
+
topics: t.array(devTopicMetadataSchema),
|
|
141
|
+
buckets: t.array(devBucketMetadataSchema),
|
|
142
|
+
realms: t.array(devRealmMetadataSchema),
|
|
143
|
+
caches: t.array(devCacheMetadataSchema),
|
|
144
|
+
pages: t.array(devPageMetadataSchema),
|
|
145
|
+
providers: t.array(devProviderMetadataSchema),
|
|
146
|
+
modules: t.array(devModuleMetadataSchema)
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/DevCollectorProvider.ts
|
|
151
|
+
var DevCollectorProvider = class {
|
|
152
|
+
alepha = $inject(Alepha);
|
|
153
|
+
serverProvider = $inject(ServerProvider);
|
|
154
|
+
log = $logger();
|
|
155
|
+
logs = [];
|
|
156
|
+
maxLogs = 1e4;
|
|
157
|
+
onStart = $hook({
|
|
158
|
+
on: "start",
|
|
159
|
+
handler: () => {
|
|
160
|
+
this.log.info(`Devtools available at ${this.serverProvider.hostname}/devtools/`);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
onLog = $hook({
|
|
164
|
+
on: "log",
|
|
165
|
+
handler: (ev) => {
|
|
166
|
+
this.logs.unshift(ev.entry);
|
|
167
|
+
if (this.logs.length > this.maxLogs) this.logs.pop();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
uiRoute = $serve({
|
|
171
|
+
path: "/devtools",
|
|
172
|
+
root: join(fileURLToPath(import.meta.url), "../../assets/devtools")
|
|
173
|
+
});
|
|
174
|
+
metadataRoute = $route({
|
|
175
|
+
method: "GET",
|
|
176
|
+
path: "/devtools/api/metadata",
|
|
177
|
+
silent: true,
|
|
178
|
+
schema: { response: devMetadataSchema },
|
|
179
|
+
handler: () => {
|
|
180
|
+
return this.getMetadata();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
logsRoute = $route({
|
|
184
|
+
method: "GET",
|
|
185
|
+
path: "/devtools/api/logs",
|
|
186
|
+
silent: true,
|
|
187
|
+
schema: { response: t.array(logEntrySchema) },
|
|
188
|
+
handler: () => {
|
|
189
|
+
return this.getLogs();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
getLogs() {
|
|
193
|
+
return this.logs;
|
|
194
|
+
}
|
|
195
|
+
getActions() {
|
|
196
|
+
return this.alepha.descriptors($action).map((action) => {
|
|
197
|
+
const schema = action.schema;
|
|
198
|
+
const options = action.options;
|
|
199
|
+
return {
|
|
200
|
+
name: action.name,
|
|
201
|
+
group: action.group,
|
|
202
|
+
method: action.method,
|
|
203
|
+
path: action.path,
|
|
204
|
+
prefix: action.prefix,
|
|
205
|
+
fullPath: action.route.path,
|
|
206
|
+
description: action.options.description,
|
|
207
|
+
summary: options.summary,
|
|
208
|
+
disabled: action.options.disabled,
|
|
209
|
+
secure: options.secure,
|
|
210
|
+
hide: options.hide,
|
|
211
|
+
body: schema?.body,
|
|
212
|
+
params: schema?.params,
|
|
213
|
+
query: schema?.query,
|
|
214
|
+
response: schema?.response,
|
|
215
|
+
bodyContentType: action.getBodyContentType()
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
getQueues() {
|
|
220
|
+
return this.alepha.descriptors($queue).map((queue) => ({
|
|
221
|
+
name: queue.name,
|
|
222
|
+
description: queue.options.description,
|
|
223
|
+
schema: queue.options.schema,
|
|
224
|
+
provider: this.getProviderName(queue.options.provider)
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
getSchedulers() {
|
|
228
|
+
return this.alepha.descriptors($scheduler).map((scheduler) => ({
|
|
229
|
+
name: scheduler.name,
|
|
230
|
+
description: scheduler.options.description,
|
|
231
|
+
cron: scheduler.options.cron,
|
|
232
|
+
interval: scheduler.options.interval,
|
|
233
|
+
lock: scheduler.options.lock
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
getTopics() {
|
|
237
|
+
return this.alepha.descriptors($topic).map((topic) => ({
|
|
238
|
+
name: topic.name,
|
|
239
|
+
description: topic.options.description,
|
|
240
|
+
schema: topic.options.schema,
|
|
241
|
+
provider: this.getProviderName(topic.options.provider)
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
getBuckets() {
|
|
245
|
+
return this.alepha.descriptors($bucket).map((bucket) => ({
|
|
246
|
+
name: bucket.name,
|
|
247
|
+
description: bucket.options.description,
|
|
248
|
+
mimeTypes: bucket.options.mimeTypes,
|
|
249
|
+
maxSize: bucket.options.maxSize,
|
|
250
|
+
provider: this.getProviderName(bucket.options.provider)
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
getRealms() {
|
|
254
|
+
return this.alepha.descriptors($realm).map((realm) => ({
|
|
255
|
+
name: realm.name,
|
|
256
|
+
description: realm.options.description,
|
|
257
|
+
roles: realm.options.roles,
|
|
258
|
+
type: "secret" in realm.options ? "internal" : "external",
|
|
259
|
+
settings: {
|
|
260
|
+
accessTokenExpiration: realm.options.settings?.accessToken?.expiration,
|
|
261
|
+
refreshTokenExpiration: realm.options.settings?.refreshToken?.expiration,
|
|
262
|
+
hasOnCreateSession: !!realm.options.settings?.onCreateSession,
|
|
263
|
+
hasOnRefreshSession: !!realm.options.settings?.onRefreshSession,
|
|
264
|
+
hasOnDeleteSession: !!realm.options.settings?.onDeleteSession
|
|
265
|
+
}
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
getCaches() {
|
|
269
|
+
return this.alepha.descriptors($cache).map((cache) => ({
|
|
270
|
+
name: cache.container,
|
|
271
|
+
ttl: cache.options.ttl,
|
|
272
|
+
disabled: cache.options.disabled,
|
|
273
|
+
provider: this.getProviderName(cache.options.provider)
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
getPages() {
|
|
277
|
+
return this.alepha.descriptors($page).map((page) => ({
|
|
278
|
+
name: page.name,
|
|
279
|
+
description: page.options.description,
|
|
280
|
+
path: page.options.path,
|
|
281
|
+
params: page.options.schema?.params,
|
|
282
|
+
query: page.options.schema?.query,
|
|
283
|
+
hasComponent: !!page.options.component,
|
|
284
|
+
hasLazy: !!page.options.lazy,
|
|
285
|
+
hasResolve: !!page.options.resolve,
|
|
286
|
+
hasChildren: !!page.options.children,
|
|
287
|
+
hasParent: !!page.options.parent,
|
|
288
|
+
hasErrorHandler: !!page.options.errorHandler,
|
|
289
|
+
static: typeof page.options.static === "boolean" ? page.options.static : !!page.options.static,
|
|
290
|
+
cache: page.options.cache,
|
|
291
|
+
client: page.options.client,
|
|
292
|
+
animation: page.options.animation
|
|
293
|
+
}));
|
|
294
|
+
}
|
|
295
|
+
getProviders() {
|
|
296
|
+
const graph = this.alepha.graph();
|
|
297
|
+
return Object.entries(graph).map(([name, info]) => ({
|
|
298
|
+
name,
|
|
299
|
+
module: info.module,
|
|
300
|
+
dependencies: info.from,
|
|
301
|
+
aliases: info.as
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
getModules() {
|
|
305
|
+
const graph = this.alepha.graph();
|
|
306
|
+
const moduleMap = /* @__PURE__ */ new Map();
|
|
307
|
+
for (const [providerName, info] of Object.entries(graph)) if (info.module) {
|
|
308
|
+
if (!moduleMap.has(info.module)) moduleMap.set(info.module, /* @__PURE__ */ new Set());
|
|
309
|
+
moduleMap.get(info.module).add(providerName);
|
|
310
|
+
}
|
|
311
|
+
return Array.from(moduleMap.entries()).map(([name, providers]) => ({
|
|
312
|
+
name,
|
|
313
|
+
providers: Array.from(providers)
|
|
314
|
+
}));
|
|
315
|
+
}
|
|
316
|
+
getMetadata() {
|
|
317
|
+
return {
|
|
318
|
+
actions: this.getActions(),
|
|
319
|
+
queues: this.getQueues(),
|
|
320
|
+
schedulers: this.getSchedulers(),
|
|
321
|
+
topics: this.getTopics(),
|
|
322
|
+
buckets: this.getBuckets(),
|
|
323
|
+
realms: this.getRealms(),
|
|
324
|
+
caches: this.getCaches(),
|
|
325
|
+
pages: this.getPages(),
|
|
326
|
+
providers: this.getProviders(),
|
|
327
|
+
modules: this.getModules()
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
getProviderName(provider) {
|
|
331
|
+
if (!provider) return "default";
|
|
332
|
+
if (provider === "memory") return "memory";
|
|
333
|
+
return provider.name || "custom";
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/index.ts
|
|
339
|
+
/**
|
|
340
|
+
* Developer tools module for monitoring and debugging Alepha applications.
|
|
341
|
+
*
|
|
342
|
+
* This module provides comprehensive data collection capabilities for tracking application behavior,
|
|
343
|
+
* performance metrics, and debugging information in real-time.
|
|
344
|
+
*
|
|
345
|
+
* @see {@link DevCollectorProvider}
|
|
346
|
+
* @module alepha.devtools
|
|
347
|
+
*/
|
|
348
|
+
const AlephaDevtools = $module({
|
|
349
|
+
name: "alepha.devtools",
|
|
350
|
+
descriptors: [],
|
|
351
|
+
services: [DevCollectorProvider],
|
|
352
|
+
register: (alepha) => {
|
|
353
|
+
alepha.with(DevCollectorProvider);
|
|
354
|
+
alepha.state.push("assets", "@alepha/devtools");
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
//#endregion
|
|
359
|
+
export { AlephaDevtools, DevCollectorProvider, devActionMetadataSchema, devBucketMetadataSchema, devCacheMetadataSchema, devMetadataSchema, devModuleMetadataSchema, devPageMetadataSchema, devProviderMetadataSchema, devQueueMetadataSchema, devRealmMetadataSchema, devSchedulerMetadataSchema, devTopicMetadataSchema };
|
|
360
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/schemas/DevActionMetadata.ts","../src/schemas/DevBucketMetadata.ts","../src/schemas/DevCacheMetadata.ts","../src/schemas/DevModuleMetadata.ts","../src/schemas/DevPageMetadata.ts","../src/schemas/DevProviderMetadata.ts","../src/schemas/DevQueueMetadata.ts","../src/schemas/DevRealmMetadata.ts","../src/schemas/DevSchedulerMetadata.ts","../src/schemas/DevTopicMetadata.ts","../src/schemas/DevMetadata.ts","../src/DevCollectorProvider.ts","../src/index.ts"],"sourcesContent":["import { type Static, t } from \"@alepha/core\";\n\nexport const devActionMetadataSchema = t.object({\n name: t.text(),\n group: t.text(),\n method: t.text(),\n path: t.text(),\n prefix: t.text(),\n fullPath: t.text(),\n description: t.optional(t.text()),\n summary: t.optional(t.text()),\n disabled: t.optional(t.boolean()),\n secure: t.optional(t.boolean()),\n hide: t.optional(t.boolean()),\n body: t.optional(t.any()),\n params: t.optional(t.any()),\n query: t.optional(t.any()),\n response: t.optional(t.any()),\n bodyContentType: t.optional(t.text()),\n});\n\nexport type DevActionMetadata = Static<typeof devActionMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devBucketMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n mimeTypes: t.optional(t.array(t.text())),\n maxSize: t.optional(t.number()),\n provider: t.text(),\n});\n\nexport type DevBucketMetadata = Static<typeof devBucketMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devCacheMetadataSchema = t.object({\n name: t.text(),\n ttl: t.optional(t.any()),\n disabled: t.optional(t.boolean()),\n provider: t.text(),\n});\n\nexport type DevCacheMetadata = Static<typeof devCacheMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devModuleMetadataSchema = t.object({\n name: t.text(),\n providers: t.array(t.text()),\n});\n\nexport type DevModuleMetadata = Static<typeof devModuleMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devPageMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n path: t.optional(t.text()),\n params: t.optional(t.any()),\n query: t.optional(t.any()),\n hasComponent: t.boolean(),\n hasLazy: t.boolean(),\n hasResolve: t.boolean(),\n hasChildren: t.boolean(),\n hasParent: t.boolean(),\n hasErrorHandler: t.boolean(),\n static: t.optional(t.boolean()),\n cache: t.optional(t.any()),\n client: t.optional(t.any()),\n animation: t.optional(t.any()),\n});\n\nexport type DevPageMetadata = Static<typeof devPageMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devProviderMetadataSchema = t.object({\n name: t.text(),\n module: t.optional(t.text()),\n dependencies: t.array(t.text()),\n aliases: t.optional(t.array(t.text())),\n});\n\nexport type DevProviderMetadata = Static<typeof devProviderMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devQueueMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n schema: t.optional(t.any()),\n provider: t.text(),\n});\n\nexport type DevQueueMetadata = Static<typeof devQueueMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devRealmMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n roles: t.optional(t.array(t.any())),\n type: t.enum([\"internal\", \"external\"]),\n settings: t.optional(\n t.object({\n accessTokenExpiration: t.optional(t.any()),\n refreshTokenExpiration: t.optional(t.any()),\n hasOnCreateSession: t.boolean(),\n hasOnRefreshSession: t.boolean(),\n hasOnDeleteSession: t.boolean(),\n }),\n ),\n});\n\nexport type DevRealmMetadata = Static<typeof devRealmMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devSchedulerMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n cron: t.optional(t.text()),\n interval: t.optional(t.any()),\n lock: t.optional(t.boolean()),\n});\n\nexport type DevSchedulerMetadata = Static<typeof devSchedulerMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\n\nexport const devTopicMetadataSchema = t.object({\n name: t.text(),\n description: t.optional(t.text()),\n schema: t.optional(t.any()),\n provider: t.text(),\n});\n\nexport type DevTopicMetadata = Static<typeof devTopicMetadataSchema>;\n","import { type Static, t } from \"@alepha/core\";\nimport { devActionMetadataSchema } from \"./DevActionMetadata.ts\";\nimport { devBucketMetadataSchema } from \"./DevBucketMetadata.ts\";\nimport { devCacheMetadataSchema } from \"./DevCacheMetadata.ts\";\nimport { devModuleMetadataSchema } from \"./DevModuleMetadata.ts\";\nimport { devPageMetadataSchema } from \"./DevPageMetadata.ts\";\nimport { devProviderMetadataSchema } from \"./DevProviderMetadata.ts\";\nimport { devQueueMetadataSchema } from \"./DevQueueMetadata.ts\";\nimport { devRealmMetadataSchema } from \"./DevRealmMetadata.ts\";\nimport { devSchedulerMetadataSchema } from \"./DevSchedulerMetadata.ts\";\nimport { devTopicMetadataSchema } from \"./DevTopicMetadata.ts\";\n\nexport const devMetadataSchema = t.object({\n actions: t.array(devActionMetadataSchema),\n queues: t.array(devQueueMetadataSchema),\n schedulers: t.array(devSchedulerMetadataSchema),\n topics: t.array(devTopicMetadataSchema),\n buckets: t.array(devBucketMetadataSchema),\n realms: t.array(devRealmMetadataSchema),\n caches: t.array(devCacheMetadataSchema),\n pages: t.array(devPageMetadataSchema),\n providers: t.array(devProviderMetadataSchema),\n modules: t.array(devModuleMetadataSchema),\n // More metadata will be added here later\n});\n\nexport type DevMetadata = Static<typeof devMetadataSchema>;\n","import { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { $bucket } from \"@alepha/bucket\";\nimport { $cache } from \"@alepha/cache\";\nimport { $hook, $inject, Alepha, t } from \"@alepha/core\";\nimport { $logger, type LogEntry, logEntrySchema } from \"@alepha/logger\";\nimport { $queue } from \"@alepha/queue\";\nimport { $page } from \"@alepha/react\";\nimport { $scheduler } from \"@alepha/scheduler\";\nimport { $realm } from \"@alepha/security\";\nimport { $action, $route, ServerProvider } from \"@alepha/server\";\nimport { $serve } from \"@alepha/server-static\";\nimport { $topic } from \"@alepha/topic\";\nimport type { DevActionMetadata } from \"./schemas/DevActionMetadata.ts\";\nimport type { DevBucketMetadata } from \"./schemas/DevBucketMetadata.ts\";\nimport type { DevCacheMetadata } from \"./schemas/DevCacheMetadata.ts\";\nimport { type DevMetadata, devMetadataSchema } from \"./schemas/DevMetadata.ts\";\nimport type { DevModuleMetadata } from \"./schemas/DevModuleMetadata.ts\";\nimport type { DevPageMetadata } from \"./schemas/DevPageMetadata.ts\";\nimport type { DevProviderMetadata } from \"./schemas/DevProviderMetadata.ts\";\nimport type { DevQueueMetadata } from \"./schemas/DevQueueMetadata.ts\";\nimport type { DevRealmMetadata } from \"./schemas/DevRealmMetadata.ts\";\nimport type { DevSchedulerMetadata } from \"./schemas/DevSchedulerMetadata.ts\";\nimport type { DevTopicMetadata } from \"./schemas/DevTopicMetadata.ts\";\n\nexport class DevCollectorProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly serverProvider = $inject(ServerProvider);\n protected readonly log = $logger();\n protected readonly logs: LogEntry[] = [];\n protected readonly maxLogs = 10000;\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: () => {\n this.log.info(\n `Devtools available at ${this.serverProvider.hostname}/devtools/`,\n );\n },\n });\n\n protected readonly onLog = $hook({\n on: \"log\",\n handler: (ev: { message?: string; entry: LogEntry }) => {\n this.logs.unshift(ev.entry);\n\n // keep only the last 10000 logs\n if (this.logs.length > this.maxLogs) {\n this.logs.pop();\n }\n },\n });\n\n protected readonly uiRoute = $serve({\n path: \"/devtools\",\n root: join(fileURLToPath(import.meta.url), \"../../assets/devtools\"),\n });\n\n protected readonly metadataRoute = $route({\n method: \"GET\",\n path: \"/devtools/api/metadata\",\n silent: true,\n schema: {\n response: devMetadataSchema,\n },\n handler: () => {\n return this.getMetadata();\n },\n });\n\n protected readonly logsRoute = $route({\n method: \"GET\",\n path: \"/devtools/api/logs\",\n silent: true,\n schema: {\n response: t.array(logEntrySchema),\n },\n handler: () => {\n return this.getLogs();\n },\n });\n\n public getLogs(): LogEntry[] {\n return this.logs;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n public getActions(): DevActionMetadata[] {\n const actionDescriptors = this.alepha.descriptors($action);\n\n return actionDescriptors.map((action) => {\n const schema = action.schema;\n const options = action.options as any; // Allow accessing augmented properties\n\n return {\n name: action.name,\n group: action.group,\n method: action.method,\n path: action.path,\n prefix: action.prefix,\n fullPath: action.route.path,\n description: action.options.description,\n summary: options.summary,\n disabled: action.options.disabled,\n secure: options.secure,\n hide: options.hide,\n body: schema?.body,\n params: schema?.params,\n query: schema?.query,\n response: schema?.response,\n bodyContentType: action.getBodyContentType(),\n };\n });\n }\n\n public getQueues(): DevQueueMetadata[] {\n const queueDescriptors = this.alepha.descriptors($queue);\n\n return queueDescriptors.map((queue) => ({\n name: queue.name,\n description: queue.options.description,\n schema: queue.options.schema,\n provider: this.getProviderName(queue.options.provider),\n }));\n }\n\n public getSchedulers(): DevSchedulerMetadata[] {\n const schedulerDescriptors = this.alepha.descriptors($scheduler);\n\n return schedulerDescriptors.map((scheduler) => ({\n name: scheduler.name,\n description: scheduler.options.description,\n cron: scheduler.options.cron,\n interval: scheduler.options.interval,\n lock: scheduler.options.lock,\n }));\n }\n\n public getTopics(): DevTopicMetadata[] {\n const topicDescriptors = this.alepha.descriptors($topic);\n\n return topicDescriptors.map((topic) => ({\n name: topic.name,\n description: topic.options.description,\n schema: topic.options.schema,\n provider: this.getProviderName(topic.options.provider),\n }));\n }\n\n public getBuckets(): DevBucketMetadata[] {\n const bucketDescriptors = this.alepha.descriptors($bucket);\n\n return bucketDescriptors.map((bucket) => ({\n name: bucket.name,\n description: bucket.options.description,\n mimeTypes: bucket.options.mimeTypes,\n maxSize: bucket.options.maxSize,\n provider: this.getProviderName(bucket.options.provider),\n }));\n }\n\n public getRealms(): DevRealmMetadata[] {\n const realmDescriptors = this.alepha.descriptors($realm);\n\n return realmDescriptors.map((realm) => ({\n name: realm.name,\n description: realm.options.description,\n roles: realm.options.roles,\n type: \"secret\" in realm.options ? \"internal\" : \"external\",\n settings: {\n accessTokenExpiration: realm.options.settings?.accessToken?.expiration,\n refreshTokenExpiration:\n realm.options.settings?.refreshToken?.expiration,\n hasOnCreateSession: !!realm.options.settings?.onCreateSession,\n hasOnRefreshSession: !!realm.options.settings?.onRefreshSession,\n hasOnDeleteSession: !!realm.options.settings?.onDeleteSession,\n },\n }));\n }\n\n public getCaches(): DevCacheMetadata[] {\n const cacheDescriptors = this.alepha.descriptors($cache);\n\n return cacheDescriptors.map((cache) => ({\n name: cache.container,\n ttl: cache.options.ttl,\n disabled: cache.options.disabled,\n provider: this.getProviderName(cache.options.provider),\n }));\n }\n\n public getPages(): DevPageMetadata[] {\n const pageDescriptors = this.alepha.descriptors($page);\n\n return pageDescriptors.map((page) => ({\n name: page.name,\n description: page.options.description,\n path: page.options.path,\n params: page.options.schema?.params,\n query: page.options.schema?.query,\n hasComponent: !!page.options.component,\n hasLazy: !!page.options.lazy,\n hasResolve: !!page.options.resolve,\n hasChildren: !!page.options.children,\n hasParent: !!page.options.parent,\n hasErrorHandler: !!page.options.errorHandler,\n static:\n typeof page.options.static === \"boolean\"\n ? page.options.static\n : !!page.options.static,\n cache: page.options.cache,\n client: page.options.client,\n animation: page.options.animation,\n }));\n }\n\n public getProviders(): DevProviderMetadata[] {\n const graph = this.alepha.graph();\n\n return Object.entries(graph).map(([name, info]) => ({\n name,\n module: info.module,\n dependencies: info.from,\n aliases: info.as,\n }));\n }\n\n public getModules(): DevModuleMetadata[] {\n const graph = this.alepha.graph();\n const moduleMap = new Map<string, Set<string>>();\n\n // Group providers by module\n for (const [providerName, info] of Object.entries(graph)) {\n if (info.module) {\n if (!moduleMap.has(info.module)) {\n moduleMap.set(info.module, new Set());\n }\n moduleMap.get(info.module)!.add(providerName);\n }\n }\n\n return Array.from(moduleMap.entries()).map(([name, providers]) => ({\n name,\n providers: Array.from(providers),\n }));\n }\n\n public getMetadata(): DevMetadata {\n return {\n actions: this.getActions(),\n queues: this.getQueues(),\n schedulers: this.getSchedulers(),\n topics: this.getTopics(),\n buckets: this.getBuckets(),\n realms: this.getRealms(),\n caches: this.getCaches(),\n pages: this.getPages(),\n providers: this.getProviders(),\n modules: this.getModules(),\n };\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected getProviderName(provider?: \"memory\" | any): string {\n if (!provider) {\n return \"default\";\n }\n if (provider === \"memory\") {\n return \"memory\";\n }\n return provider.name || \"custom\";\n }\n}\n","import { $module } from \"@alepha/core\";\nimport { DevCollectorProvider } from \"./DevCollectorProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./DevCollectorProvider.ts\";\nexport * from \"./schemas/DevActionMetadata.ts\";\nexport * from \"./schemas/DevBucketMetadata.ts\";\nexport * from \"./schemas/DevCacheMetadata.ts\";\nexport * from \"./schemas/DevMetadata.ts\";\nexport * from \"./schemas/DevModuleMetadata.ts\";\nexport * from \"./schemas/DevPageMetadata.ts\";\nexport * from \"./schemas/DevProviderMetadata.ts\";\nexport * from \"./schemas/DevQueueMetadata.ts\";\nexport * from \"./schemas/DevRealmMetadata.ts\";\nexport * from \"./schemas/DevSchedulerMetadata.ts\";\nexport * from \"./schemas/DevTopicMetadata.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Developer tools module for monitoring and debugging Alepha applications.\n *\n * This module provides comprehensive data collection capabilities for tracking application behavior,\n * performance metrics, and debugging information in real-time.\n *\n * @see {@link DevCollectorProvider}\n * @module alepha.devtools\n */\nexport const AlephaDevtools = $module({\n name: \"alepha.devtools\",\n descriptors: [],\n services: [DevCollectorProvider],\n register: (alepha) => {\n alepha.with(DevCollectorProvider);\n alepha.state.push(\"assets\", \"@alepha/devtools\");\n },\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alepha/devtools",
|
|
3
3
|
"description": "Developer tools for monitoring and debugging Alepha applications.",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=22.0.0"
|
|
@@ -14,28 +14,38 @@
|
|
|
14
14
|
"src"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@alepha/bucket": "0.11.
|
|
18
|
-
"@alepha/cache": "0.11.
|
|
19
|
-
"@alepha/core": "0.11.
|
|
20
|
-
"@alepha/logger": "0.11.
|
|
21
|
-
"@alepha/queue": "0.11.
|
|
22
|
-
"@alepha/react": "0.11.
|
|
23
|
-
"@alepha/
|
|
24
|
-
"@alepha/
|
|
25
|
-
"@alepha/
|
|
26
|
-
"@alepha/
|
|
17
|
+
"@alepha/bucket": "0.11.4",
|
|
18
|
+
"@alepha/cache": "0.11.4",
|
|
19
|
+
"@alepha/core": "0.11.4",
|
|
20
|
+
"@alepha/logger": "0.11.4",
|
|
21
|
+
"@alepha/queue": "0.11.4",
|
|
22
|
+
"@alepha/react": "0.11.4",
|
|
23
|
+
"@alepha/react-i18n": "0.11.4",
|
|
24
|
+
"@alepha/scheduler": "0.11.4",
|
|
25
|
+
"@alepha/security": "0.11.4",
|
|
26
|
+
"@alepha/server": "0.11.4",
|
|
27
|
+
"@alepha/server-static": "0.11.4",
|
|
28
|
+
"@alepha/topic": "0.11.4"
|
|
27
29
|
},
|
|
28
30
|
"devDependencies": {
|
|
29
|
-
"@
|
|
30
|
-
"
|
|
31
|
+
"@alepha/cli": "0.11.4",
|
|
32
|
+
"@alepha/ui": "0.11.4",
|
|
33
|
+
"@alepha/vite": "0.11.4",
|
|
34
|
+
"@biomejs/biome": "^2.3.3",
|
|
35
|
+
"@tabler/icons-react": "^3.35.0",
|
|
36
|
+
"react": "^19.2.0",
|
|
37
|
+
"tsdown": "^0.16.0",
|
|
31
38
|
"typescript": "^5.9.3",
|
|
32
|
-
"vitest": "^
|
|
39
|
+
"vitest": "^4.0.6"
|
|
33
40
|
},
|
|
34
41
|
"scripts": {
|
|
35
42
|
"test": "vitest run",
|
|
36
43
|
"lint": "biome check --fix",
|
|
37
|
-
"build": "
|
|
38
|
-
"
|
|
44
|
+
"build:ui": "alepha build && rm -r assets/devtools && cp -r dist/public assets/devtools",
|
|
45
|
+
"build": "yarn ui:build && tsdown -c=../../tsdown.config.ts",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"ui:dev": "alepha dev",
|
|
48
|
+
"ui:build": "alepha build && rm -r assets/devtools && cp -r dist/public assets/devtools"
|
|
39
49
|
},
|
|
40
50
|
"homepage": "https://github.com/feunard/alepha",
|
|
41
51
|
"repository": {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
1
3
|
import { $bucket } from "@alepha/bucket";
|
|
2
4
|
import { $cache } from "@alepha/cache";
|
|
3
5
|
import { $hook, $inject, Alepha, t } from "@alepha/core";
|
|
4
|
-
import type
|
|
6
|
+
import { $logger, type LogEntry, logEntrySchema } from "@alepha/logger";
|
|
5
7
|
import { $queue } from "@alepha/queue";
|
|
6
8
|
import { $page } from "@alepha/react";
|
|
7
9
|
import { $scheduler } from "@alepha/scheduler";
|
|
8
10
|
import { $realm } from "@alepha/security";
|
|
9
|
-
import { $action, $route } from "@alepha/server";
|
|
11
|
+
import { $action, $route, ServerProvider } from "@alepha/server";
|
|
12
|
+
import { $serve } from "@alepha/server-static";
|
|
10
13
|
import { $topic } from "@alepha/topic";
|
|
11
|
-
import { ui } from "./constants/ui.ts";
|
|
12
14
|
import type { DevActionMetadata } from "./schemas/DevActionMetadata.ts";
|
|
13
15
|
import type { DevBucketMetadata } from "./schemas/DevBucketMetadata.ts";
|
|
14
16
|
import type { DevCacheMetadata } from "./schemas/DevCacheMetadata.ts";
|
|
15
|
-
import type { DevLogEntry } from "./schemas/DevLogEntry.ts";
|
|
16
17
|
import { type DevMetadata, devMetadataSchema } from "./schemas/DevMetadata.ts";
|
|
17
18
|
import type { DevModuleMetadata } from "./schemas/DevModuleMetadata.ts";
|
|
18
19
|
import type { DevPageMetadata } from "./schemas/DevPageMetadata.ts";
|
|
@@ -24,38 +25,41 @@ import type { DevTopicMetadata } from "./schemas/DevTopicMetadata.ts";
|
|
|
24
25
|
|
|
25
26
|
export class DevCollectorProvider {
|
|
26
27
|
protected readonly alepha = $inject(Alepha);
|
|
27
|
-
protected readonly
|
|
28
|
+
protected readonly serverProvider = $inject(ServerProvider);
|
|
29
|
+
protected readonly log = $logger();
|
|
30
|
+
protected readonly logs: LogEntry[] = [];
|
|
28
31
|
protected readonly maxLogs = 10000;
|
|
29
32
|
|
|
33
|
+
protected readonly onStart = $hook({
|
|
34
|
+
on: "start",
|
|
35
|
+
handler: () => {
|
|
36
|
+
this.log.info(
|
|
37
|
+
`Devtools available at ${this.serverProvider.hostname}/devtools/`,
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
30
42
|
protected readonly onLog = $hook({
|
|
31
43
|
on: "log",
|
|
32
|
-
handler: (ev: { message
|
|
33
|
-
this.logs.
|
|
34
|
-
formatted: ev.message,
|
|
35
|
-
entry: ev.entry,
|
|
36
|
-
});
|
|
44
|
+
handler: (ev: { message?: string; entry: LogEntry }) => {
|
|
45
|
+
this.logs.unshift(ev.entry);
|
|
37
46
|
|
|
38
|
-
//
|
|
47
|
+
// keep only the last 10000 logs
|
|
39
48
|
if (this.logs.length > this.maxLogs) {
|
|
40
|
-
this.logs.
|
|
49
|
+
this.logs.pop();
|
|
41
50
|
}
|
|
42
51
|
},
|
|
43
52
|
});
|
|
44
53
|
|
|
45
|
-
protected readonly uiRoute = $
|
|
46
|
-
method: "GET",
|
|
54
|
+
protected readonly uiRoute = $serve({
|
|
47
55
|
path: "/devtools",
|
|
48
|
-
|
|
49
|
-
response: t.text(),
|
|
50
|
-
},
|
|
51
|
-
handler: () => {
|
|
52
|
-
return ui;
|
|
53
|
-
},
|
|
56
|
+
root: join(fileURLToPath(import.meta.url), "../../assets/devtools"),
|
|
54
57
|
});
|
|
55
58
|
|
|
56
59
|
protected readonly metadataRoute = $route({
|
|
57
60
|
method: "GET",
|
|
58
|
-
path: "/devtools/metadata",
|
|
61
|
+
path: "/devtools/api/metadata",
|
|
62
|
+
silent: true,
|
|
59
63
|
schema: {
|
|
60
64
|
response: devMetadataSchema,
|
|
61
65
|
},
|
|
@@ -66,21 +70,17 @@ export class DevCollectorProvider {
|
|
|
66
70
|
|
|
67
71
|
protected readonly logsRoute = $route({
|
|
68
72
|
method: "GET",
|
|
69
|
-
path: "/devtools/logs",
|
|
73
|
+
path: "/devtools/api/logs",
|
|
74
|
+
silent: true,
|
|
70
75
|
schema: {
|
|
71
|
-
response: t.array(
|
|
72
|
-
t.object({
|
|
73
|
-
formatted: t.text(),
|
|
74
|
-
entry: t.any(),
|
|
75
|
-
}),
|
|
76
|
-
),
|
|
76
|
+
response: t.array(logEntrySchema),
|
|
77
77
|
},
|
|
78
78
|
handler: () => {
|
|
79
79
|
return this.getLogs();
|
|
80
80
|
},
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
public getLogs():
|
|
83
|
+
public getLogs(): LogEntry[] {
|
|
84
84
|
return this.logs;
|
|
85
85
|
}
|
|
86
86
|
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export * from "./DevCollectorProvider.ts";
|
|
|
7
7
|
export * from "./schemas/DevActionMetadata.ts";
|
|
8
8
|
export * from "./schemas/DevBucketMetadata.ts";
|
|
9
9
|
export * from "./schemas/DevCacheMetadata.ts";
|
|
10
|
-
export * from "./schemas/DevLogEntry.ts";
|
|
11
10
|
export * from "./schemas/DevMetadata.ts";
|
|
12
11
|
export * from "./schemas/DevModuleMetadata.ts";
|
|
13
12
|
export * from "./schemas/DevPageMetadata.ts";
|
|
@@ -32,4 +31,8 @@ export const AlephaDevtools = $module({
|
|
|
32
31
|
name: "alepha.devtools",
|
|
33
32
|
descriptors: [],
|
|
34
33
|
services: [DevCollectorProvider],
|
|
34
|
+
register: (alepha) => {
|
|
35
|
+
alepha.with(DevCollectorProvider);
|
|
36
|
+
alepha.state.push("assets", "@alepha/devtools");
|
|
37
|
+
},
|
|
35
38
|
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { $page } from "@alepha/react";
|
|
2
|
+
import { AdminShell, RootRouter, Text, ui } from "@alepha/ui";
|
|
3
|
+
import { IconDashboard, IconLogs } from "@tabler/icons-react";
|
|
4
|
+
import DevLogs from "./DevLogs.tsx";
|
|
5
|
+
|
|
6
|
+
export class AppRouter extends RootRouter {
|
|
7
|
+
layout = $page({
|
|
8
|
+
parent: this.root,
|
|
9
|
+
component: () => (
|
|
10
|
+
<AdminShell
|
|
11
|
+
appShellProps={{
|
|
12
|
+
bg: ui.colors.surface,
|
|
13
|
+
}}
|
|
14
|
+
appShellNavbarProps={{
|
|
15
|
+
bg: ui.colors.transparent,
|
|
16
|
+
}}
|
|
17
|
+
appShellHeaderProps={{
|
|
18
|
+
bg: ui.colors.transparent,
|
|
19
|
+
style: {
|
|
20
|
+
backdropFilter: "blur(10px)",
|
|
21
|
+
},
|
|
22
|
+
}}
|
|
23
|
+
sidebarProps={{
|
|
24
|
+
collapsed: true,
|
|
25
|
+
gap: "xs",
|
|
26
|
+
}}
|
|
27
|
+
appBarProps={{
|
|
28
|
+
items: [
|
|
29
|
+
{ position: "left", type: "burger" },
|
|
30
|
+
{
|
|
31
|
+
position: "center",
|
|
32
|
+
element: (
|
|
33
|
+
<Text fw="bold" size="lg">
|
|
34
|
+
Alepha DevTools
|
|
35
|
+
</Text>
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
dashboard = $page({
|
|
45
|
+
path: "/",
|
|
46
|
+
label: "Dashboard",
|
|
47
|
+
icon: <IconDashboard />,
|
|
48
|
+
static: true,
|
|
49
|
+
parent: this.layout,
|
|
50
|
+
component: () => <div>Dashboard</div>,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
logs = $page({
|
|
54
|
+
path: "/logs",
|
|
55
|
+
label: "Logs",
|
|
56
|
+
icon: <IconLogs />,
|
|
57
|
+
static: true,
|
|
58
|
+
parent: this.layout,
|
|
59
|
+
component: DevLogs,
|
|
60
|
+
});
|
|
61
|
+
}
|