@alepha/devtools 0.11.5 → 0.11.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/schemas/DevActionMetadata.ts","../src/schemas/DevBucketMetadata.ts","../src/schemas/DevCacheMetadata.ts","../src/schemas/DevMetadata.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/DevCollectorProvider.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;cAEa,oCAAuB;QAiBlC,UAAA,CAAA;;;;;;;;;EAjBW,MAAA,sBAiBX,qBAAA;EAAA,IAAA,sBAAA,qBAAA;;;;;;;KAEU,iBAAA,GAAoB,cAAc;;;cCnBjC,oCAAuB;QAMlC,UAAA,CAAA;;;;;;KAEU,iBAAA,GAAoB,cAAc;;;cCRjC,mCAAsB;QAKjC,UAAA,CAAA;;;;;KAEU,gBAAA,GAAmB,cAAc;;;cCGhC,8BAAiB;;UAY5B,UAAA,CAAA;;;;;;;;IHtBW,QAAA,sBAiBX,qBAAA;IAAA,MAAA,sBAAA,qBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;EAjBkC,OAAA,mBAAA,mBAAA,CAAA;IAmBxB,IAAA,oBAAkC;;;;ICnBjC,QAAA,oBAMX;EAAA,CAAA,CAAA,CAAA;;;;;;;;;MANkC,kBAAA,qBAAA;MAAA,mBAAA,qBAAA;MAQxB,kBAAiB,qBAAiB;;;;ICRjC,IAAA,oBAKX;IAAA,GAAA,sBAAA,iBAAA;;;;;;eALiC,sBAAA,oBAAA;IAAA,IAAA,sBAAA,oBAAA;IAOvB,MAAA,sBAAiC,iBAAR;;;;ICGxB,UAAA,qBAYX;IAAA,WAAA,qBAAA;;;;;;;;;;;;;;;;;;;KAEU,WAAA,GAAc,cAAc;;;cCxB3B,oCAAuB;QAGlC,UAAA,CAAA;;;KAEU,iBAAA,GAAoB,cAAc;;;cCLjC,kCAAqB;QAgBhC,UAAA,CAAA;;;;;;;;;ELhBW,SAAA,qBAiBX;EAAA,eAAA,qBAAA;;;;;;KKCU,eAAA,GAAkB,cAAc;;;cClB/B,sCAAyB;QAKpC,UAAA,CAAA;;;;;KAEU,mBAAA,GAAsB,cAAc;;;cCPnC,mCAAsB;QAKjC,UAAA,CAAA;;;;;KAEU,gBAAA,GAAmB,cAAc;;;cCPhC,mCAAsB;QAcjC,UAAA,CAAA;;;;;;;;;IRdW,kBAAA,qBAiBX;EAAA,CAAA,CAAA,CAAA;;KQDU,gBAAA,GAAmB,cAAc;;;cChBhC,uCAA0B;QAMrC,UAAA,CAAA;;;;;;KAEU,oBAAA,GAAuB,cAAc;;;cCRpC,mCAAsB;QAKjC,UAAA,CAAA;;;;;KAEU,gBAAA,GAAmB,cAAc;;;cCgBhC,oBAAA;6BACc;qCACQ;0BAAA,eAAA,CACX;2BACG;;8BAAQ,aAAA,CAGP;4BAAA,aAAA,CASF;8BAAA,sBAAA,CAYE;oDAKM;;;cALN,UAAA,CAAA;;;;;;;;;;;;QXnDQ,MAAA,sBAAA,iBAAA;QAAA,KAAA,sBAAA,iBAAA;QAmBxB,QAAiB,sBAAiB,iBAAR;;;;QCnBzB,IAAA,oBAMX;QAAA,WAAA,sBAAA,oBAAA;;;;;;;;;QANkC,IAAA,sBAAA,qBAAA;MAAA,CAAA,CAAA,CAAA;MAQxB,MAAA,mBAAkC,mBAAR,CAAA;;;;QCRzB,QAAA,oBAKX;MAAA,CAAA,CAAA,CAAA;;;;;;QALiC,QAAA,oBAAA;MAAA,CAAA,CAAA,CAAA;MAOvB,MAAA,mBAAiC,mBAAR,CAAA;;;;QCGxB,IAAA,oBAYX,CAAA,UAAA,GAAA,UAAA,CAAA;QAAA,QAAA,sBAAA,mBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDQ8C4B;;aAZI,UAAA,CAAA;;;;;;;;;;aAwBd;gBAMG;eA4BD;mBAWI;eAYJ;gBAWC;eAYD;eAmBA;cAWD;kBAyBI;gBAWF;iBAoBC;;;;;;;;;;;;;;cC3NX,gBAAc,aAAA,CAAA,QAQzB,aAAA,CARyB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/schemas/DevActionMetadata.ts","../src/schemas/DevBucketMetadata.ts","../src/schemas/DevCacheMetadata.ts","../src/schemas/DevMetadata.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/DevCollectorProvider.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
- import { $hook, $inject, $module, Alepha, t } from "@alepha/core";
1
+ import { $hook, $inject, $module, Alepha, pageQuerySchema, t } from "@alepha/core";
2
2
  import { join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
+ import { $batch } from "@alepha/batch";
4
5
  import { $bucket } from "@alepha/bucket";
5
6
  import { $cache } from "@alepha/cache";
6
7
  import { $logger, logEntrySchema } from "@alepha/logger";
8
+ import { $entity, NodeSqliteProvider, parseQueryString, pg } from "@alepha/postgres";
9
+ import { Repository } from "@alepha/postgres/src/services/Repository.ts";
7
10
  import { $queue } from "@alepha/queue";
8
- import { $page } from "@alepha/react";
9
11
  import { $scheduler } from "@alepha/scheduler";
10
12
  import { $realm } from "@alepha/security";
11
13
  import { $action, $route, ServerProvider } from "@alepha/server";
@@ -148,28 +150,70 @@ const devMetadataSchema = t.object({
148
150
 
149
151
  //#endregion
150
152
  //#region src/DevCollectorProvider.ts
153
+ var DevToolsDatabaseProvider = class extends NodeSqliteProvider {
154
+ get name() {
155
+ return "devtools";
156
+ }
157
+ options = { path: ":memory:" };
158
+ };
159
+ const logs = $entity({
160
+ name: "logs",
161
+ schema: t.object({
162
+ id: pg.primaryKey(),
163
+ level: t.enum([
164
+ "SILENT",
165
+ "TRACE",
166
+ "DEBUG",
167
+ "INFO",
168
+ "WARN",
169
+ "ERROR"
170
+ ]),
171
+ message: t.text({ size: "rich" }),
172
+ service: t.text(),
173
+ module: t.text(),
174
+ context: t.optional(t.text()),
175
+ app: t.optional(t.text()),
176
+ data: t.optional(t.json()),
177
+ timestamp: t.datetime()
178
+ })
179
+ });
180
+ var LogRepository = class extends Repository {
181
+ constructor() {
182
+ super(logs, DevToolsDatabaseProvider);
183
+ }
184
+ };
151
185
  var DevCollectorProvider = class {
152
186
  alepha = $inject(Alepha);
153
187
  serverProvider = $inject(ServerProvider);
188
+ sqliteProvider = $inject(DevToolsDatabaseProvider);
154
189
  log = $logger();
155
- logs = [];
156
- maxLogs = 1e4;
190
+ logs = $inject(LogRepository);
157
191
  onStart = $hook({
158
192
  on: "start",
159
193
  handler: () => {
160
194
  this.log.info(`Devtools available at ${this.serverProvider.hostname}/devtools/`);
161
195
  }
162
196
  });
197
+ batchLogs = $batch({
198
+ maxSize: 50,
199
+ maxDuration: [10, "seconds"],
200
+ schema: logEntrySchema,
201
+ handler: async (entries) => {
202
+ await this.logs.createMany(entries);
203
+ }
204
+ });
163
205
  onLog = $hook({
164
206
  on: "log",
165
- handler: (ev) => {
166
- this.logs.unshift(ev.entry);
167
- if (this.logs.length > this.maxLogs) this.logs.pop();
207
+ handler: async (ev) => {
208
+ if (!this.alepha.isReady()) return;
209
+ if (ev.entry.level === "TRACE" && ev.entry.module === "alepha.batch") return;
210
+ await this.batchLogs.push(ev.entry);
168
211
  }
169
212
  });
170
213
  uiRoute = $serve({
171
214
  path: "/devtools",
172
- root: join(fileURLToPath(import.meta.url), "../../assets/devtools")
215
+ root: join(fileURLToPath(import.meta.url), "../../assets/devtools"),
216
+ historyApiFallback: true
173
217
  });
174
218
  metadataRoute = $route({
175
219
  method: "GET",
@@ -184,14 +228,16 @@ var DevCollectorProvider = class {
184
228
  method: "GET",
185
229
  path: "/devtools/api/logs",
186
230
  silent: true,
187
- schema: { response: t.array(logEntrySchema) },
188
- handler: () => {
189
- return this.getLogs();
231
+ schema: {
232
+ query: t.interface([pageQuerySchema], { search: t.optional(t.string()) }),
233
+ response: t.page(logEntrySchema)
234
+ },
235
+ handler: ({ query }) => {
236
+ query.sort ??= "-timestamp";
237
+ if (query.search) console.log(parseQueryString(query.search));
238
+ return this.logs.paginate(query, query.search ? { where: parseQueryString(query.search) } : {}, { count: true });
190
239
  }
191
240
  });
192
- getLogs() {
193
- return this.logs;
194
- }
195
241
  getActions() {
196
242
  return this.alepha.descriptors($action).map((action) => {
197
243
  const schema = action.schema;
@@ -274,23 +320,7 @@ var DevCollectorProvider = class {
274
320
  }));
275
321
  }
276
322
  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
- }));
323
+ return [];
294
324
  }
295
325
  getProviders() {
296
326
  const graph = this.alepha.graph();
@@ -351,7 +381,7 @@ const AlephaDevtools = $module({
351
381
  services: [DevCollectorProvider],
352
382
  register: (alepha) => {
353
383
  alepha.with(DevCollectorProvider);
354
- alepha.state.push("assets", "@alepha/devtools");
384
+ alepha.state.push("alepha.build.assets", "@alepha/devtools");
355
385
  }
356
386
  });
357
387
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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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"}
1
+ {"version":3,"file":"index.js","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 { $batch } from \"@alepha/batch\";\nimport { $bucket } from \"@alepha/bucket\";\nimport { $cache } from \"@alepha/cache\";\nimport { $hook, $inject, Alepha, pageQuerySchema, t } from \"@alepha/core\";\nimport { $logger, type LogEntry, logEntrySchema } from \"@alepha/logger\";\nimport {\n $entity,\n NodeSqliteProvider,\n parseQueryString,\n pg,\n} from \"@alepha/postgres\";\nimport { Repository } from \"@alepha/postgres/src/services/Repository.ts\";\nimport { $queue } from \"@alepha/queue\";\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\nclass DevToolsDatabaseProvider extends NodeSqliteProvider {\n get name() {\n return \"devtools\";\n }\n options = {\n path: \":memory:\",\n };\n}\n\nconst logs = $entity({\n name: \"logs\",\n schema: t.object({\n id: pg.primaryKey(),\n level: t.enum([\"SILENT\", \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\"]),\n message: t.text({\n size: \"rich\",\n }),\n service: t.text(),\n module: t.text(),\n context: t.optional(t.text()),\n app: t.optional(t.text()),\n data: t.optional(t.json()),\n timestamp: t.datetime(),\n }),\n});\n\nclass LogRepository extends Repository<typeof logs.schema> {\n constructor() {\n super(logs, DevToolsDatabaseProvider);\n }\n}\n\nexport class DevCollectorProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly serverProvider = $inject(ServerProvider);\n protected readonly sqliteProvider = $inject(DevToolsDatabaseProvider);\n protected readonly log = $logger();\n\n logs = $inject(LogRepository);\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 batchLogs = $batch({\n maxSize: 50,\n maxDuration: [10, \"seconds\"],\n schema: logEntrySchema,\n handler: async (entries: LogEntry[]) => {\n await this.logs.createMany(entries);\n },\n });\n\n protected readonly onLog = $hook({\n on: \"log\",\n handler: async (ev: { message?: string; entry: LogEntry }) => {\n if (!this.alepha.isReady()) {\n return;\n }\n\n if (ev.entry.level === \"TRACE\" && ev.entry.module === \"alepha.batch\") {\n // skip batch trace logs to avoid infinite loop\n return;\n }\n\n await this.batchLogs.push(ev.entry);\n },\n });\n\n protected readonly uiRoute = $serve({\n path: \"/devtools\",\n root: join(fileURLToPath(import.meta.url), \"../../assets/devtools\"),\n historyApiFallback: true,\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 query: t.interface([pageQuerySchema], {\n search: t.optional(t.string()),\n }),\n response: t.page(logEntrySchema),\n },\n handler: ({ query }) => {\n query.sort ??= \"-timestamp\";\n if (query.search) {\n console.log(parseQueryString(query.search));\n }\n return this.logs.paginate(\n query,\n query.search\n ? {\n where: parseQueryString(query.search),\n }\n : {},\n {\n count: true,\n },\n );\n },\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 return [];\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(\"alepha.build.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.5",
4
+ "version": "0.11.6",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=22.0.0"
@@ -14,29 +14,31 @@
14
14
  "src"
15
15
  ],
16
16
  "dependencies": {
17
- "@alepha/bucket": "0.11.5",
18
- "@alepha/cache": "0.11.5",
19
- "@alepha/core": "0.11.5",
20
- "@alepha/logger": "0.11.5",
21
- "@alepha/queue": "0.11.5",
22
- "@alepha/react": "0.11.5",
23
- "@alepha/react-i18n": "0.11.5",
24
- "@alepha/scheduler": "0.11.5",
25
- "@alepha/security": "0.11.5",
26
- "@alepha/server": "0.11.5",
27
- "@alepha/server-static": "0.11.5",
28
- "@alepha/topic": "0.11.5"
17
+ "@alepha/batch": "0.11.6",
18
+ "@alepha/bucket": "0.11.6",
19
+ "@alepha/cache": "0.11.6",
20
+ "@alepha/core": "0.11.6",
21
+ "@alepha/logger": "0.11.6",
22
+ "@alepha/postgres": "0.11.6",
23
+ "@alepha/queue": "0.11.6",
24
+ "@alepha/react": "0.11.6",
25
+ "@alepha/react-i18n": "0.11.6",
26
+ "@alepha/scheduler": "0.11.6",
27
+ "@alepha/security": "0.11.6",
28
+ "@alepha/server": "0.11.6",
29
+ "@alepha/server-static": "0.11.6",
30
+ "@alepha/topic": "0.11.6"
29
31
  },
30
32
  "devDependencies": {
31
- "@alepha/cli": "0.11.5",
32
- "@alepha/ui": "0.11.5",
33
- "@alepha/vite": "0.11.5",
34
- "@biomejs/biome": "^2.3.3",
33
+ "@alepha/cli": "0.11.6",
34
+ "@alepha/ui": "0.11.6",
35
+ "@alepha/vite": "0.11.6",
36
+ "@biomejs/biome": "^2.3.4",
35
37
  "@tabler/icons-react": "^3.35.0",
36
38
  "react": "^19.2.0",
37
- "tsdown": "^0.16.0",
39
+ "tsdown": "^0.16.1",
38
40
  "typescript": "^5.9.3",
39
- "vitest": "^4.0.6"
41
+ "vitest": "^4.0.8"
40
42
  },
41
43
  "scripts": {
42
44
  "test": "vitest run",
@@ -1,11 +1,18 @@
1
1
  import { join } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
+ import { $batch } from "@alepha/batch";
3
4
  import { $bucket } from "@alepha/bucket";
4
5
  import { $cache } from "@alepha/cache";
5
- import { $hook, $inject, Alepha, t } from "@alepha/core";
6
+ import { $hook, $inject, Alepha, pageQuerySchema, t } from "@alepha/core";
6
7
  import { $logger, type LogEntry, logEntrySchema } from "@alepha/logger";
8
+ import {
9
+ $entity,
10
+ NodeSqliteProvider,
11
+ parseQueryString,
12
+ pg,
13
+ } from "@alepha/postgres";
14
+ import { Repository } from "@alepha/postgres/src/services/Repository.ts";
7
15
  import { $queue } from "@alepha/queue";
8
- import { $page } from "@alepha/react";
9
16
  import { $scheduler } from "@alepha/scheduler";
10
17
  import { $realm } from "@alepha/security";
11
18
  import { $action, $route, ServerProvider } from "@alepha/server";
@@ -23,12 +30,45 @@ import type { DevRealmMetadata } from "./schemas/DevRealmMetadata.ts";
23
30
  import type { DevSchedulerMetadata } from "./schemas/DevSchedulerMetadata.ts";
24
31
  import type { DevTopicMetadata } from "./schemas/DevTopicMetadata.ts";
25
32
 
33
+ class DevToolsDatabaseProvider extends NodeSqliteProvider {
34
+ get name() {
35
+ return "devtools";
36
+ }
37
+ options = {
38
+ path: ":memory:",
39
+ };
40
+ }
41
+
42
+ const logs = $entity({
43
+ name: "logs",
44
+ schema: t.object({
45
+ id: pg.primaryKey(),
46
+ level: t.enum(["SILENT", "TRACE", "DEBUG", "INFO", "WARN", "ERROR"]),
47
+ message: t.text({
48
+ size: "rich",
49
+ }),
50
+ service: t.text(),
51
+ module: t.text(),
52
+ context: t.optional(t.text()),
53
+ app: t.optional(t.text()),
54
+ data: t.optional(t.json()),
55
+ timestamp: t.datetime(),
56
+ }),
57
+ });
58
+
59
+ class LogRepository extends Repository<typeof logs.schema> {
60
+ constructor() {
61
+ super(logs, DevToolsDatabaseProvider);
62
+ }
63
+ }
64
+
26
65
  export class DevCollectorProvider {
27
66
  protected readonly alepha = $inject(Alepha);
28
67
  protected readonly serverProvider = $inject(ServerProvider);
68
+ protected readonly sqliteProvider = $inject(DevToolsDatabaseProvider);
29
69
  protected readonly log = $logger();
30
- protected readonly logs: LogEntry[] = [];
31
- protected readonly maxLogs = 10000;
70
+
71
+ logs = $inject(LogRepository);
32
72
 
33
73
  protected readonly onStart = $hook({
34
74
  on: "start",
@@ -39,21 +79,35 @@ export class DevCollectorProvider {
39
79
  },
40
80
  });
41
81
 
82
+ protected batchLogs = $batch({
83
+ maxSize: 50,
84
+ maxDuration: [10, "seconds"],
85
+ schema: logEntrySchema,
86
+ handler: async (entries: LogEntry[]) => {
87
+ await this.logs.createMany(entries);
88
+ },
89
+ });
90
+
42
91
  protected readonly onLog = $hook({
43
92
  on: "log",
44
- handler: (ev: { message?: string; entry: LogEntry }) => {
45
- this.logs.unshift(ev.entry);
93
+ handler: async (ev: { message?: string; entry: LogEntry }) => {
94
+ if (!this.alepha.isReady()) {
95
+ return;
96
+ }
46
97
 
47
- // keep only the last 10000 logs
48
- if (this.logs.length > this.maxLogs) {
49
- this.logs.pop();
98
+ if (ev.entry.level === "TRACE" && ev.entry.module === "alepha.batch") {
99
+ // skip batch trace logs to avoid infinite loop
100
+ return;
50
101
  }
102
+
103
+ await this.batchLogs.push(ev.entry);
51
104
  },
52
105
  });
53
106
 
54
107
  protected readonly uiRoute = $serve({
55
108
  path: "/devtools",
56
109
  root: join(fileURLToPath(import.meta.url), "../../assets/devtools"),
110
+ historyApiFallback: true,
57
111
  });
58
112
 
59
113
  protected readonly metadataRoute = $route({
@@ -73,17 +127,30 @@ export class DevCollectorProvider {
73
127
  path: "/devtools/api/logs",
74
128
  silent: true,
75
129
  schema: {
76
- response: t.array(logEntrySchema),
130
+ query: t.interface([pageQuerySchema], {
131
+ search: t.optional(t.string()),
132
+ }),
133
+ response: t.page(logEntrySchema),
77
134
  },
78
- handler: () => {
79
- return this.getLogs();
135
+ handler: ({ query }) => {
136
+ query.sort ??= "-timestamp";
137
+ if (query.search) {
138
+ console.log(parseQueryString(query.search));
139
+ }
140
+ return this.logs.paginate(
141
+ query,
142
+ query.search
143
+ ? {
144
+ where: parseQueryString(query.search),
145
+ }
146
+ : {},
147
+ {
148
+ count: true,
149
+ },
150
+ );
80
151
  },
81
152
  });
82
153
 
83
- public getLogs(): LogEntry[] {
84
- return this.logs;
85
- }
86
-
87
154
  // -------------------------------------------------------------------------------------------------------------------
88
155
 
89
156
  public getActions(): DevActionMetadata[] {
@@ -191,28 +258,30 @@ export class DevCollectorProvider {
191
258
  }
192
259
 
193
260
  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
- }));
261
+ // const pageDescriptors = this.alepha.descriptors($page);
262
+ //
263
+ // return pageDescriptors.map((page) => ({
264
+ // name: page.name,
265
+ // description: page.options.description,
266
+ // path: page.options.path,
267
+ // params: page.options.schema?.params,
268
+ // query: page.options.schema?.query,
269
+ // hasComponent: !!page.options.component,
270
+ // hasLazy: !!page.options.lazy,
271
+ // hasResolve: !!page.options.resolve,
272
+ // hasChildren: !!page.options.children,
273
+ // hasParent: !!page.options.parent,
274
+ // hasErrorHandler: !!page.options.errorHandler,
275
+ // static:
276
+ // typeof page.options.static === "boolean"
277
+ // ? page.options.static
278
+ // : !!page.options.static,
279
+ // cache: page.options.cache,
280
+ // client: page.options.client,
281
+ // animation: page.options.animation,
282
+ // }));
283
+
284
+ return [];
216
285
  }
217
286
 
218
287
  public getProviders(): DevProviderMetadata[] {
package/src/index.ts CHANGED
@@ -33,6 +33,6 @@ export const AlephaDevtools = $module({
33
33
  services: [DevCollectorProvider],
34
34
  register: (alepha) => {
35
35
  alepha.with(DevCollectorProvider);
36
- alepha.state.push("assets", "@alepha/devtools");
36
+ alepha.state.push("alepha.build.assets", "@alepha/devtools");
37
37
  },
38
38
  });
@@ -1,5 +1,13 @@
1
1
  import { $page } from "@alepha/react";
2
- import { AdminShell, RootRouter, Text, ui } from "@alepha/ui";
2
+ import {
3
+ AdminShell,
4
+ DarkModeButton,
5
+ OmnibarButton,
6
+ RootRouter,
7
+ Text,
8
+ ui,
9
+ } from "@alepha/ui";
10
+ import ToggleSidebarButton from "@alepha/ui/src/components/buttons/ToggleSidebarButton.tsx";
3
11
  import { IconDashboard, IconLogs } from "@tabler/icons-react";
4
12
  import DevLogs from "./DevLogs.tsx";
5
13
 
@@ -21,20 +29,42 @@ export class AppRouter extends RootRouter {
21
29
  },
22
30
  }}
23
31
  sidebarProps={{
24
- collapsed: true,
25
32
  gap: "xs",
33
+ menu: [
34
+ {
35
+ element: <ToggleSidebarButton />,
36
+ },
37
+ {
38
+ label: "Dashboard",
39
+ icon: <IconDashboard />,
40
+ href: "/",
41
+ },
42
+ {
43
+ label: "Logs",
44
+ icon: <IconLogs />,
45
+ href: "/logs",
46
+ },
47
+ ],
26
48
  }}
27
49
  appBarProps={{
28
50
  items: [
29
51
  { position: "left", type: "burger" },
30
52
  {
31
- position: "center",
53
+ position: "left",
32
54
  element: (
33
55
  <Text fw="bold" size="lg">
34
56
  Alepha DevTools
35
57
  </Text>
36
58
  ),
37
59
  },
60
+ {
61
+ position: "center",
62
+ element: <OmnibarButton />,
63
+ },
64
+ {
65
+ position: "right",
66
+ element: <DarkModeButton />,
67
+ },
38
68
  ],
39
69
  }}
40
70
  />