Skip to content

Commit 59b2ba3

Browse files
authored
Add node documentation (#389)
1 parent 1f8e7f4 commit 59b2ba3

File tree

4 files changed

+213
-55
lines changed

4 files changed

+213
-55
lines changed

Node.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Node & Viam's TypeScript SDK
2+
3+
This document contains detailed instructions on including Viam in your Node project. For a runnable example, see the [examples directory](/examples/node/).
4+
5+
## Requirements
6+
7+
This document assumes you already have Node installed. If not, follow the [instructions](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) provided by Node.
8+
9+
### Dependencies
10+
11+
In addition to the Viam SDK, the following direct dependencies are requires:
12+
13+
- `@connectrpc/connect-node`
14+
- `node-datachannel`
15+
16+
You can use either Yarn or NPM to install the dependencies. This document will use NPM, but either will work.
17+
18+
`npm install @viamrobotics/sdk @connectrpc/connect-node node-datachannel`
19+
20+
### Polyfills
21+
22+
Using the SDK with Node also requires the use of some polyfills. In your application's entrypoint (`main.ts`, `index.ts`, or something similar), you will need to register those polyfills:
23+
24+
```ts
25+
// main.ts
26+
27+
import wrtc = require('node-datachannel/polyfill');
28+
for (const key in wrtc) {
29+
(global as any)[key] = (wrtc as any)[key];
30+
}
31+
```
32+
33+
### Transport
34+
35+
Communicating with your Viam machine in Node requires the use of a custom transport. In your app's entrypoint, you will also need to register the custom transport:
36+
37+
```ts
38+
// main.ts
39+
40+
import connectNode = require('@connectrpc/connect-node');
41+
globalThis.VIAM = {
42+
GRPC_TRANSPORT_FACTORY: (opts: any) =>
43+
connectNode.createGrpcTransport({ httpVersion: '2', ...opts }),
44+
};
45+
```
46+
47+
## Using the SDK
48+
49+
To use the SDK, you can use similar instructions to those found on the [documentation site](https://docs.viam.com/build/program/). Below is an example of how you could use the SDK to display a list of resources on the connected device:
50+
51+
```ts
52+
// main.ts
53+
54+
import VIAM = require('@viamrobotics/sdk');
55+
import wrtc = require('node-datachannel/polyfill');
56+
import connectNode = require('@connectrpc/connect-node');
57+
globalThis.VIAM = {
58+
GRPC_TRANSPORT_FACTORY: (opts: any) =>
59+
connectNode.createGrpcTransport({ httpVersion: '2', ...opts }),
60+
};
61+
for (const key in wrtc) {
62+
(global as any)[key] = (wrtc as any)[key];
63+
}
64+
65+
async function connect() {
66+
const host = process.env.HOST;
67+
const apiKeyId = process.env.API_KEY_ID;
68+
const apiKeySecret = process.env.API_KEY_SECRET;
69+
if (!host) {
70+
throw new Error('must set HOST env var');
71+
}
72+
if (!apiKeyId) {
73+
throw new Error('must set API_KEY_ID env var');
74+
}
75+
if (!apiKeySecret) {
76+
throw new Error('must set API_KEY_SECRET env var');
77+
}
78+
79+
const client = await VIAM.createRobotClient({
80+
host,
81+
credentials: {
82+
type: 'api-key',
83+
authEntity: apiKeyId,
84+
payload: apiKeySecret,
85+
},
86+
signalingAddress: 'https://app.viam.com:443',
87+
iceServers: [{ urls: 'stun:global.stun.twilio.com:3478' }],
88+
});
89+
90+
console.log(await client.resourceNames());
91+
}
92+
93+
connect().catch((e) => {
94+
console.error('error connecting to machine', e);
95+
});
96+
```
97+
98+
In the above example, it is assumed that certain environment variables are set (`HOST`, `API_KEY_ID`, and `API_KEY_SECRET`). You can set those in the process or have a `.env` file set them automatically. If you use a `.env.` file, be sure to exclude it from version control.
99+
100+
In your terminal, you can run:
101+
102+
`npx tsc && node --env-file=.env main.js`

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ Build and connect to robots with TypeScript
1010

1111
> **Warning**
1212
> This is a beta release of the Viam TypeScript SDK. Stability is not guaranteed. Breaking changes are likely to occur, and occur often.
13-
> TS SDK only works in a browser environment.
1413
1514
## Usage
1615

@@ -28,12 +27,16 @@ npm install @viamrobotics/sdk
2827

2928
[https://ts.viam.dev](https://ts.viam.dev/)
3029

30+
## Node
31+
32+
To use this SDK with node, read the [documentation](/Node.md) or view the [example](/examples/node/)
33+
3134
## React Native
3235

3336
To use this SDK with React Native, read the [documentation](/ReactNative.md) or view the [example](/examples/react-native/)
3437

3538
## License
3639

37-
Copyright 2022-2023 Viam Inc.
40+
Copyright 2022-2024 Viam Inc.
3841

3942
Apache 2.0 - See [LICENSE](https://github.com/viamrobotics/viam-typescript-sdk/blob/main/LICENSE) file

ReactNative.md

Lines changed: 103 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# React Native & Viam's TypeScript SDK
22

3-
Viam's React Native support is still experimental. Therefore, we've provided this document for with detailed instructions on including Viam in your React Native project.
3+
This document contains detailed instructions on including Viam in your React Native project. For an runnable example, see the [examples directory](/examples/react-native/).
44

55
## Requirements
66

@@ -11,63 +11,102 @@ This document assumes you already have a React Native project. If not, follow th
1111
1212
### Dependencies
1313

14-
You must use the latest version of Viam's TypeScript SDK, `>=0.11.0`, alongside a few other direct dependencies: `react-native-webrtc`, `react-native-url-polyfill`, and `@improbable-eng/grpc-web-react-native-transport`.
14+
You must use the latest version of Viam's TypeScript SDK, `>=0.26.1`, alongside a few other direct dependencies:
1515

16-
You can use either Yarn or NPM to install the dependencies. This document will use NPM, but either will work.
16+
- `fast-text-encoding`
17+
- `react-native-fast-encoder`
18+
- `react-native-fetch-api`
19+
- `react-native-url-polyfill`
20+
- `react-native-webrtc`
21+
- `web-streams-polyfill`
1722

18-
`npm install @viamrobotics/sdk react-native-webrtc react-native-url-polyfill @improbable-eng/grpc-web-react-native-transport`
23+
You can use either Yarn or NPM to install the dependencies. This document will use NPM, but either will work.
1924

20-
### Configuration
25+
`npm install @viamrobotics/sdk fast-text-encoding react-native-fast-encoder react-native-fetch-api react-native-url-polyfill react-native-webrtc web-streams-polyfill`
2126

22-
#### `index.js`
27+
### Polyfills
2328

24-
You will also have to update your `index.js`. These updates should be placed above all other imports or customizations.
29+
Using the SDK with React Native also requires a number of polyfills. You can find these at [polyfills.native.ts](/examples/react-native/polyfills.native.ts) and [polyfills.ts](/examples/react-native/polyfills.ts). They are also pasted in their entirety below. You can copy these directly into your application.
2530

26-
Firstly, you will have to import the URL polyfill:
31+
```ts
32+
// polyfills.native.ts
2733

28-
```js
34+
// Dervied from https://raw.githubusercontent.com/connectrpc/examples-es/refs/heads/main/react-native
35+
import TextEncoder from 'react-native-fast-encoder';
36+
// @ts-expect-error -- missing type declarations
37+
import { polyfillGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctions';
38+
// @ts-expect-error -- missing type declarations
39+
import { fetch, Headers, Request, Response } from 'react-native-fetch-api';
2940
import 'react-native-url-polyfill/auto';
41+
import { registerGlobals } from 'react-native-webrtc';
42+
import { ReadableStream } from 'web-streams-polyfill';
43+
44+
export function polyfills() {
45+
polyfillGlobal('TextDecoder', () => TextEncoder);
46+
polyfillGlobal('TextEncoder', () => TextEncoder);
47+
registerGlobals();
48+
polyfillGlobal('ReadableStream', () => ReadableStream);
49+
polyfillGlobal(
50+
'fetch',
51+
() =>
52+
(...args: Parameters<typeof window.fetch>) =>
53+
fetch(args[0], {
54+
...args[1],
55+
// Inject textStreaming: https://github.com/react-native-community/fetch/issues/15
56+
reactNative: { textStreaming: true },
57+
})
58+
);
59+
polyfillGlobal('Headers', () => Headers);
60+
polyfillGlobal('Request', () => Request);
61+
polyfillGlobal('Response', () => Response);
62+
// Polyfill async.Iterator. For some reason, the Babel presets and plugins are not doing the trick.
63+
// Code from here: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#caveats
64+
(Symbol as any).asyncIterator =
65+
Symbol.asyncIterator || Symbol.for('Symbol.asyncIterator');
66+
}
3067
```
3168

32-
Then, you have to register the React Native WebRTC globals:
69+
```ts
70+
// polyfills.ts
3371

34-
```js
35-
import { registerGlobals } from 'react-native-webrtc';
36-
registerGlobals();
72+
// From https://raw.githubusercontent.com/connectrpc/examples-es/refs/heads/main/react-native
73+
// No polyfills needed for web
74+
export function polyfills() {}
3775
```
3876

39-
Finally, you will have to update add the GRPC connection configuration:
77+
### Transport
4078

41-
```js
42-
import { ReactNativeTransport } from '@improbable-eng/grpc-web-react-native-transport';
43-
global.VIAM = {
44-
GRPC_TRANSPORT_FACTORY: ReactNativeTransport,
45-
};
46-
```
79+
Communicating with your Viam machine in React Native requires the use of a custom transport. You can find it in the examples directory at [transport.ts](/examples/react-native/transport.ts). You can copy that file as is and put it in your project's root directory (sibling to the `polyfill` files).
4780

48-
Your final `index.js` might look something like this:
81+
## Configuration
4982

50-
```js
51-
/** @format */
83+
### `App.tsx`
5284

53-
import 'react-native-url-polyfill/auto';
85+
You will also have to update your `App.tsx` to import and install the `polyfills` and update the Viam transport factory.
5486

55-
import { registerGlobals } from 'react-native-webrtc';
56-
registerGlobals();
87+
```tsx
88+
// App.tsx
5789

58-
import { ReactNativeTransport } from '@improbable-eng/grpc-web-react-native-transport';
59-
global.VIAM = {
60-
GRPC_TRANSPORT_FACTORY: ReactNativeTransport,
61-
};
90+
// React imports here
91+
// e.g.
92+
// import React, { useState } from 'react';
93+
94+
// ADD THE FOLLOWING LINES
95+
import * as VIAM from '@viamrobotics/sdk';
96+
import { polyfills } from './polyfills';
97+
polyfills();
6298

63-
import { AppRegistry } from 'react-native';
64-
import App from './App';
65-
import { name as appName } from './app.json';
99+
import { GrpcWebTransportOptions } from '@connectrpc/connect-web';
100+
import { createXHRGrpcWebTransport } from './transport';
66101

67-
AppRegistry.registerComponent(appName, () => App);
102+
globalThis.VIAM = {
103+
GRPC_TRANSPORT_FACTORY: (opts: GrpcWebTransportOptions) => {
104+
return createXHRGrpcWebTransport(opts);
105+
},
106+
};
68107
```
69108

70-
#### `metro.config.js`
109+
### `metro.config.js`
71110

72111
In addition, your `metro.config.js` file needs to be updated as well. `react-native` and `react-native-webrtc` require conflicting versions of the library `event-target-shim`. Because of that, we need to tell the Metro Bundler to package this library properly. The following is a full example of what the `metro.config.js` file could look like. If you have made any changes yourself to the bundler, yours will look different.
73112

@@ -127,8 +166,7 @@ To use the SDK, you can use similar instructions to those found on the [document
127166
```tsx
128167
// App.tsx
129168

130-
import React, { PropsWithoutRef } from 'react';
131-
import { useState } from 'react';
169+
import React, { PropsWithoutRef, useState } from 'react';
132170
import {
133171
Button,
134172
FlatList,
@@ -140,6 +178,17 @@ import {
140178
} from 'react-native';
141179

142180
import * as VIAM from '@viamrobotics/sdk';
181+
import { polyfills } from './polyfills';
182+
polyfills();
183+
184+
import { GrpcWebTransportOptions } from '@connectrpc/connect-web';
185+
import { createXHRGrpcWebTransport } from './transport';
186+
187+
globalThis.VIAM = {
188+
GRPC_TRANSPORT_FACTORY: (opts: GrpcWebTransportOptions) => {
189+
return createXHRGrpcWebTransport(opts);
190+
},
191+
};
143192

144193
type ResourceNameViewProps = PropsWithoutRef<{
145194
resourceName: VIAM.ResourceName;
@@ -163,19 +212,23 @@ function App(): React.JSX.Element {
163212
const [resourceNames, setResourceNames] = useState<VIAM.ResourceName[]>([]);
164213

165214
async function connect() {
166-
const host = 'YOUR_HOST';
167-
const client = await VIAM.createRobotClient({
168-
host,
169-
credential: {
170-
type: 'api-key',
171-
payload: 'YOUR_API_KEY',
172-
},
173-
authEntity: 'YOUR_API_KEY_ID',
174-
signalingAddress: 'https://app.viam.com:443',
175-
});
176-
setConnected(true);
177-
const rns = await client.resourceNames();
178-
setResourceNames(rns.sort((a, b) => (a.name < b.name ? -1 : 1)));
215+
const host = 'test4-main.hrsdzs2gp3.viam.cloud';
216+
try {
217+
const client = await VIAM.createRobotClient({
218+
host,
219+
credentials: {
220+
type: 'api-key',
221+
authEntity: '2f862d8c-7824-4f1f-aca1-0a9fab38506a',
222+
payload: '4ft2ch1zdxsjyj5trn4ppq4rk7crj2jc',
223+
},
224+
signalingAddress: 'https://app.viam.com:443',
225+
});
226+
setConnected(true);
227+
const rns = await client.resourceNames();
228+
setResourceNames(rns.sort((a, b) => (a.name < b.name ? -1 : 1)));
229+
} catch (error) {
230+
console.error(error);
231+
}
179232
}
180233

181234
return (

examples/react-native/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The following direct dependencies are required:
3535
- react-native-webrtc
3636
- web-streams-polyfill
3737
38-
In addition, polyfills and a custom gRPC Transport are provided at `polyfills.[native].ts` and `transport.ts` respectively.
38+
In addition, polyfills and a custom gRPC Transport are provided at `polyfills.native.ts` and `transport.ts` respectively.
3939
4040
#### `App.tsx`
4141
@@ -44,12 +44,12 @@ The `App.tsx` file was updated to include the following polyfills and updates:
4444
- Polyfills:
4545
4646
```js
47-
import { polyfills } from "./polyfills";
47+
import {polyfills} from './polyfills';
4848
polyfills();
49-
5049
```
5150
5251
- GRPC connection configuration
52+
5353
```js
5454
import { GrpcWebTransportOptions } from "@connectrpc/connect-web";
5555
import { createXHRGrpcWebTransport } from './transport';

0 commit comments

Comments
 (0)