Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update Node.js example to run as expected #393

Merged
merged 4 commits into from
Oct 16, 2024

Conversation

HipsterBrown
Copy link
Contributor

I'm very excited to be able to use the Viam TypeScript SDK for my Node.js projects! Thanks for all the hard work to make this integration possible @edaniels and @njooma! 👏

After running through the current documentation and example application, I ran into a few issues that I'm resolving with this PR.

@@ -1,10 +1,10 @@
# Node & Viam's TypeScript SDK
# Node.js & Viam's TypeScript SDK
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the official name "Node.js" for consistency across the documentation.


## Requirements

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.
This document assumes you already have Node.js >= version 20 installed. If not, follow the [instructions](https://nodejs.org/en/learn/getting-started/how-to-install-nodejs) provided by Node.js.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The --env-file flag was introduced in v20, so calling this out just in case some folks are running v18 which is still under long term support.


```ts
// main.ts

import wrtc = require('node-datachannel/polyfill');
const wrtc = require('node-datachannel/polyfill');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node.js supports two module formats: CommonJS (require) and ESM (import). While they can be mixed together in some programs, the expected syntax for each format is different. If we wanted to use ESM import statements it would look a little like reversed Python:

import wrtc from 'node-datachannel/polyfill';

However after updating the example code to use ESM, it appears the Viam TypeScript SDK does not have an ESM compatible module export for Node.js at the moment. So I've updated the example code to use CommonJS for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file works fine for me in Node 20 mod your API key secret fix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import wrtc = require('node-datachannel/polyfill') works in Node 20? That's quite odd since it doesn't work in the REPL:

image

Could tsc be transpiling the code to be valid?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes tsc or tsx would transpile to js since node can't run typescript.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe eslint/the community in general prefers ESM style imports in TS? At least i often see lint errors when i do const foo = require('bar')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 22 can run TypeScript with the experimental type stripping flag and would fail with the example code as is. I think we should have valid JS in the examples, even if tsc papers over the syntax errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe eslint/the community in general prefers ESM style imports in TS? At least i often see lint errors when i do const foo = require('bar')

Yes, ESM is the official standard and should be used when possible. However, the current build output of the TS SDK cannot be imported as ESM in Node.js:

image

(The above example in the REPL is using the dynamic ESM import syntax but the same error applies when running main.ts with static ESM imports)

@@ -17,7 +17,6 @@
"ts-protoc-gen": "^0.14.0",
"typescript": "^5.2.2"
},
"type": "module",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field enforces ESM for Node.js projects, which is not currently possible with the TS SDK, so removing this to run the project as CommonJS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for node 20

const wrtc = require('node-datachannel/polyfill');
const connectNode = require('@connectrpc/connect-node');

// @ts-expect-error
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required to pass the TypeScript compiler (tsc). If the project was updated to use something like tsx, it could run in a single command: tsx --env-file=.env src/main.ts

Otherwise, once Node.js v22 is more widely used, it could be run directly without the extra dependency using the type stripping feature: node --experimental-strip-types --env-file=.env src/main.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even with tsx in place, I think it's still good to call this out for anyone who decides to copy-paste it into their own app that's not using tsx.

@@ -12,7 +14,7 @@ for (const key in wrtc) {
async function connect() {
const host = process.env.HOST;
const apiKeyId = process.env.API_KEY_ID;
const apiKeySecret = process.env.API_KEY_SECRET;
const apiKeySecret = process.env.API_KEY;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README uses API_KEY in the .env file instead of API_KEY_SECRET and this naming is more consistent across the other SDK documentation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

Copy link
Contributor

@edaniels edaniels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks good to me other than a discussion for main.ts (mod api key secret fix). 20 is about a year old and 18 is EOL in 6 months. I think it'd be better to be on 20.

@HipsterBrown
Copy link
Contributor Author

I don't know why the E2E tests are failing. I ran them locally with the same result.

@edaniels
Copy link
Contributor

@HipsterBrown maybe it's best to move to tsx instead of tsc while getting node --experimental-strip-types src/main.ts to work too? Whatever gives the most compat I'm all for

@@ -116,3 +116,5 @@ docs/dist
src/api-version.ts

*.DS_Store

playwright-report/
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this since I was running the playwright tests locally.

"scripts": {
"preinstall": "make -C ../.. build",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "npx tsc && node --env-file=.env src/main.js"
"start": "tsx --env-file=.env src/main.ts"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use tsx, so no worry about waiting on the TypeScript compiler or leftover .js files.

const wrtc = require('node-datachannel/polyfill');
const connectNode = require('@connectrpc/connect-node');

// @ts-expect-error
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even with tsx in place, I think it's still good to call this out for anyone who decides to copy-paste it into their own app that's not using tsx.

@@ -7,12 +7,12 @@ test('check resource names and multiple statuses', async ({ page }) => {
const resourceNames = page
.getByTestId('resource-names')
.getByTestId('resource-name');
await expect(resourceNames).toHaveCount(4);
await expect(resourceNames).toHaveCount(3);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why the number of builtin resources is only 1 now, maybe something changed in the server implementation. It appears to be unrelated to my changes.

@HipsterBrown HipsterBrown merged commit bc7385e into main Oct 16, 2024
3 checks passed
@HipsterBrown HipsterBrown deleted the nhehr/update-node-readme branch October 16, 2024 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants