Skip to content

Commit 8ddf7ad

Browse files
committed
feat(api): restructure versioning information in GraphQL schema
- Introduced new CoreVersions and PackageVersions types to encapsulate core system and software package version details. - Updated InfoVersions type to include references to CoreVersions and PackageVersions. - Modified the versions resolver to return structured version information. - Added a new query for fetching version information in the frontend. - Updated the HeaderOsVersion component to display the new version information. - Created a ReleaseNotesModal component for viewing OS release notes.
1 parent 26aeca3 commit 8ddf7ad

File tree

17 files changed

+424
-103
lines changed

17 files changed

+424
-103
lines changed

api/dev/configs/api.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "4.13.1",
2+
"version": "4.14.0",
33
"extraOrigins": [],
44
"sandbox": true,
55
"ssoSubIds": [],

api/generated-schema.graphql

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,12 +1501,18 @@ type InfoBaseboard implements Node {
15011501
memSlots: Float
15021502
}
15031503

1504-
type InfoVersions implements Node {
1505-
id: PrefixedID!
1504+
type CoreVersions {
1505+
"""Unraid version"""
1506+
unraid: String
1507+
1508+
"""Unraid API version"""
1509+
api: String
15061510

15071511
"""Kernel version"""
15081512
kernel: String
1513+
}
15091514

1515+
type PackageVersions {
15101516
"""OpenSSL version"""
15111517
openssl: String
15121518

@@ -1590,9 +1596,16 @@ type InfoVersions implements Node {
15901596

15911597
"""Docker version"""
15921598
docker: String
1599+
}
15931600

1594-
"""Unraid version"""
1595-
unraid: String
1601+
type InfoVersions implements Node {
1602+
id: PrefixedID!
1603+
1604+
"""Core system versions"""
1605+
core: CoreVersions!
1606+
1607+
"""Software package versions"""
1608+
packages: PackageVersions!
15961609
}
15971610

15981611
type Info implements Node {

api/src/unraid-api/cli/generated/graphql.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,8 @@ export type InfoVersions = Node & {
10411041
__typename?: 'InfoVersions';
10421042
/** Apache version */
10431043
apache?: Maybe<Scalars['String']['output']>;
1044+
/** Unraid API version */
1045+
api?: Maybe<Scalars['String']['output']>;
10441046
/** Docker version */
10451047
docker?: Maybe<Scalars['String']['output']>;
10461048
/** gcc version */

api/src/unraid-api/graph/resolvers/info/info.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { DisplayService } from '@app/unraid-api/graph/resolvers/info/display/dis
88
import { InfoResolver } from '@app/unraid-api/graph/resolvers/info/info.resolver.js';
99
import { MemoryService } from '@app/unraid-api/graph/resolvers/info/memory/memory.service.js';
1010
import { OsService } from '@app/unraid-api/graph/resolvers/info/os/os.service.js';
11+
import { CoreVersionsResolver } from '@app/unraid-api/graph/resolvers/info/versions/core-versions.resolver.js';
12+
import { VersionsResolver } from '@app/unraid-api/graph/resolvers/info/versions/versions.resolver.js';
1113
import { VersionsService } from '@app/unraid-api/graph/resolvers/info/versions/versions.service.js';
1214
import { ServicesModule } from '@app/unraid-api/graph/services/services.module.js';
1315

@@ -19,6 +21,8 @@ import { ServicesModule } from '@app/unraid-api/graph/services/services.module.j
1921

2022
// Sub-resolvers
2123
DevicesResolver,
24+
VersionsResolver,
25+
CoreVersionsResolver,
2226

2327
// Services
2428
CpuService,
@@ -28,6 +32,6 @@ import { ServicesModule } from '@app/unraid-api/graph/services/services.module.j
2832
VersionsService,
2933
DisplayService,
3034
],
31-
exports: [InfoResolver, DevicesResolver, DisplayService],
35+
exports: [InfoResolver, DevicesResolver, VersionsResolver, CoreVersionsResolver, DisplayService],
3236
})
3337
export class InfoModule {}

api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,7 @@ describe('InfoResolver Integration Tests', () => {
169169
const result = await infoResolver.versions();
170170

171171
expect(result).toHaveProperty('id', 'info/versions');
172-
expect(result).toHaveProperty('unraid');
173-
expect(result).toHaveProperty('kernel');
174-
expect(result).toHaveProperty('node');
175-
expect(result).toHaveProperty('npm');
176-
// Verify unraid version from mock
177-
expect(result.unraid).toBe('6.12.0');
172+
// Versions now returns a stub object, with actual data resolved via field resolvers
178173
});
179174
});
180175

api/src/unraid-api/graph/resolvers/info/info.resolver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export class InfoResolver {
9494
}
9595

9696
@ResolveField(() => InfoVersions)
97-
public async versions(): Promise<InfoVersions> {
97+
public versions(): Partial<InfoVersions> {
9898
return this.versionsService.generateVersions();
9999
}
100100
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ResolveField, Resolver } from '@nestjs/graphql';
2+
3+
import { versions } from 'systeminformation';
4+
5+
import { CoreVersions } from '@app/unraid-api/graph/resolvers/info/versions/versions.model.js';
6+
7+
@Resolver(() => CoreVersions)
8+
export class CoreVersionsResolver {
9+
@ResolveField(() => String, { nullable: true })
10+
async kernel(): Promise<string | undefined> {
11+
const softwareVersions = await versions();
12+
return softwareVersions.kernel;
13+
}
14+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { readFileSync } from 'node:fs';
2+
import { join } from 'node:path';
3+
4+
let cachedVersion: string | undefined;
5+
6+
export function getApiVersion(): string {
7+
if (cachedVersion) {
8+
return cachedVersion;
9+
}
10+
11+
try {
12+
const packagePath = join(process.cwd(), 'package.json');
13+
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
14+
cachedVersion = packageJson.version || 'unknown';
15+
return cachedVersion;
16+
} catch (error) {
17+
console.error('Failed to read API version from package.json:', error);
18+
return 'unknown';
19+
}
20+
}

api/src/unraid-api/graph/resolvers/info/versions/versions.model.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@ import { Field, ObjectType } from '@nestjs/graphql';
22

33
import { Node } from '@unraid/shared/graphql.model.js';
44

5-
@ObjectType({ implements: () => Node })
6-
export class InfoVersions extends Node {
5+
@ObjectType()
6+
export class CoreVersions {
7+
@Field(() => String, { nullable: true, description: 'Unraid version' })
8+
unraid?: string;
9+
10+
@Field(() => String, { nullable: true, description: 'Unraid API version' })
11+
api?: string;
12+
713
@Field(() => String, { nullable: true, description: 'Kernel version' })
814
kernel?: string;
15+
}
916

17+
@ObjectType()
18+
export class PackageVersions {
1019
@Field(() => String, { nullable: true, description: 'OpenSSL version' })
1120
openssl?: string;
1221

@@ -90,7 +99,13 @@ export class InfoVersions extends Node {
9099

91100
@Field(() => String, { nullable: true, description: 'Docker version' })
92101
docker?: string;
102+
}
93103

94-
@Field(() => String, { nullable: true, description: 'Unraid version' })
95-
unraid?: string;
104+
@ObjectType({ implements: () => Node })
105+
export class InfoVersions extends Node {
106+
@Field(() => CoreVersions, { description: 'Core system versions' })
107+
core!: CoreVersions;
108+
109+
@Field(() => PackageVersions, { description: 'Software package versions' })
110+
packages!: PackageVersions;
96111
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { ConfigService } from '@nestjs/config';
2+
import { ResolveField, Resolver } from '@nestjs/graphql';
3+
4+
import { versions } from 'systeminformation';
5+
6+
import {
7+
CoreVersions,
8+
InfoVersions,
9+
PackageVersions,
10+
} from '@app/unraid-api/graph/resolvers/info/versions/versions.model.js';
11+
12+
@Resolver(() => InfoVersions)
13+
export class VersionsResolver {
14+
constructor(private readonly configService: ConfigService) {}
15+
16+
@ResolveField(() => CoreVersions)
17+
core(): CoreVersions {
18+
const unraid = this.configService.get<string>('store.emhttp.var.version') || 'unknown';
19+
const api = this.configService.get<string>('api.version') || 'unknown';
20+
21+
return {
22+
unraid,
23+
api,
24+
kernel: undefined, // Will be resolved separately if requested
25+
};
26+
}
27+
28+
@ResolveField(() => PackageVersions)
29+
async packages(): Promise<PackageVersions> {
30+
const softwareVersions = await versions();
31+
32+
return {
33+
openssl: softwareVersions.openssl,
34+
systemOpenssl: softwareVersions.systemOpenssl,
35+
node: softwareVersions.node,
36+
v8: softwareVersions.v8,
37+
npm: softwareVersions.npm,
38+
yarn: softwareVersions.yarn,
39+
pm2: softwareVersions.pm2,
40+
gulp: softwareVersions.gulp,
41+
grunt: softwareVersions.grunt,
42+
git: softwareVersions.git,
43+
tsc: softwareVersions.tsc,
44+
mysql: softwareVersions.mysql,
45+
redis: softwareVersions.redis,
46+
mongodb: softwareVersions.mongodb,
47+
apache: (softwareVersions as any).apache,
48+
nginx: softwareVersions.nginx,
49+
php: softwareVersions.php,
50+
postfix: softwareVersions.postfix,
51+
postgresql: softwareVersions.postgresql,
52+
perl: softwareVersions.perl,
53+
python: softwareVersions.python,
54+
python3: softwareVersions.python3,
55+
pip: softwareVersions.pip,
56+
pip3: softwareVersions.pip3,
57+
java: softwareVersions.java,
58+
gcc: softwareVersions.gcc,
59+
virtualbox: softwareVersions.virtualbox,
60+
docker: softwareVersions.docker,
61+
};
62+
}
63+
}

0 commit comments

Comments
 (0)