brillout / wildcard-api

Functions as API.
MIT License
368 stars 14 forks source link

`Cannot convert a Symbol value to a string` when `console.log()`ing `this` in endpoint function #16

Closed chriscalo closed 5 years ago

chriscalo commented 5 years ago

The getting started section of the Wildcard API docs state that this will be equal to the requestProps object passed to getApiResponse().

// Node.js

const {endpoints} = require('wildcard-api');

endpoints.myFirstEndpoint = async function () {
  // The `this` object is the `requestProps` object we passed to `getApiResponse`. Because
  // the headers are set on `requestProps.headers`, we can access them over `this.headers`.
  // You can then, for example, use the headers for authentication.
  console.log('The HTTP request headers:', this.headers);

  return {msg: 'hello from my first Wildcard endpoint';
};

I tried console.log()ing this from an endpoint function:

import { endpoints } from "wildcard-api";
import { file } from "ez-file";

endpoints.greet = async function greet() {
  // The getting started section of the [Wildcard API docs][wildcard-docs] state
  // that `this` will be equal to the `requestProps` object passed to
  // `getApiResponse()`.
  //
  // [wildcard-docs]: https://github.com/reframejs/wildcard-api
  console.log(this);
  return await file("./greeting.txt");
};

Unfortunately, it blows up with the following error:

TypeError: Cannot convert a Symbol value to a string
    at RegExp.test (<anonymous>)
    at getPropString (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/wildcard-api/server/WildcardApi.js:687:23)
    at Object.get (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/wildcard-api/server/WildcardApi.js:673:28)
    at Proxy.toString (<anonymous>)
    at /Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:163189
    at /Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:188786
    at Object._s (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:197621)

    at Object.<anonymous> (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:199489)
    at Object.apply (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:199279)
    at Object.[nodejs.util.inspect.custom] (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:203874)
    at formatValue (internal/util/inspect.js:491:31)
    at inspect (internal/util/inspect.js:189:10)
    at Object.formatWithOptions (util.js:84:12)
    at Object.Console.(anonymous function) (console.js:191:15)
    at Object.log (console.js:202:31)
    at Object.ha (/Users/ccalo/Projects/goldpage-vue-express-starter/node_modules/esm/esm.js:1:203749)

See the bug-when-logging-this-in-endpoint-function branch to reproduce this error.

brillout commented 5 years ago

See https://github.com/chriscalo/goldpage-vue-express-starter/pull/2.

The need to use bind() when using Wildcard with SSR is explained here: https://github.com/reframejs/wildcard-api/blob/master/docs/ssr-auth.md#readme

As usual, let me know if something's not clear.

I'm going to answer to the rest later.

brillout commented 5 years ago

it blows up with the following error

An edge case led to this unfriendly error to be thrown. It's now fixed in the newly published version 0.5.4; the proper original error message that explains what's going on is now shown instead. I'm sorry you didn't see the proper error message — I do care about error messages that contain an explanation.

chriscalo commented 5 years ago

Thanks for the fix! šŸ‘ I'll give the a try today.

I'm sorry you didn't see the proper error message ā€” I do care about error messages that contain an explanation.

No worries, I get that these libs are still very early in their maturity. I deeply appreciate your responsiveness to these issues when they come up.

It appears that Wildcard API is already trying to set this when calling the endpoint method by using endpoint.apply(). Any idea why this isn't working? (Is it the use of Proxy? Or am I not reading this right?)

  async function runEndpoint({endpointName, endpointArgs, requestProps, isDirectCall}) {
    // ...
    const endpoint = endpointsObject[endpointName];
    // ...

    const requestProps_proxy = create_requestProps_proxy({requestProps, endpointName, isDirectCall});

    let endpointResult;
    let endpointError;

    try {
      endpointResult = await endpoint.apply(
        requestProps_proxy,
        endpointArgs,
      );
    } catch(err) {
      endpointError = err;
    }

    // ...
  }

Perhaps the more important question: is there somewhere I can put this binding logic once so I don't have to do it on every endpoint call?

brillout commented 5 years ago

You can read about bind() here. It explains why bind() is necessary when using the Wildcard client in Node.js.

Perhaps the more important question: is there somewhere I can put this binding logic once so I don't have to do it on every endpoint call?

I'm afraid not; this is inherent to SSR. You'll always have to manually provide the HTTP request information while doing SSR, no matter whether you use RPC, REST, or GraphQL.

chriscalo commented 5 years ago

I now see why the request info must be manually provided. šŸ‘ Thanks for the explanation.

brillout commented 5 years ago

You'll always have to manually provide the HTTP request information while doing SSR

That said, one thing I want to do is to have Goldpage automatically provide requestProps to Wildcard. Although there will be some edge cases where the user will still need to use bind().