Update/040 types (#2845)

* small type changes and clear todos

* handle notifications and metrics

* wip

* fixes

* migration

* dedup all urls

* better handling of clearnet ips

* add rfkill dependency

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
This commit is contained in:
Aiden McClelland
2025-03-06 20:36:19 -07:00
committed by GitHub
parent ac392dcb96
commit e830fade06
63 changed files with 800 additions and 480 deletions

View File

@@ -771,7 +771,7 @@ export namespace Mock {
},
},
},
read: false,
seen: false,
},
{
id: 2,
@@ -782,7 +782,7 @@ export namespace Mock {
title: 'SSH Key Added',
message: 'A new SSH key was added. If you did not do this, shit is bad.',
data: null,
read: false,
seen: false,
},
{
id: 3,
@@ -793,7 +793,7 @@ export namespace Mock {
title: 'SSH Key Removed',
message: 'A SSH key was removed.',
data: null,
read: false,
seen: false,
},
{
id: 4,
@@ -811,7 +811,7 @@ export namespace Mock {
)
.join(''),
data: null,
read: false,
seen: false,
},
{
id: 5,
@@ -822,7 +822,7 @@ export namespace Mock {
title: 'Welcome to StartOS 0.3.6!',
message: 'Click "View Details" to learn all about the new version',
data: markdown,
read: false,
seen: false,
},
]

View File

@@ -81,7 +81,6 @@ export namespace RR {
guid: string
}
// @TODO 040 implement websocket
export type FollowServerMetricsReq = {} // server.metrics.follow
export type FollowServerMetricsRes = {
guid: string
@@ -136,17 +135,16 @@ export namespace RR {
} // notification.list
export type GetNotificationsRes = ServerNotification<number>[]
// @TODO 040 all these notification endpoints need updating
export type DeleteNotificationReq = { ids: number[] } // notification.delete
export type DeleteNotificationRes = null
export type DeleteNotificationsReq = { ids: number[] } // notification.remove
export type DeleteNotificationsRes = null
export type MarkSeenNotificationReq = DeleteNotificationReq // notification.mark-seen
export type MarkSeenNotificationReq = DeleteNotificationsReq // notification.mark-seen
export type MarkSeenNotificationRes = null
export type MarkSeenAllNotificationsReq = { before: number } // notification.mark-seen-before
export type MarkSeenAllNotificationsRes = null
export type MarkUnseenNotificationReq = DeleteNotificationReq // notification.mark-unseen
export type MarkUnseenNotificationReq = DeleteNotificationsReq // notification.mark-unseen
export type MarkUnseenNotificationRes = null
// wifi
@@ -175,9 +173,11 @@ export namespace RR {
}
export type AddWifiRes = null
// @TODO 040
export type EnableWifiReq = { enable: boolean } // wifi.enable
export type EnableWifiRes = null
export type EnabledWifiReq = { enable: boolean } // wifi.set-enabled
export type EnabledWifiRes = null
export type SetWifiCountryReq = { country: string } // wifi.country.set
export type SetWifiCountryRes = null
export type ConnectWifiReq = { ssid: string } // wifi.connect
export type ConnectWifiRes = null
@@ -523,8 +523,7 @@ export type ServerNotification<T extends number> = {
title: string
message: string
data: NotificationData<T>
// @TODO 040
read: boolean
seen: boolean
}
export type NotificationLevel = 'success' | 'info' | 'warning' | 'error'
@@ -532,10 +531,10 @@ export type NotificationLevel = 'success' | 'info' | 'warning' | 'error'
export type NotificationData<T> = T extends 0
? null
: T extends 1
? BackupReport
: T extends 2
? string
: any
? BackupReport
: T extends 2
? string
: any
export type BackupReport = {
server: {

View File

@@ -177,12 +177,12 @@ export abstract class ApiService {
): Promise<RR.MarkSeenAllNotificationsRes>
abstract markUnseenNotifications(
params: RR.DeleteNotificationReq,
): Promise<RR.DeleteNotificationRes>
params: RR.DeleteNotificationsReq,
): Promise<RR.DeleteNotificationsRes>
abstract deleteNotifications(
params: RR.DeleteNotificationReq,
): Promise<RR.DeleteNotificationRes>
params: RR.DeleteNotificationsReq,
): Promise<RR.DeleteNotificationsRes>
// ** proxies **
@@ -220,7 +220,11 @@ export abstract class ApiService {
// wifi
abstract enableWifi(params: RR.EnableWifiReq): Promise<RR.EnableWifiRes>
abstract enableWifi(params: RR.EnabledWifiReq): Promise<RR.EnabledWifiRes>
abstract setWifiCountry(
params: RR.SetWifiCountryReq,
): Promise<RR.SetWifiCountryRes>
abstract getWifi(
params: RR.GetWifiReq,

View File

@@ -245,7 +245,6 @@ export class LiveApiService extends ApiService {
async followServerMetrics(
params: RR.FollowServerMetricsReq,
): Promise<RR.FollowServerMetricsRes> {
// @TODO 040 implement .follow
return this.rpcRequest({ method: 'server.metrics.follow', params })
}
@@ -350,8 +349,8 @@ export class LiveApiService extends ApiService {
}
async deleteNotifications(
params: RR.DeleteNotificationReq,
): Promise<RR.DeleteNotificationRes> {
params: RR.DeleteNotificationsReq,
): Promise<RR.DeleteNotificationsRes> {
return this.rpcRequest({ method: 'notification.remove', params })
}
@@ -422,7 +421,7 @@ export class LiveApiService extends ApiService {
// wifi
async enableWifi(params: RR.EnableWifiReq): Promise<RR.EnableWifiRes> {
async enableWifi(params: RR.EnabledWifiReq): Promise<RR.EnabledWifiRes> {
return this.rpcRequest({ method: 'wifi.enable', params })
}
@@ -433,6 +432,12 @@ export class LiveApiService extends ApiService {
return this.rpcRequest({ method: 'wifi.get', params, timeout })
}
async setWifiCountry(
params: RR.SetWifiCountryReq,
): Promise<RR.SetWifiCountryRes> {
return this.rpcRequest({ method: 'wifi.country.set', params })
}
async addWifi(params: RR.AddWifiReq): Promise<RR.AddWifiRes> {
return this.rpcRequest({ method: 'wifi.add', params })
}

View File

@@ -519,8 +519,8 @@ export class MockApiService extends ApiService {
}
async deleteNotifications(
params: RR.DeleteNotificationReq,
): Promise<RR.DeleteNotificationRes> {
params: RR.DeleteNotificationsReq,
): Promise<RR.DeleteNotificationsRes> {
await pauseFor(2000)
return null
}
@@ -696,7 +696,7 @@ export class MockApiService extends ApiService {
// wifi
async enableWifi(params: RR.EnableWifiReq): Promise<RR.EnableWifiRes> {
async enableWifi(params: RR.EnabledWifiReq): Promise<RR.EnabledWifiRes> {
await pauseFor(2000)
const patch = [
{
@@ -710,6 +710,13 @@ export class MockApiService extends ApiService {
return null
}
async setWifiCountry(
params: RR.SetWifiCountryReq,
): Promise<RR.SetWifiCountryRes> {
await pauseFor(2000)
return null
}
async getWifi(params: RR.GetWifiReq): Promise<RR.GetWifiRes> {
await pauseFor(2000)
return Mock.Wifi

View File

@@ -39,6 +39,11 @@ export const mockPatchData: DataModel = {
selected: null,
lastRegion: null,
},
acme: {
[knownACME[0].url]: {
contact: ['mailto:support@start9.com'],
},
},
host: {
bindings: {
80: {
@@ -171,11 +176,6 @@ export const mockPatchData: DataModel = {
},
},
},
acme: {
[knownACME[0].url]: {
contact: ['mailto:support@start9.com'],
},
},
unreadNotificationCount: 4,
// password is asdfasdf
passwordHash:
@@ -191,109 +191,6 @@ export const mockPatchData: DataModel = {
backupProgress: {},
},
hostname: 'random-words',
// @ts-ignore
host: {
bindings: {
80: {
enabled: true,
net: {
assignedPort: null,
assignedSslPort: 443,
public: false,
},
options: {
preferredExternalPort: 80,
addSsl: {
preferredExternalPort: 443,
alpn: { specified: ['http/1.1', 'h2'] },
},
secure: null,
},
},
},
domains: {},
onions: ['myveryownspecialtoraddress'],
hostnameInfo: {
80: [
{
kind: 'ip',
networkInterfaceId: 'eth0',
public: false,
hostname: {
kind: 'local',
value: 'adjective-noun.local',
port: null,
sslPort: 443,
},
},
{
kind: 'ip',
networkInterfaceId: 'wlan0',
public: false,
hostname: {
kind: 'local',
value: 'adjective-noun.local',
port: null,
sslPort: 443,
},
},
{
kind: 'ip',
networkInterfaceId: 'eth0',
public: false,
hostname: {
kind: 'ipv4',
value: '10.0.0.1',
port: null,
sslPort: 443,
},
},
{
kind: 'ip',
networkInterfaceId: 'wlan0',
public: false,
hostname: {
kind: 'ipv4',
value: '10.0.0.2',
port: null,
sslPort: 443,
},
},
{
kind: 'ip',
networkInterfaceId: 'eth0',
public: false,
hostname: {
kind: 'ipv6',
value: 'fe80::cd00:0000:0cde:1257:0000:211e:72cd',
scopeId: 2,
port: null,
sslPort: 443,
},
},
{
kind: 'ip',
networkInterfaceId: 'wlan0',
public: false,
hostname: {
kind: 'ipv6',
value: 'fe80::cd00:0000:0cde:1257:0000:211e:1234',
scopeId: 3,
port: null,
sslPort: 443,
},
},
{
kind: 'onion',
hostname: {
value: 'myveryownspecialtoraddress.onion',
port: 80,
sslPort: 443,
},
},
],
},
},
pubkey: 'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m',
caFingerprint: 'SHA-256: 63 2B 11 99 44 40 17 DF 37 FC C3 DF 0F 3D 15',
ntpSynced: false,

View File

@@ -25,7 +25,7 @@ export class NotificationService {
).pipe(shareReplay(1))
async markSeen(notifications: ServerNotifications) {
const ids = notifications.filter(n => !n.read).map(n => n.id)
const ids = notifications.filter(n => !n.seen).map(n => n.id)
this.updateCount(-ids.length)
@@ -43,7 +43,7 @@ export class NotificationService {
}
async markUnseen(notifications: ServerNotifications) {
const ids = notifications.filter(n => n.read).map(n => n.id)
const ids = notifications.filter(n => n.seen).map(n => n.id)
this.updateCount(ids.length)
@@ -53,7 +53,7 @@ export class NotificationService {
}
async remove(notifications: ServerNotifications): Promise<void> {
this.updateCount(-notifications.filter(n => !n.read).length)
this.updateCount(-notifications.filter(n => !n.seen).length)
this.api
.deleteNotifications({ ids: notifications.map(n => n.id) })

View File

@@ -1,16 +1,6 @@
import { T } from '@start9labs/start-sdk'
export type DataModel = Omit<T.Public, 'serverInfo'> & {
ui: UIData
// @TODO 040
serverInfo: Omit<
T.Public['serverInfo'],
'wifi' | 'networkInterfaces' | 'host'
> & {
network: NetworkInfo
}
packageData: Record<string, PackageDataEntry>
}
export type DataModel = T.Public & { ui: UIData; packageData: AllPackageData }
export type UIData = {
name: string | null
@@ -37,20 +27,7 @@ export type UIStore = {
name?: string
}
export type NetworkInfo = {
wifi: T.WifiInfo & { enabled: boolean }
host: T.Host
networkInterfaces: {
[id: string]: {
inbound: boolean | null
outbound: boolean | null
ipInfo:
| (T.IpInfo & {
name: string
})
| null
}
}
export type NetworkInfo = T.NetworkInfo & {
// @TODO 041
// start9To: {
// subdomain: string