@angelitosystems/nest-devtools 1.0.6 → 1.0.7

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.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { DevToolsUserConfig } from '@angelitosystems/devtools-core';
2
- export { DevToolsUserConfig, RequestContext, requestContext } from '@angelitosystems/devtools-core';
1
+ import { DevToolsConfig, DevToolsUserConfig, ProfileKind, ProfileResult } from '@angelitosystems/devtools-core';
2
+ export { DevToolsUserConfig, ProfileKind, ProfileResult, RequestContext, requestContext } from '@angelitosystems/devtools-core';
3
3
  import { INestApplication } from '@nestjs/common';
4
+ import { ProjectInfo, Redactor, DevToolsEventName, DevToolsEventMap } from '@angelitosystems/devtools-protocol';
4
5
 
5
6
  /** Public helper: report an error manually from anywhere in the app. */
6
7
  declare function captureError(error: unknown, options?: {
@@ -9,6 +10,30 @@ declare function captureError(error: unknown, options?: {
9
10
  service?: string;
10
11
  }): void;
11
12
 
13
+ interface PluginContext {
14
+ readonly config: DevToolsConfig;
15
+ readonly project: ProjectInfo;
16
+ readonly redactor: Redactor;
17
+ emit<K extends DevToolsEventName>(event: K, payload: DevToolsEventMap[K]): void;
18
+ custom(name: string, data?: unknown): void;
19
+ }
20
+ interface DevToolsPlugin {
21
+ readonly name: string;
22
+ onInit?(context: PluginContext): void | Promise<void>;
23
+ onAttach?(app: INestApplication, context: PluginContext): void | (() => void) | Promise<void | (() => void)>;
24
+ onDispose?(): void | Promise<void>;
25
+ }
26
+ /** Runs third-party instrumentation without allowing it to affect the app. */
27
+ declare class PluginManager {
28
+ private readonly plugins;
29
+ private readonly cleanups;
30
+ private readonly initialized;
31
+ constructor(plugins: DevToolsPlugin[]);
32
+ attach(app: INestApplication, config: DevToolsConfig, project: ProjectInfo): () => void;
33
+ private run;
34
+ private reportFailure;
35
+ }
36
+
12
37
  /** Result of calling NestDevTools.init(). */
13
38
  interface InitResult {
14
39
  /** True when instrumentation is live. */
@@ -19,6 +44,9 @@ interface InitResult {
19
44
  projectName: string;
20
45
  server: string;
21
46
  }
47
+ type NestDevToolsOptions = DevToolsUserConfig & {
48
+ plugins?: DevToolsPlugin[];
49
+ };
22
50
  /**
23
51
  * Main entry point: `NestDevTools.init(app, config?)`.
24
52
  *
@@ -29,17 +57,26 @@ declare class NestDevTools {
29
57
  private static readonly cleanups;
30
58
  private static initialized;
31
59
  /** Initialize DevTools for a NestJS application. One active instance per process. */
32
- static init(app: INestApplication, userConfig?: DevToolsUserConfig): InitResult;
60
+ static init(app: INestApplication, userConfig?: NestDevToolsOptions): InitResult;
33
61
  /** Teardown everything (mostly useful in tests). */
34
62
  static destroy(): void;
35
63
  /** Whether the SDK is currently active in this process. */
36
64
  static isActive(): boolean;
65
+ /** Start an explicit CPU or heap profile. */
66
+ static startProfile(kind: ProfileKind): Promise<{
67
+ profileId: string;
68
+ startedAt: number;
69
+ }>;
70
+ /** Stop the active profile and return its captured result. */
71
+ static stopProfile(): Promise<ProfileResult>;
37
72
  }
38
73
  /** Convenience functional alias: devtools.init(app). */
39
74
  declare const devtools: {
40
75
  init: typeof NestDevTools.init;
41
76
  destroy: typeof NestDevTools.destroy;
42
77
  isActive: typeof NestDevTools.isActive;
78
+ startProfile: typeof NestDevTools.startProfile;
79
+ stopProfile: typeof NestDevTools.stopProfile;
43
80
  };
44
81
 
45
- export { type InitResult, NestDevTools, captureError, devtools };
82
+ export { type DevToolsPlugin, type InitResult, NestDevTools, type NestDevToolsOptions, type PluginContext, PluginManager, captureError, devtools };
package/dist/index.js CHANGED
@@ -1353,6 +1353,84 @@ function printConnectionStatus(state, dashboard) {
1353
1353
  writeOriginalConsole("log", ` ${paint(DIM, "Reintentando en segundo plano \u2014 se conectar\xE1 solo cuando el dashboard est\xE9 arriba.")}`);
1354
1354
  }
1355
1355
 
1356
+ // src/plugins.ts
1357
+ import { Redactor as Redactor7 } from "@angelitosystems/devtools-protocol";
1358
+ var PluginManager = class {
1359
+ constructor(plugins) {
1360
+ this.plugins = plugins;
1361
+ }
1362
+ plugins;
1363
+ cleanups = [];
1364
+ initialized = [];
1365
+ attach(app, config, project) {
1366
+ const redactor = new Redactor7({ redact: config.redact, allow: config.allow, maxBytes: config.maxPayloadBytes });
1367
+ const context = {
1368
+ config,
1369
+ project,
1370
+ redactor,
1371
+ emit: (event, payload) => {
1372
+ try {
1373
+ emit(event, redactor.redact(payload));
1374
+ } catch {
1375
+ }
1376
+ },
1377
+ custom: (name, data) => {
1378
+ try {
1379
+ emit("plugin.event", {
1380
+ projectId: project.projectId,
1381
+ plugin: "custom",
1382
+ name,
1383
+ data: redactor.redact(data),
1384
+ timestamp: Date.now()
1385
+ });
1386
+ } catch {
1387
+ }
1388
+ }
1389
+ };
1390
+ for (const plugin of this.plugins) {
1391
+ if (!plugin || !plugin.name) continue;
1392
+ this.initialized.push(plugin);
1393
+ this.run(plugin.name, () => plugin.onInit?.(context));
1394
+ this.run(plugin.name, async () => {
1395
+ const cleanup = await plugin.onAttach?.(app, context);
1396
+ if (typeof cleanup === "function") this.cleanups.push(cleanup);
1397
+ });
1398
+ }
1399
+ return () => {
1400
+ for (const cleanup of this.cleanups.splice(0)) {
1401
+ try {
1402
+ cleanup();
1403
+ } catch {
1404
+ }
1405
+ }
1406
+ for (const plugin of this.initialized.splice(0)) this.run(plugin.name, () => plugin.onDispose?.());
1407
+ };
1408
+ }
1409
+ run(name, operation) {
1410
+ try {
1411
+ const result = operation();
1412
+ if (result && typeof result.then === "function") {
1413
+ void result.catch((error) => this.reportFailure(name, error));
1414
+ }
1415
+ } catch (error) {
1416
+ this.reportFailure(name, error);
1417
+ }
1418
+ }
1419
+ reportFailure(name, error) {
1420
+ try {
1421
+ emit("log.created", {
1422
+ projectId: "plugin-system",
1423
+ level: "error",
1424
+ message: `DevTools plugin ${name} failed: ${error instanceof Error ? error.message : String(error)}`,
1425
+ processId: process.pid,
1426
+ timestamp: Date.now(),
1427
+ context: "plugin"
1428
+ });
1429
+ } catch {
1430
+ }
1431
+ }
1432
+ };
1433
+
1356
1434
  // src/sdk.ts
1357
1435
  var NestDevTools = class {
1358
1436
  static cleanups = [];
@@ -1398,6 +1476,9 @@ var NestDevTools = class {
1398
1476
  }
1399
1477
  }
1400
1478
  });
1479
+ if (userConfig?.plugins && userConfig.plugins.length > 0) {
1480
+ registerCleanup(new PluginManager(userConfig.plugins).attach(app, config, projectInfo));
1481
+ }
1401
1482
  const adapter = app.getHttpAdapter();
1402
1483
  const httpReady = Boolean(adapter && ["http", "express"].includes(adapter.getType()));
1403
1484
  const http = new HttpInstrumentation({ config, projectInfo });
@@ -1442,11 +1523,21 @@ var NestDevTools = class {
1442
1523
  static isActive() {
1443
1524
  return this.initialized;
1444
1525
  }
1526
+ /** Start an explicit CPU or heap profile. */
1527
+ static startProfile(kind) {
1528
+ return coreDevtools2.startProfile(kind);
1529
+ }
1530
+ /** Stop the active profile and return its captured result. */
1531
+ static stopProfile() {
1532
+ return coreDevtools2.stopProfile();
1533
+ }
1445
1534
  };
1446
1535
  var devtools = {
1447
1536
  init: NestDevTools.init.bind(NestDevTools),
1448
1537
  destroy: NestDevTools.destroy.bind(NestDevTools),
1449
- isActive: NestDevTools.isActive.bind(NestDevTools)
1538
+ isActive: NestDevTools.isActive.bind(NestDevTools),
1539
+ startProfile: NestDevTools.startProfile.bind(NestDevTools),
1540
+ stopProfile: NestDevTools.stopProfile.bind(NestDevTools)
1450
1541
  };
1451
1542
  function safeHostname() {
1452
1543
  try {
@@ -1484,6 +1575,7 @@ function dashboardUrl(server) {
1484
1575
  import { requestContext as requestContext8 } from "@angelitosystems/devtools-core";
1485
1576
  export {
1486
1577
  NestDevTools,
1578
+ PluginManager,
1487
1579
  captureError,
1488
1580
  devtools,
1489
1581
  requestContext8 as requestContext