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

Version Packages #93

Merged
merged 4 commits into from Jan 10, 2023
Merged

Version Packages #93

merged 4 commits into from Jan 10, 2023

Conversation

github-actions[bot]
Copy link
Contributor

@github-actions github-actions bot commented Nov 18, 2022

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@apollo/datasource-rest@5.0.0

Major Changes

  • #89 4a249ec Thanks @trevor-scheer! - This change restores the full functionality of willSendRequest which
    previously existed in the v3 version of this package. The v4 change introduced a
    regression where the incoming request's body was no longer included in the
    object passed to the willSendRequest hook, it was always undefined.

    For consistency and typings reasons, the path argument is now the first
    argument to the willSendRequest hook, followed by the AugmentedRequest
    request object.

  • #115 be4371f Thanks @glasser! - The errorFromResponse method now receives an options object with url, request, response, and parsedBody rather than just a response, and the body has already been parsed.

  • #110 ea43a27 Thanks @trevor-scheer! - Update default cacheKeyFor to include method

    In its previous form, cacheKeyFor only used the URL to calculate the cache key. As a result, when cacheOptions.ttl was specified, the method was ignored. This could lead to surprising behavior where a POST request's response was cached and returned for a GET request (for example).

    The default cacheKeyFor now includes the request method, meaning there will now be distinct cache entries for a given URL per method.

  • #88 2c3dbd0 Thanks @glasser! - When passing params as an object, parameters with undefined values are now skipped, like with JSON.stringify. So you can write:

    getPost(query: string | undefined) {
      return this.get('post', { params: { query } });
    }

    and if query is not provided, the query parameter will be left off of the URL instead of given the value undefined.

    As part of this change, we've removed the ability to provide params in formats other than this kind of object or as an URLSearchParams object. Previously, we allowed every form of input that could be passed to new URLSearchParams(). If you were using one of the other forms (like a pre-serialized URL string or an array of two-element arrays), just pass it directly to new URLSearchParams; note that the feature of stripping undefined values will not occur in this case. For example, you can replace this.get('post', { params: [['query', query]] }) with this.get('post', { params: new URLSearchParams([['query', query]]) }). (URLSearchParams is available in Node as a global.)

  • #100 2e51657 Thanks @glasser! - Instead of memoizing GET requests forever in memory, only apply de-duplication during the lifetime of the original request. Replace the memoizeGetRequests field with a requestDeduplicationPolicyFor() method to determine how de-duplication works per request.

    To restore the surprising infinite-unconditional-cache behavior of previous versions, use this implementation of requestDeduplicationPolicyFor() (which replaces deduplicate-during-request-lifetime with deduplicate-until-invalidated):

    override protected requestDeduplicationPolicyFor(
      url: URL,
      request: RequestOptions,
    ): RequestDeduplicationPolicy {
      const cacheKey = this.cacheKeyFor(url, request);
      if (request.method === 'GET') {
        return {
          policy: 'deduplicate-until-invalidated',
          deduplicationKey: `${request.method} ${cacheKey}`,
        };
      } else {
        return {
          policy: 'do-not-deduplicate',
          invalidateDeduplicationKeys: [`GET ${cacheKey}`],
        };
      }
    }

    To restore the behavior of memoizeGetRequests = false, use this implementation of requestDeduplicationPolicyFor():

    protected override requestDeduplicationPolicyFor() {
      return { policy: 'do-not-deduplicate' } as const;
    }
  • #107 4b2a6f9 Thanks @trevor-scheer! - Remove didReceiveResponse hook

    The naming of this hook is deceiving; if this hook is overridden it becomes
    responsible for returning the parsed body and handling errors if they occur. It
    was originally introduced in
    Apollo server 2.0. - RESTDataSource access to full response obj (headers,...) apollo-server#1324, where the author
    implemented it due to lack of access to the complete response (headers) in the
    fetch methods (get, post, ...). This approach isn't a type safe way to
    accomplish this and places the burden of body parsing and error handling on the
    user.

    Removing this hook is a prerequisite to a subsequent change that will introduce
    the ability to fetch a complete response (headers included) aside from the
    provided fetch methods which only return a body. This change will reinstate the
    functionality that the author of this hook had originally intended in a more
    direct manner.

  • #95 c59b82f Thanks @glasser! - Simplify interpretation of this.baseURL so it works exactly like links in a web browser.

    If you set this.baseURL to an URL with a non-empty path component, this may change the URL that your methods talk to. Specifically:

    • Paths passed to methods such as this.get('/foo') now replace the entire URL path from this.baseURL. If you did not intend this, write this.get('foo') instead.
    • If this.baseURL has a non-empty path and does not end in a trailing slash, paths such as this.get('foo') will replace the last component of the URL path instead of adding a new component. If you did not intend this, add a trailing slash to this.baseURL.

    If you preferred the v4 semantics and do not want to make the changes described above, you can restore v4 semantics by overriding resolveURL in your subclass with the following code from v4:

    override resolveURL(path: string): ValueOrPromise<URL> {
      if (path.startsWith('/')) {
        path = path.slice(1);
      }
      const baseURL = this.baseURL;
      if (baseURL) {
        const normalizedBaseURL = baseURL.endsWith('/')
          ? baseURL
          : baseURL.concat('/');
        return new URL(path, normalizedBaseURL);
      } else {
        return new URL(path);
      }
    }

    As part of this change, it is now possible to specify URLs whose first path segment contains a colon, such as this.get('/foo:bar').

  • #121 32f8f04 Thanks @glasser! - We now write to the shared HTTP-header-sensitive cache in the background rather than before the fetch resolves. By default, errors talking to the cache are logged with console.log; override catchCacheWritePromiseErrors to customize. If you call fetch(), the result object has a httpCache.cacheWritePromise field that you can await if you want to know when the cache write ends.

Minor Changes

  • #117 0f94ad9 Thanks @renovate! - If your provided cache is created with PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation (new in @apollo/utils.keyvaluecache@2.1.0), the httpcache: prefix will not be added to cache keys.

  • #114 6ebc093 Thanks @glasser! - Allow specifying the cache key directly as a cacheKey option in the request options. This is read by the default implementation of cacheKeyFor (which is still called).

  • #106 4cbfd36 Thanks @glasser! - Previously, RESTDataSource doubled the TTL used with its shared header-sensitive cache when it may be able to use the cache entry after it goes stale because it contained the ETag header; for these cache entries, RESTDataSource can set the If-None-Match header when sending the REST request and the server can return a 304 response telling RESTDataSource to reuse the old response from its cache. Now, RESTDataSource also extends the TTL for responses with the Last-Modified header (which it can validate with If-Modified-Since).

  • #110 ea43a27 Thanks @trevor-scheer! - Provide head() HTTP helper method

    Some REST APIs make use of HEAD requests. It seems reasonable for us to provide this method as we do the others.

    It's worth noting that the API differs from the other helpers. While bodies are expected/allowed for other requests, that is explicitly not the case for HEAD requests. This method returns the request object itself rather than a parsed body so that useful information can be extracted from the headers.

  • #114 6ebc093 Thanks @glasser! - Allow specifying the options passed to new CachePolicy() via a httpCacheSemanticsCachePolicyOptions option in the request options.

  • #121 32f8f04 Thanks @glasser! - If you're using node-fetch as your Fetcher implementation (the default) and the response has header names that appear multiple times (such as Set-Cookie), then you can use the node-fetch-specific API (await myRestDataSource.fetch(url)).response.headers.raw() to see the multiple header values separately.

  • #115 be4371f Thanks @glasser! - New throwIfResponseIsError hook allows you to control whether a response should be returned or thrown as an error. Partially replaces the removed didReceiveResponse hook.

  • #116 ac767a7 Thanks @glasser! - The cacheOptions function and cacheOptionsFor method may now optionally be async.

  • #90 b66da37 Thanks @trevor-scheer! - Add a new overridable method shouldJSONSerializeBody for customizing body serialization behavior. This method should return a boolean in order to inform RESTDataSource as to whether or not it should call JSON.stringify on the request body.

  • #110 ea43a27 Thanks @trevor-scheer! - Add public fetch method

    Users previously had no well-defined way to access the complete response (i.e. for header inspection). The public API of HTTP helper methods only returned the parsed response body. A didReceiveResponse hook existed as an attempt to solve this, but its semantics weren't well-defined, nor was it a type safe approach to solving the problem.

    The new fetch method allows users to "bypass" the convenience of the HTTP helpers in order to construct their own full request and inspect the complete response themselves.

    The DataSourceFetchResult type returned by this method also contains other useful information, like a requestDeduplication field containing the request's deduplication policy and whether it was deduplicated against a previous request.

Patch Changes

  • #121 609ba1f Thanks @glasser! - When de-duplicating requests, the returned parsed body is now cloned rather than shared across duplicate requests. If you override the parseBody method, you should also override cloneParsedBody to match.

  • #105 8af22fe Thanks @glasser! - The fetch Response now consistently has a non-empty url property; previously, url was an empty string if the response was read from the HTTP cache.

  • #90 b66da37 Thanks @trevor-scheer! - Correctly identify and serialize all plain objects (like those with a null prototype)

  • #94 834401d Thanks @renovate! - Update @apollo/utils.fetcher dependency to v2.0.0

  • #89 4a249ec Thanks @trevor-scheer! - string and Buffer bodies are now correctly included on the outgoing request.
    Due to a regression in v4, they were ignored and never sent as the body.
    string and Buffer bodies are now passed through to the outgoing request
    (without being JSON stringified).

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 18, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@github-actions github-actions bot force-pushed the changeset-release/main branch 3 times, most recently from c686198 to 270aeb6 Compare November 24, 2022 00:04
@github-actions github-actions bot force-pushed the changeset-release/main branch 10 times, most recently from 8f88cbc to 46c021b Compare December 3, 2022 11:12
@github-actions github-actions bot force-pushed the changeset-release/main branch 11 times, most recently from 86897ae to 6e11700 Compare December 12, 2022 17:08
@github-actions github-actions bot force-pushed the changeset-release/main branch 5 times, most recently from 4d5b91b to 2312582 Compare December 15, 2022 00:00
@github-actions github-actions bot force-pushed the changeset-release/main branch 3 times, most recently from be35f46 to 7fcaea8 Compare December 19, 2022 23:23
@github-actions github-actions bot force-pushed the changeset-release/main branch 2 times, most recently from 4c3407a to ce782e6 Compare December 31, 2022 10:34
@glasser
Copy link
Member

glasser commented Jan 7, 2023

Note that this is reasonably ready for release but we're waiting for some vacations to wrap up :)

@github-actions github-actions bot force-pushed the changeset-release/main branch 2 times, most recently from 930c7fb to ba6923d Compare January 7, 2023 16:55
CHANGELOG.md Outdated Show resolved Hide resolved
@trevor-scheer trevor-scheer merged commit c1cee39 into main Jan 10, 2023
@trevor-scheer trevor-scheer deleted the changeset-release/main branch January 10, 2023 16:45
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.

None yet

2 participants