@alepha/devtools 0.10.6 → 0.11.0

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.
@@ -23,249 +23,253 @@ import type { DevSchedulerMetadata } from "./schemas/DevSchedulerMetadata.ts";
23
23
  import type { DevTopicMetadata } from "./schemas/DevTopicMetadata.ts";
24
24
 
25
25
  export class DevCollectorProvider {
26
- protected readonly alepha = $inject(Alepha);
27
- protected readonly logs: DevLogEntry[] = [];
28
- protected readonly maxLogs = 10000;
29
-
30
- protected readonly onLog = $hook({
31
- on: "log",
32
- handler: (ev: { message: string; entry: LogEntry }) => {
33
- this.logs.push({
34
- formatted: ev.message,
35
- entry: ev.entry,
36
- });
37
-
38
- // Keep only the last 10000 logs
39
- if (this.logs.length > this.maxLogs) {
40
- this.logs.shift();
41
- }
42
- },
43
- });
44
-
45
- protected readonly uiRoute = $route({
46
- method: "GET",
47
- path: "/devtools",
48
- schema: {
49
- response: t.text(),
50
- },
51
- handler: () => {
52
- return ui;
53
- },
54
- });
55
-
56
- protected readonly metadataRoute = $route({
57
- method: "GET",
58
- path: "/devtools/metadata",
59
- schema: {
60
- response: devMetadataSchema,
61
- },
62
- handler: () => {
63
- return this.getMetadata();
64
- },
65
- });
66
-
67
- protected readonly logsRoute = $route({
68
- method: "GET",
69
- path: "/devtools/logs",
70
- schema: {
71
- response: t.array(
72
- t.object({
73
- formatted: t.text(),
74
- entry: t.any(),
75
- }),
76
- ),
77
- },
78
- handler: () => {
79
- return this.getLogs();
80
- },
81
- });
82
-
83
- public getLogs(): DevLogEntry[] {
84
- return this.logs;
85
- }
86
-
87
- public getActions(): DevActionMetadata[] {
88
- const actionDescriptors = this.alepha.descriptors($action);
89
-
90
- return actionDescriptors.map((action) => {
91
- const schema = action.schema;
92
- const options = action.options as any; // Allow accessing augmented properties
93
-
94
- return {
95
- name: action.name,
96
- group: action.group,
97
- method: action.method,
98
- path: action.path,
99
- prefix: action.prefix,
100
- fullPath: action.route.path,
101
- description: action.options.description,
102
- summary: options.summary,
103
- disabled: action.options.disabled,
104
- secure: options.secure,
105
- hide: options.hide,
106
- body: schema?.body,
107
- params: schema?.params,
108
- query: schema?.query,
109
- response: schema?.response,
110
- bodyContentType: action.getBodyContentType(),
111
- };
112
- });
113
- }
114
-
115
- public getQueues(): DevQueueMetadata[] {
116
- const queueDescriptors = this.alepha.descriptors($queue);
117
-
118
- return queueDescriptors.map((queue) => ({
119
- name: queue.name,
120
- description: queue.options.description,
121
- schema: queue.options.schema,
122
- provider: this.getProviderName(queue.options.provider),
123
- }));
124
- }
125
-
126
- public getSchedulers(): DevSchedulerMetadata[] {
127
- const schedulerDescriptors = this.alepha.descriptors($scheduler);
128
-
129
- return schedulerDescriptors.map((scheduler) => ({
130
- name: scheduler.name,
131
- description: scheduler.options.description,
132
- cron: scheduler.options.cron,
133
- interval: scheduler.options.interval,
134
- lock: scheduler.options.lock,
135
- }));
136
- }
137
-
138
- public getTopics(): DevTopicMetadata[] {
139
- const topicDescriptors = this.alepha.descriptors($topic);
140
-
141
- return topicDescriptors.map((topic) => ({
142
- name: topic.name,
143
- description: topic.options.description,
144
- schema: topic.options.schema,
145
- provider: this.getProviderName(topic.options.provider),
146
- }));
147
- }
148
-
149
- public getBuckets(): DevBucketMetadata[] {
150
- const bucketDescriptors = this.alepha.descriptors($bucket);
151
-
152
- return bucketDescriptors.map((bucket) => ({
153
- name: bucket.name,
154
- description: bucket.options.description,
155
- mimeTypes: bucket.options.mimeTypes,
156
- maxSize: bucket.options.maxSize,
157
- provider: this.getProviderName(bucket.options.provider),
158
- }));
159
- }
160
-
161
- public getRealms(): DevRealmMetadata[] {
162
- const realmDescriptors = this.alepha.descriptors($realm);
163
-
164
- return realmDescriptors.map((realm) => ({
165
- name: realm.name,
166
- description: realm.options.description,
167
- roles: realm.options.roles,
168
- type: "secret" in realm.options ? "internal" : "external",
169
- settings: {
170
- accessTokenExpiration: realm.options.settings?.accessToken?.expiration,
171
- refreshTokenExpiration:
172
- realm.options.settings?.refreshToken?.expiration,
173
- hasOnCreateSession: !!realm.options.settings?.onCreateSession,
174
- hasOnRefreshSession: !!realm.options.settings?.onRefreshSession,
175
- hasOnDeleteSession: !!realm.options.settings?.onDeleteSession,
176
- },
177
- }));
178
- }
179
-
180
- public getCaches(): DevCacheMetadata[] {
181
- const cacheDescriptors = this.alepha.descriptors($cache);
182
-
183
- return cacheDescriptors.map((cache) => ({
184
- name: cache.container,
185
- ttl: cache.options.ttl,
186
- disabled: cache.options.disabled,
187
- provider: this.getProviderName(cache.options.provider),
188
- }));
189
- }
190
-
191
- public getPages(): DevPageMetadata[] {
192
- const pageDescriptors = this.alepha.descriptors($page);
193
-
194
- return pageDescriptors.map((page) => ({
195
- name: page.name,
196
- description: page.options.description,
197
- path: page.options.path,
198
- params: page.options.schema?.params,
199
- query: page.options.schema?.query,
200
- hasComponent: !!page.options.component,
201
- hasLazy: !!page.options.lazy,
202
- hasResolve: !!page.options.resolve,
203
- hasChildren: !!page.options.children,
204
- hasParent: !!page.options.parent,
205
- hasErrorHandler: !!page.options.errorHandler,
206
- static:
207
- typeof page.options.static === "boolean"
208
- ? page.options.static
209
- : !!page.options.static,
210
- cache: page.options.cache,
211
- client: page.options.client,
212
- animation: page.options.animation,
213
- }));
214
- }
215
-
216
- public getProviders(): DevProviderMetadata[] {
217
- const graph = this.alepha.graph();
218
-
219
- return Object.entries(graph).map(([name, info]) => ({
220
- name,
221
- module: info.module,
222
- dependencies: info.from,
223
- aliases: info.as,
224
- }));
225
- }
226
-
227
- public getModules(): DevModuleMetadata[] {
228
- const graph = this.alepha.graph();
229
- const moduleMap = new Map<string, Set<string>>();
230
-
231
- // Group providers by module
232
- for (const [providerName, info] of Object.entries(graph)) {
233
- if (info.module) {
234
- if (!moduleMap.has(info.module)) {
235
- moduleMap.set(info.module, new Set());
236
- }
237
- moduleMap.get(info.module)!.add(providerName);
238
- }
239
- }
240
-
241
- return Array.from(moduleMap.entries()).map(([name, providers]) => ({
242
- name,
243
- providers: Array.from(providers),
244
- }));
245
- }
246
-
247
- public getMetadata(): DevMetadata {
248
- return {
249
- actions: this.getActions(),
250
- queues: this.getQueues(),
251
- schedulers: this.getSchedulers(),
252
- topics: this.getTopics(),
253
- buckets: this.getBuckets(),
254
- realms: this.getRealms(),
255
- caches: this.getCaches(),
256
- pages: this.getPages(),
257
- providers: this.getProviders(),
258
- modules: this.getModules(),
259
- };
260
- }
261
-
262
- protected getProviderName(provider?: "memory" | any): string {
263
- if (!provider) {
264
- return "default";
265
- }
266
- if (provider === "memory") {
267
- return "memory";
268
- }
269
- return provider.name || "custom";
270
- }
26
+ protected readonly alepha = $inject(Alepha);
27
+ protected readonly logs: DevLogEntry[] = [];
28
+ protected readonly maxLogs = 10000;
29
+
30
+ protected readonly onLog = $hook({
31
+ on: "log",
32
+ handler: (ev: { message: string; entry: LogEntry }) => {
33
+ this.logs.push({
34
+ formatted: ev.message,
35
+ entry: ev.entry,
36
+ });
37
+
38
+ // Keep only the last 10000 logs
39
+ if (this.logs.length > this.maxLogs) {
40
+ this.logs.shift();
41
+ }
42
+ },
43
+ });
44
+
45
+ protected readonly uiRoute = $route({
46
+ method: "GET",
47
+ path: "/devtools",
48
+ schema: {
49
+ response: t.text(),
50
+ },
51
+ handler: () => {
52
+ return ui;
53
+ },
54
+ });
55
+
56
+ protected readonly metadataRoute = $route({
57
+ method: "GET",
58
+ path: "/devtools/metadata",
59
+ schema: {
60
+ response: devMetadataSchema,
61
+ },
62
+ handler: () => {
63
+ return this.getMetadata();
64
+ },
65
+ });
66
+
67
+ protected readonly logsRoute = $route({
68
+ method: "GET",
69
+ path: "/devtools/logs",
70
+ schema: {
71
+ response: t.array(
72
+ t.object({
73
+ formatted: t.text(),
74
+ entry: t.any(),
75
+ }),
76
+ ),
77
+ },
78
+ handler: () => {
79
+ return this.getLogs();
80
+ },
81
+ });
82
+
83
+ public getLogs(): DevLogEntry[] {
84
+ return this.logs;
85
+ }
86
+
87
+ // -------------------------------------------------------------------------------------------------------------------
88
+
89
+ public getActions(): DevActionMetadata[] {
90
+ const actionDescriptors = this.alepha.descriptors($action);
91
+
92
+ return actionDescriptors.map((action) => {
93
+ const schema = action.schema;
94
+ const options = action.options as any; // Allow accessing augmented properties
95
+
96
+ return {
97
+ name: action.name,
98
+ group: action.group,
99
+ method: action.method,
100
+ path: action.path,
101
+ prefix: action.prefix,
102
+ fullPath: action.route.path,
103
+ description: action.options.description,
104
+ summary: options.summary,
105
+ disabled: action.options.disabled,
106
+ secure: options.secure,
107
+ hide: options.hide,
108
+ body: schema?.body,
109
+ params: schema?.params,
110
+ query: schema?.query,
111
+ response: schema?.response,
112
+ bodyContentType: action.getBodyContentType(),
113
+ };
114
+ });
115
+ }
116
+
117
+ public getQueues(): DevQueueMetadata[] {
118
+ const queueDescriptors = this.alepha.descriptors($queue);
119
+
120
+ return queueDescriptors.map((queue) => ({
121
+ name: queue.name,
122
+ description: queue.options.description,
123
+ schema: queue.options.schema,
124
+ provider: this.getProviderName(queue.options.provider),
125
+ }));
126
+ }
127
+
128
+ public getSchedulers(): DevSchedulerMetadata[] {
129
+ const schedulerDescriptors = this.alepha.descriptors($scheduler);
130
+
131
+ return schedulerDescriptors.map((scheduler) => ({
132
+ name: scheduler.name,
133
+ description: scheduler.options.description,
134
+ cron: scheduler.options.cron,
135
+ interval: scheduler.options.interval,
136
+ lock: scheduler.options.lock,
137
+ }));
138
+ }
139
+
140
+ public getTopics(): DevTopicMetadata[] {
141
+ const topicDescriptors = this.alepha.descriptors($topic);
142
+
143
+ return topicDescriptors.map((topic) => ({
144
+ name: topic.name,
145
+ description: topic.options.description,
146
+ schema: topic.options.schema,
147
+ provider: this.getProviderName(topic.options.provider),
148
+ }));
149
+ }
150
+
151
+ public getBuckets(): DevBucketMetadata[] {
152
+ const bucketDescriptors = this.alepha.descriptors($bucket);
153
+
154
+ return bucketDescriptors.map((bucket) => ({
155
+ name: bucket.name,
156
+ description: bucket.options.description,
157
+ mimeTypes: bucket.options.mimeTypes,
158
+ maxSize: bucket.options.maxSize,
159
+ provider: this.getProviderName(bucket.options.provider),
160
+ }));
161
+ }
162
+
163
+ public getRealms(): DevRealmMetadata[] {
164
+ const realmDescriptors = this.alepha.descriptors($realm);
165
+
166
+ return realmDescriptors.map((realm) => ({
167
+ name: realm.name,
168
+ description: realm.options.description,
169
+ roles: realm.options.roles,
170
+ type: "secret" in realm.options ? "internal" : "external",
171
+ settings: {
172
+ accessTokenExpiration: realm.options.settings?.accessToken?.expiration,
173
+ refreshTokenExpiration:
174
+ realm.options.settings?.refreshToken?.expiration,
175
+ hasOnCreateSession: !!realm.options.settings?.onCreateSession,
176
+ hasOnRefreshSession: !!realm.options.settings?.onRefreshSession,
177
+ hasOnDeleteSession: !!realm.options.settings?.onDeleteSession,
178
+ },
179
+ }));
180
+ }
181
+
182
+ public getCaches(): DevCacheMetadata[] {
183
+ const cacheDescriptors = this.alepha.descriptors($cache);
184
+
185
+ return cacheDescriptors.map((cache) => ({
186
+ name: cache.container,
187
+ ttl: cache.options.ttl,
188
+ disabled: cache.options.disabled,
189
+ provider: this.getProviderName(cache.options.provider),
190
+ }));
191
+ }
192
+
193
+ public getPages(): DevPageMetadata[] {
194
+ const pageDescriptors = this.alepha.descriptors($page);
195
+
196
+ return pageDescriptors.map((page) => ({
197
+ name: page.name,
198
+ description: page.options.description,
199
+ path: page.options.path,
200
+ params: page.options.schema?.params,
201
+ query: page.options.schema?.query,
202
+ hasComponent: !!page.options.component,
203
+ hasLazy: !!page.options.lazy,
204
+ hasResolve: !!page.options.resolve,
205
+ hasChildren: !!page.options.children,
206
+ hasParent: !!page.options.parent,
207
+ hasErrorHandler: !!page.options.errorHandler,
208
+ static:
209
+ typeof page.options.static === "boolean"
210
+ ? page.options.static
211
+ : !!page.options.static,
212
+ cache: page.options.cache,
213
+ client: page.options.client,
214
+ animation: page.options.animation,
215
+ }));
216
+ }
217
+
218
+ public getProviders(): DevProviderMetadata[] {
219
+ const graph = this.alepha.graph();
220
+
221
+ return Object.entries(graph).map(([name, info]) => ({
222
+ name,
223
+ module: info.module,
224
+ dependencies: info.from,
225
+ aliases: info.as,
226
+ }));
227
+ }
228
+
229
+ public getModules(): DevModuleMetadata[] {
230
+ const graph = this.alepha.graph();
231
+ const moduleMap = new Map<string, Set<string>>();
232
+
233
+ // Group providers by module
234
+ for (const [providerName, info] of Object.entries(graph)) {
235
+ if (info.module) {
236
+ if (!moduleMap.has(info.module)) {
237
+ moduleMap.set(info.module, new Set());
238
+ }
239
+ moduleMap.get(info.module)!.add(providerName);
240
+ }
241
+ }
242
+
243
+ return Array.from(moduleMap.entries()).map(([name, providers]) => ({
244
+ name,
245
+ providers: Array.from(providers),
246
+ }));
247
+ }
248
+
249
+ public getMetadata(): DevMetadata {
250
+ return {
251
+ actions: this.getActions(),
252
+ queues: this.getQueues(),
253
+ schedulers: this.getSchedulers(),
254
+ topics: this.getTopics(),
255
+ buckets: this.getBuckets(),
256
+ realms: this.getRealms(),
257
+ caches: this.getCaches(),
258
+ pages: this.getPages(),
259
+ providers: this.getProviders(),
260
+ modules: this.getModules(),
261
+ };
262
+ }
263
+
264
+ // -------------------------------------------------------------------------------------------------------------------
265
+
266
+ protected getProviderName(provider?: "memory" | any): string {
267
+ if (!provider) {
268
+ return "default";
269
+ }
270
+ if (provider === "memory") {
271
+ return "memory";
272
+ }
273
+ return provider.name || "custom";
274
+ }
271
275
  }
package/src/index.ts CHANGED
@@ -29,7 +29,7 @@ export * from "./schemas/DevTopicMetadata.ts";
29
29
  * @module alepha.devtools
30
30
  */
31
31
  export const AlephaDevtools = $module({
32
- name: "alepha.devtools",
33
- descriptors: [],
34
- services: [DevCollectorProvider],
32
+ name: "alepha.devtools",
33
+ descriptors: [],
34
+ services: [DevCollectorProvider],
35
35
  });
@@ -1,22 +1,22 @@
1
1
  import { type Static, t } from "@alepha/core";
2
2
 
3
3
  export const devActionMetadataSchema = t.object({
4
- name: t.text(),
5
- group: t.text(),
6
- method: t.text(),
7
- path: t.text(),
8
- prefix: t.text(),
9
- fullPath: t.text(),
10
- description: t.optional(t.text()),
11
- summary: t.optional(t.text()),
12
- disabled: t.optional(t.boolean()),
13
- secure: t.optional(t.boolean()),
14
- hide: t.optional(t.boolean()),
15
- body: t.optional(t.any()),
16
- params: t.optional(t.any()),
17
- query: t.optional(t.any()),
18
- response: t.optional(t.any()),
19
- bodyContentType: t.optional(t.text()),
4
+ name: t.text(),
5
+ group: t.text(),
6
+ method: t.text(),
7
+ path: t.text(),
8
+ prefix: t.text(),
9
+ fullPath: t.text(),
10
+ description: t.optional(t.text()),
11
+ summary: t.optional(t.text()),
12
+ disabled: t.optional(t.boolean()),
13
+ secure: t.optional(t.boolean()),
14
+ hide: t.optional(t.boolean()),
15
+ body: t.optional(t.any()),
16
+ params: t.optional(t.any()),
17
+ query: t.optional(t.any()),
18
+ response: t.optional(t.any()),
19
+ bodyContentType: t.optional(t.text()),
20
20
  });
21
21
 
22
22
  export type DevActionMetadata = Static<typeof devActionMetadataSchema>;
@@ -1,11 +1,11 @@
1
1
  import { type Static, t } from "@alepha/core";
2
2
 
3
3
  export const devBucketMetadataSchema = t.object({
4
- name: t.text(),
5
- description: t.optional(t.text()),
6
- mimeTypes: t.optional(t.array(t.text())),
7
- maxSize: t.optional(t.number()),
8
- provider: t.text(),
4
+ name: t.text(),
5
+ description: t.optional(t.text()),
6
+ mimeTypes: t.optional(t.array(t.text())),
7
+ maxSize: t.optional(t.number()),
8
+ provider: t.text(),
9
9
  });
10
10
 
11
11
  export type DevBucketMetadata = Static<typeof devBucketMetadataSchema>;
@@ -1,10 +1,10 @@
1
1
  import { type Static, t } from "@alepha/core";
2
2
 
3
3
  export const devCacheMetadataSchema = t.object({
4
- name: t.text(),
5
- ttl: t.optional(t.any()),
6
- disabled: t.optional(t.boolean()),
7
- provider: t.text(),
4
+ name: t.text(),
5
+ ttl: t.optional(t.any()),
6
+ disabled: t.optional(t.boolean()),
7
+ provider: t.text(),
8
8
  });
9
9
 
10
10
  export type DevCacheMetadata = Static<typeof devCacheMetadataSchema>;
@@ -2,10 +2,10 @@ import { type Static, t } from "@alepha/core";
2
2
  import type { LogEntry } from "@alepha/logger";
3
3
 
4
4
  export const devLogEntrySchema = t.object({
5
- formatted: t.text(),
6
- entry: t.any(), // Use any since LogEntry has Date instead of string for timestamp
5
+ formatted: t.text(),
6
+ entry: t.any(), // Use any since LogEntry has Date instead of string for timestamp
7
7
  });
8
8
 
9
9
  export type DevLogEntry = Static<typeof devLogEntrySchema> & {
10
- entry: LogEntry;
10
+ entry: LogEntry;
11
11
  };
@@ -11,17 +11,17 @@ import { devSchedulerMetadataSchema } from "./DevSchedulerMetadata.ts";
11
11
  import { devTopicMetadataSchema } from "./DevTopicMetadata.ts";
12
12
 
13
13
  export const devMetadataSchema = t.object({
14
- actions: t.array(devActionMetadataSchema),
15
- queues: t.array(devQueueMetadataSchema),
16
- schedulers: t.array(devSchedulerMetadataSchema),
17
- topics: t.array(devTopicMetadataSchema),
18
- buckets: t.array(devBucketMetadataSchema),
19
- realms: t.array(devRealmMetadataSchema),
20
- caches: t.array(devCacheMetadataSchema),
21
- pages: t.array(devPageMetadataSchema),
22
- providers: t.array(devProviderMetadataSchema),
23
- modules: t.array(devModuleMetadataSchema),
24
- // More metadata will be added here later
14
+ actions: t.array(devActionMetadataSchema),
15
+ queues: t.array(devQueueMetadataSchema),
16
+ schedulers: t.array(devSchedulerMetadataSchema),
17
+ topics: t.array(devTopicMetadataSchema),
18
+ buckets: t.array(devBucketMetadataSchema),
19
+ realms: t.array(devRealmMetadataSchema),
20
+ caches: t.array(devCacheMetadataSchema),
21
+ pages: t.array(devPageMetadataSchema),
22
+ providers: t.array(devProviderMetadataSchema),
23
+ modules: t.array(devModuleMetadataSchema),
24
+ // More metadata will be added here later
25
25
  });
26
26
 
27
27
  export type DevMetadata = Static<typeof devMetadataSchema>;
@@ -1,8 +1,8 @@
1
1
  import { type Static, t } from "@alepha/core";
2
2
 
3
3
  export const devModuleMetadataSchema = t.object({
4
- name: t.text(),
5
- providers: t.array(t.text()),
4
+ name: t.text(),
5
+ providers: t.array(t.text()),
6
6
  });
7
7
 
8
8
  export type DevModuleMetadata = Static<typeof devModuleMetadataSchema>;