diff --git a/scopes/harmony/diagnostic/diagnostic.graphql.ts b/scopes/harmony/diagnostic/diagnostic.graphql.ts index 89287b3290d1..f9ae6b56fe13 100644 --- a/scopes/harmony/diagnostic/diagnostic.graphql.ts +++ b/scopes/harmony/diagnostic/diagnostic.graphql.ts @@ -15,7 +15,8 @@ export class DiagnosticGraphql implements Schema { resolvers = { Query: { _diagnostic: () => { - return this.diagnosticMain.getDiagnosticData(); + // return this.diagnosticMain.getDiagnosticData(); + return {}; }, }, }; diff --git a/scopes/harmony/diagnostic/diagnostic.main.runtime.ts b/scopes/harmony/diagnostic/diagnostic.main.runtime.ts index 8f19748be2b8..763157b75486 100644 --- a/scopes/harmony/diagnostic/diagnostic.main.runtime.ts +++ b/scopes/harmony/diagnostic/diagnostic.main.runtime.ts @@ -1,4 +1,5 @@ import { getBitVersion } from '@teambit/bit.get-bit-version'; +import os from 'os'; import type { SlotRegistry } from '@teambit/harmony'; import { Slot } from '@teambit/harmony'; @@ -45,13 +46,46 @@ export class DiagnosticMain { return { version }; } + static getProcessInfo() { + const memUsage = process.memoryUsage(); + const cpuUsage = process.cpuUsage(); + return { + uptime: process.uptime(), + pid: process.pid, + nodeVersion: process.version, + platform: process.platform, + arch: process.arch, + memory: { + rss: memUsage.rss, + heapTotal: memUsage.heapTotal, + heapUsed: memUsage.heapUsed, + external: memUsage.external, + arrayBuffers: memUsage.arrayBuffers, + }, + cpu: { + user: cpuUsage.user, + system: cpuUsage.system, + }, + system: { + totalMemory: os.totalmem(), + freeMemory: os.freemem(), + cpuCount: os.cpus().length, + loadAverage: os.loadavg(), + hostname: os.hostname(), + }, + }; + } + static async provider( [express, graphql]: [ExpressMain, GraphqlMain], config: any, [diagnosticSlot]: [DiagnosticSlot] ) { const diagnosticMain = new DiagnosticMain(diagnosticSlot); - diagnosticMain.register({ diagnosticFn: DiagnosticMain.getBitVersion }); + diagnosticMain.register( + { diagnosticFn: DiagnosticMain.getBitVersion }, + { diagnosticFn: DiagnosticMain.getProcessInfo } + ); express.register([new DiagnosticRoute(diagnosticMain)]); graphql.register(() => new DiagnosticGraphql(diagnosticMain)); return diagnosticMain; diff --git a/scopes/harmony/diagnostic/diagnostic.route.ts b/scopes/harmony/diagnostic/diagnostic.route.ts index 3d5ca3cb083d..f707f180c7ed 100644 --- a/scopes/harmony/diagnostic/diagnostic.route.ts +++ b/scopes/harmony/diagnostic/diagnostic.route.ts @@ -1,4 +1,4 @@ -import type { Route, Request, Response } from '@teambit/express'; +import type { Route, Request, Response, Middleware } from '@teambit/express'; import { Verb } from '@teambit/express'; import type { DiagnosticMain } from './diagnostic.main.runtime'; @@ -7,12 +7,12 @@ export class DiagnosticRoute implements Route { method = 'GET'; route = '/_diagnostic'; - verb = Verb.READ; + verb = Verb.WRITE; - middlewares = [ + middlewares: Middleware[] = [ async (req: Request, res: Response) => { const diagnosticData = this.diagnosticMain.getDiagnosticData(); - res.json(diagnosticData); + return res.json(diagnosticData); }, ]; } diff --git a/scopes/harmony/diagnostic/diagnostic.spec.ts b/scopes/harmony/diagnostic/diagnostic.spec.ts new file mode 100644 index 000000000000..1949b251e546 --- /dev/null +++ b/scopes/harmony/diagnostic/diagnostic.spec.ts @@ -0,0 +1,76 @@ +import os from 'os'; +import { expect } from 'chai'; +import { DiagnosticMain } from './diagnostic.main.runtime'; + +describe('DiagnosticMain', () => { + describe('getBitVersion', () => { + it('should return an object with a version string', () => { + const result = DiagnosticMain.getBitVersion(); + expect(result).to.have.property('version'); + expect(result.version).to.be.a('string'); + }); + }); + + describe('getProcessInfo', () => { + it('should return process uptime as a positive number', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.uptime).to.be.a('number'); + expect(result.uptime).to.be.greaterThan(0); + }); + + it('should return the current process pid', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.pid).to.equal(process.pid); + }); + + it('should return node version, platform, and arch', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.nodeVersion).to.equal(process.version); + expect(result.platform).to.equal(process.platform); + expect(result.arch).to.equal(process.arch); + }); + + it('should return memory usage with all expected fields', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.memory).to.have.property('rss').that.is.a('number'); + expect(result.memory).to.have.property('heapTotal').that.is.a('number'); + expect(result.memory).to.have.property('heapUsed').that.is.a('number'); + expect(result.memory).to.have.property('external').that.is.a('number'); + expect(result.memory).to.have.property('arrayBuffers').that.is.a('number'); + }); + + it('should return memory values that are positive', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.memory.rss).to.be.greaterThan(0); + expect(result.memory.heapTotal).to.be.greaterThan(0); + expect(result.memory.heapUsed).to.be.greaterThan(0); + }); + + it('should return cpu usage with user and system fields', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.cpu).to.have.property('user').that.is.a('number'); + expect(result.cpu).to.have.property('system').that.is.a('number'); + }); + + it('should return system info matching os module values', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.system.totalMemory).to.equal(os.totalmem()); + expect(result.system.cpuCount).to.equal(os.cpus().length); + expect(result.system.hostname).to.equal(os.hostname()); + }); + + it('should return load average as an array of 3 numbers', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.system.loadAverage).to.be.an('array').with.lengthOf(3); + result.system.loadAverage.forEach((val) => { + expect(val).to.be.a('number'); + }); + }); + + it('should return free memory less than or equal to total memory', () => { + const result = DiagnosticMain.getProcessInfo(); + expect(result.system.freeMemory).to.be.at.most(result.system.totalMemory); + expect(result.system.freeMemory).to.be.greaterThan(0); + }); + }); +}); diff --git a/scopes/harmony/express/index.ts b/scopes/harmony/express/index.ts index 5befacd8dff4..6c71b42590e3 100644 --- a/scopes/harmony/express/index.ts +++ b/scopes/harmony/express/index.ts @@ -1,7 +1,6 @@ export type { RouteSlot } from './express.main.runtime'; -export type { Route } from './types'; export { Verb } from './types'; -export type { Request, Response, NextFunction, Middleware } from './types'; +export type { Route, Request, Response, NextFunction, Middleware } from './types'; export type { MiddlewareManifest } from './middleware-manifest'; export type { ExpressMain } from './express.main.runtime'; export { ExpressAspect } from './express.aspect'; diff --git a/scopes/harmony/express/types/index.ts b/scopes/harmony/express/types/index.ts index c84bc3bf4a52..2be80c95bdb1 100644 --- a/scopes/harmony/express/types/index.ts +++ b/scopes/harmony/express/types/index.ts @@ -1,4 +1,5 @@ -export { Request } from './request'; -export { Response } from './response'; -export { NextFunction } from './next'; -export { Route, Middleware, Verb } from './route'; +export type { Request } from './request'; +export type { Response } from './response'; +export type { NextFunction } from './next'; +export type { Route, Middleware } from './route'; +export { Verb } from './route'; diff --git a/scopes/harmony/graphql/index.ts b/scopes/harmony/graphql/index.ts index 9ec851d8dcbb..67cbb5542eba 100644 --- a/scopes/harmony/graphql/index.ts +++ b/scopes/harmony/graphql/index.ts @@ -1,6 +1,6 @@ export { GraphqlAspect, GraphqlAspect as default } from './graphql.aspect'; -export type { Schema } from './schema'; +export type { Schema, DocumentNode, SchemaDirectives } from './schema'; export type { GraphqlMain, SchemaSlot } from './graphql.main.runtime'; export type { GraphqlUI, GraphQLClient } from './graphql.ui.runtime'; export type { GraphQLServer } from './graphql-server'; diff --git a/scopes/harmony/graphql/schema.ts b/scopes/harmony/graphql/schema.ts index cc24b672ef31..9713bdc261e9 100644 --- a/scopes/harmony/graphql/schema.ts +++ b/scopes/harmony/graphql/schema.ts @@ -1,6 +1,9 @@ import type { DocumentNode } from 'graphql'; import type { SchemaDirectives } from '@graphql-modules/core'; +export type { DocumentNode } from 'graphql'; +export type { SchemaDirectives } from '@graphql-modules/core'; + /** * graphql schema for an extension. */