Skip to content

Commit 0d4f327

Browse files
committed
remove .json in paths, and use superagent instead of axios
1 parent b4f4dae commit 0d4f327

File tree

16 files changed

+152
-116
lines changed

16 files changed

+152
-116
lines changed

β€Žsrc/lib/NMOS.tsβ€Ž

Lines changed: 135 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
import { NMOSDeviceRuntimeOptions, NMOSNodeRuntimeOptions } from './types'
2-
import { Axios } from 'axios'
32
import is04endpoints from '../schema/is04/index'
43
import is05endpoints from '../schema/is05/index'
54
import { z, ZodError } from 'zod'
6-
import _ from 'lodash'
5+
import _, { type get } from 'lodash'
6+
import superagent, { type SuperAgent, type SuperAgentStatic } from 'superagent'
7+
import nodeapiBaseV13 from '../schema/is04/v1.3/zod/nodeapi-base.json'
8+
import nodeapiBaseV12 from '../schema/is04/v1.2/zod/nodeapi-base.json'
9+
import nodeapiSelfV13 from '../schema/is04/v1.3/zod/_node'
10+
import nodeapiSelfV12 from '../schema/is04/v1.2/zod/_node'
11+
import nodeapiDevicesV13 from '../schema/is04/v1.3/zod/_devices'
12+
import nodeapiDevicesV12 from '../schema/is04/v1.2/zod/_devices'
13+
import nodeapiSourcesV13 from '../schema/is04/v1.3/zod/_sources'
14+
import nodeapiSourcesV12 from '../schema/is04/v1.2/zod/_sources'
15+
import nodeapiFlowsV13 from '../schema/is04/v1.3/zod/_flows'
16+
import nodeapiFlowsV12 from '../schema/is04/v1.2/zod/_flows'
17+
import nodeapiSendersV13 from '../schema/is04/v1.3/zod/_senders'
18+
import nodeapiSendersV12 from '../schema/is04/v1.2/zod/_senders'
19+
import nodeapiReceiversV13 from '../schema/is04/v1.3/zod/_receivers'
20+
import nodeapiReceiversV12 from '../schema/is04/v1.2/zod/_receivers'
721

822
type IS04Endpoints = typeof is04endpoints
923
export type IS04EndpointTypes = keyof typeof is04endpoints
@@ -14,141 +28,160 @@ export type IS05EndpointTypes = keyof typeof is05endpoints
1428
export type IS05EndpointType<T extends IS05EndpointTypes> = z.infer<IS05Endpoints[T]>
1529

1630
export class NMOSNodeRuntime {
17-
private runtime: Axios
1831
private options: NMOSNodeRuntimeOptions
1932

33+
private protocol: 'http' | 'https'
34+
private host: string
35+
private port: number
36+
private basePath: string
37+
private is04Version: 'v1.0' | 'v1.1' | 'v1.2' | 'v1.3' | undefined
38+
private timeout: number = 2000
39+
private insecureHTTPParser: boolean = true
40+
2041
constructor(options: NMOSNodeRuntimeOptions) {
2142
this.options = options
22-
this.runtime = new Axios({
23-
baseURL: `${options.protocol}://${options.host}:${options.port}${options.basePath}`,
24-
timeout: 1000,
25-
headers: {
26-
'Content-Type': 'application/json',
27-
},
28-
})
43+
this.protocol = options.protocol
44+
this.host = options.host
45+
this.port = options.port
46+
this.basePath = options.basePath
47+
this.timeout = options.timeout || 2000
48+
this.insecureHTTPParser = options.insecureHTTPParser || true
2949
}
3050

31-
async get<T extends IS04EndpointTypes>(path: T, options: Record<string, string> = {}): Promise<z.infer<typeof is04endpoints[T]>> {
32-
const endpoint = is04endpoints[path]
33-
const resolvedPath = path.replace(/{([^}]*)}/g, (_, key) => options[key])
34-
const result = await this.runtime.get<IS04EndpointType<T>>(resolvedPath)
51+
setIS04Version(version: 'v1.0' | 'v1.1' | 'v1.2' | 'v1.3') {
52+
this.is04Version = version
53+
}
3554

36-
if (result.status !== 200) {
37-
throw new Error('Failed to fetch data from: ' + resolvedPath)
38-
}
55+
async probeNodeApiSupport(): Promise<('v1.0' | 'v1.1' | 'v1.2' | 'v1.3')[]> {
56+
const response = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node`)
57+
const firstParse = z
58+
.array(z.string())
59+
.parse(response.body)
60+
.map((s) => s.replace(/\/$/, ''))
61+
62+
return firstParse as ('v1.0' | 'v1.1' | 'v1.2' | 'v1.3')[]
63+
}
3964

40-
if (typeof result.data === 'string') {
41-
try {
42-
result.data = JSON.parse(result.data)
43-
} catch (error) {
44-
console.error(error)
45-
throw new Error('Failed to parse JSON')
46-
}
65+
requireIS04Version() {
66+
if (!this.is04Version) {
67+
throw new Error('IS04 version not set')
4768
}
69+
}
4870

49-
if (this.options.strict) {
50-
return await endpoint.parseAsync(result.data)
51-
} else {
52-
const parse = await endpoint.safeParseAsync(result.data)
71+
get(url: string) {
72+
return superagent.get(url).timeout(this.timeout).disableTLSCerts().accept('json')
73+
}
5374

54-
if (!parse.success) {
55-
parse.error.errors.forEach((error) => {
56-
console.error('Validation error [' + path + ']', error.path.join('.') + ': ' + error.message, 'received', _.get(result.data, error.path.join('.')))
57-
})
58-
}
75+
async nodeSelfGet() {
76+
this.requireIS04Version()
77+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/self`)
78+
79+
if (this.is04Version === 'v1.3') {
80+
const safe = nodeapiSelfV13.parse(httpRes.body)
81+
return safe
82+
}
5983

60-
return parse.data as z.infer<typeof endpoint>
84+
if (this.is04Version === 'v1.2') {
85+
const safe = nodeapiSelfV12.parse(httpRes.body)
86+
// do polyfill here....
87+
return safe
6188
}
89+
90+
throw new Error('Unknown IS04 version')
6291
}
63-
}
6492

65-
export class NMOSConnectionRuntime {
66-
private runtime: Axios
67-
private options: NMOSDeviceRuntimeOptions
93+
async nodeDevicesGet() {
94+
this.requireIS04Version()
95+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/devices`)
96+
97+
if (this.is04Version === 'v1.3') {
98+
const safe = nodeapiDevicesV13.parse(httpRes.body)
99+
return safe
100+
}
68101

69-
constructor(options: NMOSDeviceRuntimeOptions) {
70-
this.options = options
71-
this.runtime = new Axios({
72-
baseURL: `${options.baseUrl}`,
73-
timeout: 1000,
74-
headers: {
75-
'Content-Type': 'application/json',
76-
},
77-
})
102+
if (this.is04Version === 'v1.2') {
103+
const safe = nodeapiDevicesV12.parse(httpRes.body)
104+
return safe
105+
}
106+
107+
throw new Error('Unknown IS04 version')
78108
}
79109

80-
async execute<T extends IS05EndpointTypes>(method: 'patch' | 'get', path: T, options: Record<string, string> = {}) {
81-
const endpoint = is05endpoints[path]
82-
const resolvedPath = path.replace(/{([^}]*)}/g, (_, key) => options[key])
83110

84-
if (method !== 'get' && method !== 'patch') {
85-
throw new Error('unknwon method ' + method)
111+
async nodeSourcesGet() {
112+
this.requireIS04Version()
113+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/sources`)
114+
115+
if (this.is04Version === 'v1.3') {
116+
const safe = nodeapiSourcesV13.parse(httpRes.body)
117+
return safe
86118
}
87119

88-
const result = method === 'get' ? await this.runtime.get<IS05EndpointType<T>>(resolvedPath) : method === 'patch' ? await this.runtime.patch<IS05EndpointType<T>>(resolvedPath) : undefined
89-
90-
if (!result) {
91-
throw new Error('Unknown error')
120+
if (this.is04Version === 'v1.2') {
121+
const safe = nodeapiSourcesV12.parse(httpRes.body)
122+
return safe
92123
}
93124

94-
if (result.status !== 200) {
95-
throw new Error('Failed to fetch data from: ' + resolvedPath)
125+
throw new Error('Unknown IS04 version')
126+
}
127+
128+
129+
async nodeFlowsGet() {
130+
this.requireIS04Version()
131+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/flows`)
132+
133+
if (this.is04Version === 'v1.3') {
134+
const safe = nodeapiFlowsV13.parse(httpRes.body)
135+
return safe
96136
}
97137

98-
try {
99-
if (typeof result.data === 'string') {
100-
try {
101-
result.data = JSON.parse(result.data)
102-
} catch (error) {
103-
console.error(error)
104-
throw new Error('Failed to parse JSON')
105-
}
106-
}
107-
108-
const parse = await endpoint.safeParseAsync(result.data)
109-
110-
if (!parse.success) {
111-
parse.error.errors.forEach((error) => {
112-
console.error('Validation error [' + path + ']', error.path.join('.') + ': ' + error.message, 'received', _.get(result.data, error.path.join('.')))
113-
})
114-
115-
if (this.options.strict) {
116-
console.error('Strict mode enabled, failed to parse data')
117-
throw new ZodError(parse.error.issues)
118-
}
119-
}
120-
121-
return parse.data as z.infer<typeof endpoint>
122-
123-
} catch (error) {
124-
console.error('error', error)
138+
if (this.is04Version === 'v1.2') {
139+
const safe = nodeapiFlowsV12.parse(httpRes.body)
140+
return safe
125141
}
126-
}
127142

128-
async get<T extends IS05EndpointTypes>(path: T, options: Record<string, string> = {}) {
129-
this.execute('get', path, options)
143+
throw new Error('Unknown IS04 version')
130144
}
131145

132-
async patch<T extends IS05EndpointTypes>(path: T, options: Record<string, string> = {}) {
133-
this.execute('patch', path, options)
146+
async nodeSendersGet() {
147+
this.requireIS04Version()
148+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/senders`)
149+
150+
if (this.is04Version === 'v1.3') {
151+
const safe = nodeapiSendersV13.parse(httpRes.body)
152+
return safe
153+
}
154+
155+
if (this.is04Version === 'v1.2') {
156+
const safe = nodeapiSendersV12.parse(httpRes.body)
157+
return safe
158+
}
159+
160+
throw new Error('Unknown IS04 version')
134161
}
135-
}
136162

163+
async nodeReceiversGet() {
164+
this.requireIS04Version()
165+
const httpRes = await this.get(`${this.protocol}://${this.host}:${this.port}${this.basePath}/node/${this.is04Version}/receivers`)
137166

167+
if (this.is04Version === 'v1.3') {
168+
const safe = nodeapiReceiversV13.parse(httpRes.body)
169+
return safe
170+
}
138171

172+
if (this.is04Version === 'v1.2') {
173+
const safe = nodeapiReceiversV12.parse(httpRes.body)
174+
return safe
175+
}
139176

140-
export class NMOSConnectionAPI extends NMOSConnectionRuntime {
141-
constructor({
142-
baseUrl = '',
143-
strict = true,
144-
}: Partial<NMOSDeviceRuntimeOptions>) {
145-
super({
146-
baseUrl,
147-
strict,
148-
})
177+
throw new Error('Unknown IS04 version')
149178
}
179+
180+
150181
}
151182

183+
184+
152185
export class NMOSNodeAPI extends NMOSNodeRuntime {
153186
constructor({
154187
dialect = null,
@@ -158,6 +191,7 @@ export class NMOSNodeAPI extends NMOSNodeRuntime {
158191
basePath = '/x-nmos',
159192
strict = true,
160193
insecureHTTPParser = true,
194+
timeout = 2000,
161195
}: Partial<NMOSNodeRuntimeOptions>) {
162196
super({
163197
dialect,
@@ -167,6 +201,7 @@ export class NMOSNodeAPI extends NMOSNodeRuntime {
167201
basePath,
168202
strict,
169203
insecureHTTPParser,
204+
timeout,
170205
})
171206
}
172207
}

β€Žsrc/lib/types.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type NMOSNodeRuntimeOptions = {
88
dialect: NMOSDialect
99
strict: boolean
1010
insecureHTTPParser: boolean
11+
timeout?: number
1112
}
1213

1314
export type NMOSDeviceRuntimeOptions = {

β€Žsrc/schema/is04/v1.2/index.tsβ€Ž

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import node from './zod/_node.json'
2-
import devices from './zod/_devices.json'
3-
import device from './zod/_device.json'
4-
import senders from './zod/_senders.json'
5-
import sender from './zod/_sender.json'
6-
import receivers from './zod/_receivers.json'
7-
import receiver from './zod/_receiver.json'
8-
import sources from './zod/_sources.json'
9-
import source from './zod/_source.json'
10-
import flows from './zod/_flows.json'
1+
import node from './zod/_node'
2+
import devices from './zod/_devices'
3+
import device from './zod/_device'
4+
import senders from './zod/_senders'
5+
import sender from './zod/_sender'
6+
import receivers from './zod/_receivers'
7+
import receiver from './zod/_receiver'
8+
import sources from './zod/_sources'
9+
import source from './zod/_source'
10+
import flows from './zod/_flows'
1111
import flow from './zod/_flow.json'
1212

1313
export default {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { unknown, z } from 'zod'
22
import { idPrimitive } from './_primitives'
33
import { tags } from './_propTags'
44
import { _nmosResourceBase } from './_nnosResourceBase'
5-
import _device from './_device.json'
5+
import _device from './_device'
66

77
export default z
88
.array(
File renamed without changes.

src/schema/is04/v1.2/zod/_receivers.json.ts renamed to src/schema/is04/v1.2/zod/_receivers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { _receiverBase } from './_receiverBase'
55
import { _receiverVideoCore } from './_receiverVideoCore'
66
import { _receiverAudioCore } from './_receiverAudioCore'
77
import { _receiverDataCore } from './_receiverDataCore'
8-
import _nmosReceiver from './_receiver.json'
8+
import _nmosReceiver from './_receiver'
99

1010
export default z
1111
.array(

0 commit comments

Comments
Β (0)