@axium/sysadmin 0.2.0 → 0.2.2

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.
@@ -129,6 +129,27 @@ function memory() {
129
129
  total,
130
130
  used: total - available,
131
131
  };
132
+ try {
133
+ const dmiMemoryInfo = execFileSync('sudo', ['-n', 'dmidecode', '-t', '17'], {
134
+ encoding: 'utf8',
135
+ stdio: ['ignore', 'pipe', 'ignore'],
136
+ });
137
+ for (const match of dmiMemoryInfo.matchAll(/^\s*(?:Configured Memory|Configured Clock)?\s*Speed:\s*(\d+)\s*MT\/s/gim)) {
138
+ memory.speed = Math.max(memory.speed, Number(match[1]));
139
+ }
140
+ const populated = (field) => {
141
+ for (const [, match] of dmiMemoryInfo.matchAll(new RegExp(`^[ \\t]*${field}:[ \\t]*(.+)$`, 'gim'))) {
142
+ const value = match.trim();
143
+ if (value && value !== 'Unknown')
144
+ return value;
145
+ }
146
+ };
147
+ memory.formFactor = populated('Form Factor');
148
+ memory.type = populated('Type');
149
+ }
150
+ catch {
151
+ // dmidecode missing, not root, or sudo needs a password
152
+ }
132
153
  const swapTotal = info.SwapTotal ?? 0n;
133
154
  if (swapTotal > 0n)
134
155
  memory.swap = { total: swapTotal, used: swapTotal - (info.SwapFree ?? 0n) };
package/dist/common.d.ts CHANGED
@@ -320,6 +320,8 @@ declare const SysadminClientToServer: {
320
320
  }, z.core.$strip>>;
321
321
  memory: z.ZodObject<{
322
322
  speed: z.ZodInt;
323
+ formFactor: z.ZodOptional<z.ZodString>;
324
+ type: z.ZodOptional<z.ZodString>;
323
325
  swap: z.ZodOptional<z.ZodObject<{
324
326
  total: z.ZodCoercedBigInt<unknown>;
325
327
  used: z.ZodCoercedBigInt<unknown>;
@@ -376,6 +378,8 @@ declare const SysadminServerToClient: {
376
378
  }, z.core.$strip>>;
377
379
  memory: z.ZodObject<{
378
380
  speed: z.ZodInt;
381
+ formFactor: z.ZodOptional<z.ZodString>;
382
+ type: z.ZodOptional<z.ZodString>;
379
383
  swap: z.ZodOptional<z.ZodObject<{
380
384
  total: z.ZodCoercedBigInt<unknown>;
381
385
  used: z.ZodCoercedBigInt<unknown>;
package/dist/info.d.ts CHANGED
@@ -23,6 +23,8 @@ export interface GPU extends z.infer<typeof GPU> {
23
23
  }
24
24
  export declare const Memory: z.ZodObject<{
25
25
  speed: z.ZodInt;
26
+ formFactor: z.ZodOptional<z.ZodString>;
27
+ type: z.ZodOptional<z.ZodString>;
26
28
  swap: z.ZodOptional<z.ZodObject<{
27
29
  total: z.ZodCoercedBigInt<unknown>;
28
30
  used: z.ZodCoercedBigInt<unknown>;
@@ -72,6 +74,8 @@ export declare const SystemInfo: z.ZodObject<{
72
74
  }, z.core.$strip>>;
73
75
  memory: z.ZodObject<{
74
76
  speed: z.ZodInt;
77
+ formFactor: z.ZodOptional<z.ZodString>;
78
+ type: z.ZodOptional<z.ZodString>;
75
79
  swap: z.ZodOptional<z.ZodObject<{
76
80
  total: z.ZodCoercedBigInt<unknown>;
77
81
  used: z.ZodCoercedBigInt<unknown>;
package/dist/info.js CHANGED
@@ -17,6 +17,10 @@ export const Memory = z.object({
17
17
  ...TotalUsed.shape,
18
18
  /** Memory speed in MT/s */
19
19
  speed: z.int().nonnegative(),
20
+ /** Form factor, e.g. 'DIMM' or 'SODIMM' */
21
+ formFactor: z.string().optional(),
22
+ /** Memory type, e.g. 'DDR4' or 'DDR5' */
23
+ type: z.string().optional(),
20
24
  /** Only available when swap is in use */
21
25
  swap: TotalUsed.optional(),
22
26
  });
package/locales/en.json CHANGED
@@ -14,8 +14,6 @@
14
14
  "online": "Online",
15
15
  "offline": "Offline",
16
16
  "back_to_main": "Back to System Administration",
17
- "back_to_systems": "Back to Systems",
18
- "back_to_users": "Back to System Users",
19
17
  "SystemInitDialog": {
20
18
  "submit": "Add System",
21
19
  "save": "Save",
@@ -62,6 +60,7 @@
62
60
  "cpu_cores": "{count} cores",
63
61
  "gpu": "Graphics",
64
62
  "memory": "Memory",
63
+ "memory_speed": "{speed} MT/s",
65
64
  "swap": "Swap",
66
65
  "storage": "Storage",
67
66
  "network": "Network",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/sysadmin",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "description": "System administration for Axium",
6
6
  "funding": {
@@ -31,22 +31,17 @@
31
31
  }
32
32
 
33
33
  function usageText(used: bigint, total: bigint): string {
34
+ if (used <= 0n) return formatBytes(total);
34
35
  return text('sysadmin.system.usage', { used: formatBytes(used), total: formatBytes(total) });
35
36
  }
36
37
 
37
- function speedText(speed: number): string {
38
- if (speed < 1000) return `${speed} MBit/s`;
39
- const gb = speed / 1000;
40
- return `${gb % 1 === 0 ? gb : gb.toFixed(1)} GBit/s`;
41
- }
42
-
43
38
  const socket = await connect();
44
39
 
45
40
  async function loadInfo() {
46
41
  try {
47
42
  const all = await socket.emitWithAck('sysadmin:getSystemInfo');
48
43
  info = all.find(i => i.hostname === system.hostname);
49
- if (!info) error = true;
44
+ error = !info;
50
45
  } catch {
51
46
  error = true;
52
47
  } finally {
@@ -64,9 +59,9 @@
64
59
  </svelte:head>
65
60
 
66
61
  <div class="system-page">
67
- <a class="subtle icon-text back" href="/sysadmin/systems">
62
+ <a class="subtle icon-text back" href="/sysadmin">
68
63
  <Icon i="arrow-left" />
69
- <span>{text('sysadmin.back_to_systems')}</span>
64
+ <span>{text('sysadmin.back_to_main')}</span>
70
65
  </a>
71
66
 
72
67
  <div class="system-header">
@@ -124,7 +119,19 @@
124
119
  {/if}
125
120
 
126
121
  <div class="component">
127
- <h3><Icon i="memory" /> {text('sysadmin.system.memory')}</h3>
122
+ <h3>
123
+ <Icon i="memory" />
124
+ {text('sysadmin.system.memory')}
125
+ {#if info.memory.type}
126
+ <span class="subtle">{info.memory.type}</span>
127
+ {/if}
128
+ {#if info.memory.formFactor}
129
+ <span class="subtle">{info.memory.formFactor}</span>
130
+ {/if}
131
+ {#if info.memory.speed}
132
+ <span class="subtle">{text('sysadmin.system.memory_speed', { speed: info.memory.speed })}</span>
133
+ {/if}
134
+ </h3>
128
135
  <NumberBar
129
136
  value={fraction(info.memory.used, info.memory.total)}
130
137
  max={1}
@@ -170,7 +177,11 @@
170
177
  {/if}
171
178
  </span>
172
179
  {#if iface.speed}
173
- <span class="subtle">{speedText(iface.speed)}</span>
180
+ <span class="subtle"
181
+ >{iface.speed < 1000
182
+ ? `${iface.speed} MBit/s`
183
+ : `${(iface.speed / 1000).toFixed(2).replace(/\.?0+$/, '')} GBit/s`}</span
184
+ >
174
185
  {/if}
175
186
  </span>
176
187
  </div>
@@ -27,9 +27,9 @@
27
27
  </svelte:head>
28
28
 
29
29
  <div class="user-page">
30
- <a class="subtle icon-text back" href="/sysadmin/users">
30
+ <a class="subtle icon-text back" href="/sysadmin">
31
31
  <Icon i="arrow-left" />
32
- <span>{text('sysadmin.back_to_users')}</span>
32
+ <span>{text('sysadmin.back_to_main')}</span>
33
33
  </a>
34
34
 
35
35
  <div class="user-header">