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 #3132

Merged
merged 1 commit into from
Jul 13, 2024
Merged

Version Packages #3132

merged 1 commit into from
Jul 13, 2024

Conversation

github-actions[bot]
Copy link
Contributor

@github-actions github-actions bot commented Jun 22, 2024

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 master, this PR will be updated.

Releases

@data-client/core@0.14.0

Minor Changes

  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: setResponseAction.payload -> setResponseAction.response

    This only affects those writing custom Managers that
    inspect SET_RESPONSE_TYPE action.payload.

    Before

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.payload);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.response);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • 96f7eb0 Thanks @ntucker! - Renamed FETCH action.meta.createdAt to fetchedAt to be consistent with other actions like
    SET_RESPONSE.

    BREAKING CHANGE: fetchAction.meta.createdAt -> fetchAction.meta.fetchedAt

  • #3138 ee509fb Thanks @ntucker! - Remove throttle from FETCH_TYPE action

    BREAKING CHANGE: action.meta.throttle -> !action.endpoint.sideEffect

  • #3143 f4cf8a4 Thanks @ntucker! - action.meta.args -> action.args

  • #3143 f4cf8a4 Thanks @ntucker! - Add actions export

    actions is a namespace for all action creators. It is typically
    preferred to use Controller's type-safe dispatch methods, as
    members of this namespace could have breaking changes in a minor release.

    import { actions, type Manager, type Middleware } from '@data-client/core';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => {
        const todo = { id: '5', title: 'my first todo' };
    
        // These do the same thing
        controller.dispatch(
          actions.createSet(Todo, { args: [{ id: todo.id }], value: todo }),
        );
        // This is simpler; type-enforced; and will only change in major versions
        controller.set(Todo, { id: todo.id }, todo);
    
        return async action => next(action);
      };
    
      cleanup() {}
    }

    BREAKING CHANGE: Removed createFetch, createSet, createSetResponse from export. Use action.createFetch instead.

  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: remove fetchAction.payload

    This only affects those writing custom Managers that
    inspect FETCH_TYPE action.fetch.

    Before

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action.fetch().then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action
              .endpoint(...action.meta.args)
              .fetch()
              .then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • #3143 f4cf8a4 Thanks @ntucker! - action.meta.key -> action.key

  • #3139 9df0f7c Thanks @ntucker! - Get rid of fetch action.meta.nm. This is not used anywhere.

Patch Changes

  • 3ffa454 Thanks @ntucker! - internal: Simplify fetchReducer code

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }
  • Updated dependencies [2ad1811, 2ad1811, 2ad1811, 2ad1811, 2ad1811, 2ad1811]:

    • @data-client/normalizr@0.14.0

@data-client/endpoint@0.14.0

Minor Changes

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }

Patch Changes

  • #3133 7bd322d Thanks @ntucker! - Validate after marking cirucular reference loops

    This should not change any behavior as validate should be deterministic so if it fails
    it will fail again and failure measure throwing which exits the whole stack.
    This improves code grouping. (And possibly cache locality improvement - though didn't check.)

@data-client/graphql@0.14.0

Minor Changes

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }

Patch Changes

@data-client/normalizr@0.14.0

Minor Changes

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change normalize() interface

    function normalize(
      schema,
      input,
      args,
      { entities, indexes, entityMeta },
      { date, expiresAt, fetchedAt },
    );

    Usage

    const { result, entities, indexes, entityMeta } = normalize(
      action.endpoint.schema,
      payload,
      action.args,
      state,
      action.meta,
    );
  • #3134 2ad1811 Thanks @ntucker! - Change denormalize() interface

    function denormalize(schema, input, entities, args);

    Usage

    const value = denormalize(endpoint.schema, input, state.entities, args);
  • #3134 2ad1811 Thanks @ntucker! - Change MemoCache methods interface

    class MemoCache {
      denormalize(schema, input, entities, args): { data; paths };
      query(schema, args, entities, indexes): data;
      buildQueryKey(schema, args, entities, indexes): normalized;
    }

@data-client/react@0.14.0

Minor Changes

  • #3146 6325384 Thanks @ntucker! - Call fetches immediately - do not wait for idle

    NetworkManager will fetch
    immediately, rather than waiting for idle. With React 18+ it is expected for
    React to better handle work with concurrent mode and batching. Due to this, it
    is not longer deemed the best performance to wait for idle and instead we should
    fetch immediately.

    IdlingNetworkManager is still available to keep the previous behavior.

Patch Changes

  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: setResponseAction.payload -> setResponseAction.response

    This only affects those writing custom Managers that
    inspect SET_RESPONSE_TYPE action.payload.

    Before

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.payload);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.response);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • #3143 f4cf8a4 Thanks @ntucker! - action.meta.args -> action.args

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: remove fetchAction.payload

    This only affects those writing custom Managers that
    inspect FETCH_TYPE action.fetch.

    Before

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action.fetch().then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action
              .endpoint(...action.meta.args)
              .fetch()
              .then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }
  • 8aabe18 Thanks @ntucker! - More robust requestIdleCallback wrapper

  • #3143 f4cf8a4 Thanks @ntucker! - action.meta.key -> action.key

  • #3139 9df0f7c Thanks @ntucker! - Get rid of fetch action.meta.nm. This is not used anywhere.

  • Updated dependencies [d225595, 96f7eb0, 3ffa454, ee509fb, f4cf8a4, f4cf8a4, 2ad1811, d225595, 2ad1811, 2ad1811, f4cf8a4, 9df0f7c]:

    • @data-client/core@0.14.0

@data-client/rest@0.14.0

Minor Changes

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize visit() interface; removing non-contextual arguments.

    /** Visits next data + schema while recurisvely normalizing */
    export interface Visit {
      (schema: any, value: any, parent: any, key: any, args: readonly any[]): any;
      creating?: boolean;
    }

    This results in a 10% normalize performance boost.

    processedEntity[key] = visit(
      processedEntity[key],
      processedEntity,
      key,
      this.schema[key],
      addEntity,
      visitedEntities,
      storeEntities,
      args,
    );
    processedEntity[key] = visit(
      this.schema[key],
      processedEntity[key],
      processedEntity,
      key,
      args,
    );

    The information needed from these arguments are provided by closing visit() around them.

  • #3134 2ad1811 Thanks @ntucker! - Change Schema.normalize interface from direct data access, to using functions like getEntity

    interface SchemaSimple {
      normalize(
        input: any,
        parent: any,
        key: any,
        args: any[],
        visit: (
          schema: any,
          value: any,
          parent: any,
          key: any,
          args: readonly any[],
        ) => any,
        addEntity: (...args: any) => any,
        getEntity: (...args: any) => any,
        checkLoop: (...args: any) => any,
      ): any;
    }

    We also add checkLoop(), which moves some logic in Entity
    to the core normalize algorithm.

    /** Returns true if a circular reference is found */
    export interface CheckLoop {
      (entityKey: string, pk: string, input: object): boolean;
    }
  • #3134 2ad1811 Thanks @ntucker! - Change Schema.denormalize unvisit to have schema argument first.

    interface SchemaSimple {
      denormalize(
        input: {},
        args: readonly any[],
        unvisit: (schema: any, input: any) => any,
      ): T;
    }

Patch Changes

@data-client/img@0.14.0

Patch Changes

@data-client/ssr@0.12.14

Patch Changes

@data-client/test@0.14.0

Patch Changes

  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: setResponseAction.payload -> setResponseAction.response

    This only affects those writing custom Managers that
    inspect SET_RESPONSE_TYPE action.payload.

    Before

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.payload);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      SET_RESPONSE_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case SET_RESPONSE_TYPE:
            console.log('Resolved with value', action.response);
            return next(action);
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • #3141 d225595 Thanks @ntucker! - BREAKING CHANGE: remove fetchAction.payload

    This only affects those writing custom Managers that
    inspect FETCH_TYPE action.fetch.

    Before

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action.fetch().then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }

    After

    import {
      FETCH_TYPE,
      type Manager,
      type Middleware,
    } from '@data-client/react';
    
    export default class MyManager implements Manager {
      getMiddleware = (): Middleware => controller => next => async action => {
        switch (action.type) {
          case FETCH_TYPE:
            // consume fetch, and print the resolution
            action
              .endpoint(...action.meta.args)
              .fetch()
              .then(response => console.log(response));
          default:
            return next(action);
        }
      };
    
      cleanup() {}
    }
  • #3134 2ad1811 Thanks @ntucker! - Expand peerdep support range to include ^0.14.0

  • 39471f5 Thanks @ntucker! - Add missing types export to @data-client/test/browser

example-benchmark@0.4.53

Patch Changes

coinbase-lite@0.0.9

Patch Changes

normalizr-github-example@0.1.36

Patch Changes

normalizr-redux-example@0.1.34

Patch Changes

normalizr-relationships@0.1.36

Patch Changes

Copy link

codecov bot commented Jun 22, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.79%. Comparing base (226823a) to head (03c2fe4).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3132   +/-   ##
=======================================
  Coverage   98.79%   98.79%           
=======================================
  Files         131      131           
  Lines        2247     2247           
  Branches      455      455           
=======================================
  Hits         2220     2220           
  Misses         16       16           
  Partials       11       11           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@github-actions github-actions bot force-pushed the changeset-release/master branch 5 times, most recently from c1f0396 to 8f14c22 Compare June 29, 2024 18:16
@github-actions github-actions bot force-pushed the changeset-release/master branch 7 times, most recently from f00a313 to 099ed35 Compare July 1, 2024 15:22
@github-actions github-actions bot force-pushed the changeset-release/master branch 3 times, most recently from 640a653 to d13a345 Compare July 1, 2024 18:11
@github-actions github-actions bot force-pushed the changeset-release/master branch 3 times, most recently from 768868e to f9799e3 Compare July 2, 2024 10:27
@github-actions github-actions bot force-pushed the changeset-release/master branch 2 times, most recently from 5342138 to 25cca20 Compare July 2, 2024 11:53
@github-actions github-actions bot force-pushed the changeset-release/master branch 4 times, most recently from b4275c4 to 8778ccb Compare July 4, 2024 13:41
@github-actions github-actions bot force-pushed the changeset-release/master branch 10 times, most recently from d7e6397 to 71597e2 Compare July 11, 2024 07:16
@github-actions github-actions bot force-pushed the changeset-release/master branch 2 times, most recently from 3672904 to 540fb78 Compare July 12, 2024 13:32
@github-actions github-actions bot force-pushed the changeset-release/master branch 3 times, most recently from 021a3dc to 03c2fe4 Compare July 13, 2024 13:56
@ntucker ntucker disabled auto-merge July 13, 2024 17:20
@ntucker ntucker added this pull request to the merge queue Jul 13, 2024
Merged via the queue into master with commit 5935ff7 Jul 13, 2024
19 checks passed
@ntucker ntucker deleted the changeset-release/master branch July 13, 2024 18:56
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

1 participant