Giter Club home page Giter Club logo

ngrx-traits's People

Contributors

francobasilico avatar gabrielguerrero avatar gremlin896 avatar valeriocomo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ngrx-traits's Issues

allow disabling clear selection on filter an sort

withEntitiesSingleSelection and withEntitiesMultiSelection, currently clear the selection if a filter or a remoter sort happens, because both cloud create an invalid selection if the previously selected entities are no longer present
There are some cases where dev might not like this behaviour, so this PR is to add two flags, cleanOnFilter and clearOnRemoteSort, to both traits. These flags default to true and, when set to false, will disable this behaviour.

Refactor withEntities* store features to allow receiving the config as a factory

Refactor withEntities* store features to allow receiving the config as a factory, this will enable more dynamic configuration, like setting default sort or filter from a service or cookie
implement new withStore custom feature that will help to ease implementing this use case in our own custom features, but can also be use by devs to create their own custom store features that receive a factory that receives the store and returns the config

withEntitiesSyncToUrl

The idea of this store feature is that when added to a configuration that has withEntities and/or withEntitiesFilter and withEntitiesSort* and/or withEntities*Pagination will read from the url and update the store parameters like filter sort and page, and when the app changes the state will update the url.

Improve docs

  • Add typedCallConfig to withCalls api docs
  • Add withCalls to main signal.md
  • Add discord link to signal.md

trying to get a dumb component to work with mult-selection

new to ngrx/signals and traits so perhaps I'm missing something ;)

I was wanting to create a dumb component that uses the primeng table

So I have the store

const entity = type<SablTenant>();

export const TenantStore = signalStore(
    { providedIn: 'root' },
    withState(initialState),
    withCallStatus({ initialValue: 'loading' }),
    withEntities({ entity }),
    withEntitiesMultiSelection<SablTenant>({ entity }),
    withEntitiesSingleSelection({ entity }),

the TenantComponent

export class TenantComponent {
    store = inject(TenantStore);
    constructor() {}

and the dumb table component

export class TenantTableComponent {
    entities = input<SablTenant[]>([]);
    selected = input<SablTenant[]>([]);

    onEdit = output<SablTenant>();
    onDelete = output<SablTenant>();
    onDeleteAll = output<SablTenant[]>();
    onSelectedChange = output<SablTenant[]>();
    onNew = output();

and the HTML of the TenantComponent

<tenant-table 
            [entities]="store.entities()" 
            [selected]="store.entitiesSelected()"
            
            (onEdit)="onEdit($event)" 
            (onSelectedChange)="onSelectionChange($event)"
            (onDelete)="onDelete($event)"></tenant-table>    

the primeng table has a [(selection)]="selected()" bind which I can't get to work (Unsupported expression in a two-way bindingngtsc(-995002))

so I thought I'd try this instead

(selectionChange)="onSelectedChange.emit($event)"

which runs the onSelectionChange function in the top level TenantComponent

onSelectionChange(items: Entity[]) {
        const data = { ids: items.map((item) => item.id) };
        console.log('received', data);
        this.store.selectEntities(data);

        console.log('selected', this.store.entitiesSelected());
    }
    ```
    
    at this point, when I select an item in the table I get this
   
![Screenshot from 2024-05-15 22-59-51](https://github.com/gabrielguerrero/ngrx-traits/assets/929523/e50f05f1-08ed-4b85-af37-f24f58e30d19)
    

which is expected

however, when I deselect the item in the table I get this

![Screenshot from 2024-05-15 22-57-57](https://github.com/gabrielguerrero/ngrx-traits/assets/929523/a35cea7b-6a62-45dc-9053-61c5fd0ef81a)

and as you can see, the "store.entitiesSelected()" doesn't get cleared

I would like to know a couple of things

a) is there a way to bind the store.entitiesSelected() to a 2-way 
b) if not, what am I doing wrong with this code ;) 

many thanks

Implement typed error for withCallStatus withCalls and withEntitiesLoadingCall

Currently the error prop generated by withCallStatus withCalls and withEntitiesLoadingCall, has an unknown type, so devs are forced to create a computed if they want to get anything from the error.

  • withCallStatus will get an optional errorType prop.
  • withCallStatus and withEntitiesLoadingCall, will get a mapError optional function, that can be used to give the right type to the error or transform it before it gets stored

withCalls typedCallConfig that has a no resultProp and a call with no parameters doesnt generate the correct types

The following code should generate a property called testCallResult but it doesn't, and also damages the previous function types removing them from the store.

const Store = signalStore(
withState({ foo: 'bar' }),
withCalls((store) => ({
testCall: typedCallConfig({
call: () => {
return of(true);
},
onSuccess: (result) => {
// patchState should be able to update the store inside onSuccess
patchState(store, { foo: result });
},
onError,
}),
})),
);
As a workaround you can omit using typedCallConfig and use an object for the config but that loses the type for the result on the onSuccess method

tidy packages

Align version numbers and clear out any packages not needed

Allow factory config in withEntitiesLoadingCall

Allow an alternative way of using withEntitiesLoadingCall, that receives a factory function like with withCalls, this has the advantage of allowing us to use the store in the onSuccess and onError
example

withEntitiesLoadingCall(({ entitiesPagedRequest, entitiesFilter, se }) => ({
fetchEntities: async () => {
const res = await lastValueFrom(
inject(BranchService).getBranches({
search: entitiesFilter().search,
skip: entitiesPagedRequest().startIndex,
take: entitiesPagedRequest().size,
}),
);
return { entities: res.resultList };
},
onSuccess: ({ entities }) => {
// call the store signals.computed or methods or patchState
}
})),

Allow loadEntitiesPage to receive the pageSize

Allow loadEntitiesPage to receive the pageSize, so pagination components like angular material mat-paginator can affect be used to change the pageSize dynamically
This will affect loadEntitiesPage of withEntitiesLocalPagination and withEntitiesRemotePagination

Update docs

Ensure the docs in the markdown files are up to date with latest changes, and ensure all traits have JS docs

withCalls should optionally allow returning reactive values

Currently, withCalls will only return the first value emitted, and will then unsubscribe from the source (https://github.com/gabrielguerrero/ngrx-traits/blob/main/libs/ngrx-traits/signals/src/lib/with-calls/with-calls.ts#L258).

I have a need to return a value which can emit multiple times. I don't need loading states for each, as the value will just sometimes emit more up-to-date values. I just need the first loading state for the initial fetch.

I currently have a workaround using withMethods and withCallStatus, but it would be nicer to be able to configure (opt-in) withCalls to not limit to just 1 emitted value.

Reproduction: https://stackblitz.com/edit/stackblitz-starters-1wjxgd?file=src%2Fmain.ts

I am happy to submit a PR if this is something that you are interested in the library supporting.

The automated release is failing 🚨

🚨 The automated release from the beta branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the beta branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid publishCmd option.

The publishCmd option is required and must be a non empty String.

Your configuration for the publishCmd option is [ 'nx run affected --target=release --args="--version=${nextRelease.version}"' ].


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

if store with local sort and local filter have defaults, clearing the filter doesnt return all the items

Given a store like the following with local sort and filter, and default values for each filter and sort

 const Store = signalStore(
        withEntities({
          entity,
        }),
        withCallStatus(),
        withEntitiesLocalFilter({
          entity,
          defaultFilter: { search: '' },
          filterFn: (entity, filter) =>
            !filter?.search ||
            entity?.name.toLowerCase().includes(filter?.search.toLowerCase()),
        }),
        withEntitiesLocalSort({
          entity,
          defaultSort: { field: 'name', direction: 'asc' },
        }),
      );
      ```
      The list loads with the correct filter applied, but if you clear the filter the entities list doesnt return all results, and loses the sort order
      
      Workaround: ensure withEntitiesLocalSort is before withEntitiesLocalFilter in the store definition

merge traits

This is a place holder to find a way to best merge a set of traits into one
Possible examples

export const traits = createEntityFeatureFactory(
  {
     products: [
       addLoadEntities<Product>(),
      addSingleSelection<Product>(),
     addSort<Product>()
  ],
   orders: [
       addLoadEntities<Order>(),
      addSingleSelection<Order>(),
     addSort<Order>()
  ]
  }
);

Another possible way

export const traits = createEntityFeatureFactory(
....
   addProperty('products', addLoadEntities<Product>(),
      addSingleSelection<Product>(),
     addSort<Product>()),    
addProperty('orders',  addLoadEntities<Order>(),
      addSingleSelection<Order>(),
     addSort<Order>())

First one I think is easier to implement , second one is harder but more flexible so might be more useful, there are state shapes that the second can do but not the first

Multiple withEntities and withEntitiesLocalFilter breaks signalStoreFeature

When creating a reusable signalStoreFeature and adding multiple withEntities, If I need to use a withEntitiesLocalFilter for one of the entities, signalStoreFeature is broken.

example that doesn't work:

const entity = type<Product>();
const collection1 = 'product';

const entity2 = type<{ otherField: boolean }>();
const collection2 = 'product2';

const withFeature = () =>
  signalStoreFeature(
    withEntities({ entity, collection: collection1 }),
    withEntities({ entity: entity2, collection: collection2 }),
    withEntitiesLocalFilter({
      entity,
      collection: collection1,
      defaultFilter: { test: 'test' },
      defaultDebounce: 0,
      filterFn: (entity, filter) => true,
    })
  );

if I move the withEntitiesLocalFilter next to the corresponding withEntities it works:

const entity = type<Product>();
const collection1 = 'product';

const entity2 = type<{ otherField: boolean }>();
const collection2 = 'product2';

const withFeature = () =>
signalStoreFeature(
  withEntities({ entity, collection: collection1 }),
  withEntitiesLocalFilter({
    entity,
    collection: collection1,
    defaultFilter: { test: 'test' },
    defaultDebounce: 0,
    filterFn: (entity, filter) => true,
  })
  withEntities({ entity: entity2, collection: collection2 }),
 
);

withInputBindings

New experimental store feature to sync component multiple input params to the store

  const Store = signalStore(
    withInputBindings({
      pageIndex: 0,
      length: 0,
      pageSize: 10,
      pageSizeOptions: [5, 10, 20],
    }),
  );

  class PaginatorComponent {
    readonly pageIndex = signal(3);
    readonly length = signal(100);
    readonly pageSize = signal(10);
    readonly pageSizeOptions = signal([5, 10, 20]);
    constructor(private store: any) {
      this.store.bindInputs({
        pageIndex: this.pageIndex,
        length: this.length,
        pageSize: this.pageSize,
        pageSizeOptions: this.pageSizeOptions,
      });
    }
  }

WithCalls store every result in the state

WithCalls feature is great for making the request and tracking status, errors and result.

WithCalls allows me to use onSuccess to manipulate the result But what if I don't want to store the whole result of the call?

Is there any way I can ignore storing the result and just get the benefit of the tracking status/errors?

withCalls(
    (store, dataService = inject(WebCoreDataAccessService), downloadService = inject(FileDownloaderService)) => ({
      downloadInvoice: {
        call: ({ id, fileName }: { id: string; fileName: string }) => {
          downloadService.downloadFile(`${environment.api}/invoicing/${id}`, fileName);
          return of(true);
        },

        mapPipe: 'switchMap',
      },
    }),
  ),

In this example downloadInvoice is an operation that doesn't generate result

Remote Pagination bug when last page has only 1 item

There is a bug in withEntitiesRemotePagination , that makes the last page not render if it has only one item
Example of a case that produces the error

   const Store = signalStore(
  withEntities({ entity, ollection: productsCollection }),
  withCallStatus({ ollection: productsCollection }),
  withEntitiesRemotePagination({
    entity,
    ollection: productsCollection,
    pageSize: 10,
    pagesToCache: 1,
  }),
  withEntitiesLoadingCall(
    ({ productsPagedRequest, productsFilter, productsSort }) => ({
      collection: productsCollection,
      fetchEntities: async () => {
        const res = await lastValueFrom(
          inject(ProductService).getProducts({
            search: productsFilter().search,
            skip: productsPagedRequest().startIndex,
            take: productsPagedRequest().size,
            sortAscending: productsSort().direction === "asc",
            sortColumn: productsSort().field,
          }),
        );
        return { entities: res.resultList, total: res.total };
      },
      mapError: (error) => (error as Error).message,
    }),
  ),
);


withCalls methods should be restricted to only have up to one param

In withCalls config, we should restrict the param of the function to only have one param, this is because we transform the function inside to an rxMethod which can only take one param, if the users need multiple params they should do it by making the first param an object with multiple props

Allow withCall onSuccess to receive method params

Implement changes to allow the onSuccess and onError handlers of the withCalls to receive the params used in the call

const Store = signalStore(
          withState({ foo: 'bar' }),
          withState({ ok: false }),
          withCalls((store) => ({
            testCall: typedCallConfig({
              call: ({ ok }: { ok: boolean }) => {
                return ok
                  ? apiResponse
                  : apiResponse.pipe(
                      tap(() => throwError(() => new Error('fail'))),
                    );
              },
              resultProp: 'baz',
              onSuccess: (result, { ok }) => { // second param is the params of the call
                // patchState should be able to update the store inside onSuccess
                patchState(store, { foo: result, ok });
              },
              onError,
            }),
          })),
        );
        ```

The automated release is failing 🚨

🚨 The automated release from the 16.x branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the 16.x branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here are some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


The release 16.0.0 on branch 16.x cannot be published as it is out of range.

Based on the releases published on other branches, only versions within the range >=16.0.0 <16.0.0-beta.1 can be published from branch 16.x.

The following commits are responsible for the invalid release:

  • ci(build.yaml): support N.x branches to patch previous release (f96bda7)
  • fix(package.json): fix commons and core dependencies to require angular and ngrx 16 (30db9da)
  • build(packaga.json): migration to nx 16 angular 16 and ngrx 16 (4238bc6)
  • fix(example-app): Remove dependencies to deprecated @angular/flex-layout (9b3363d)

Those commits should be moved to a valid branch with git merge or git cherry-pick and removed from branch 16.x with git revert or git reset.

A valid branch could be main or next.

See the workflow configuration documentation for more details.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

withCalls typedCallConfig that has a resultProp doesnt generate the correct type with the prop

The following code should generate a property called baz but it doesnt

const Store = signalStore(
          withState({ foo: 'bar' }),
          withCalls((store) => ({
            testCall: typedCallConfig({
              call: ({ ok }: { ok: boolean }) => {
                return ok
                  ? apiResponse
                  : apiResponse.pipe(
                      tap(() => throwError(() => new Error('fail'))),
                    );
              },
              resultProp: 'baz', // <--  store result in baz property 
              onSuccess: (result) => {
                // patchState should be able to update the store inside onSuccess
                patchState(store, { foo: result });
              },
              onError,
            }),
          })),
        );

As a workaround you can omit using typedCallConfig and use an object for the config but that loses the type for the result on the onSuccess method

not able to create custom store features with generic that use withEntities

Currently we can not create a custom store features with generics that use entity and collection pass to the withEntities* for example

export function withEntityMethods<
    Entity extends { id: string | number },
    Collection extends string ,
>(
    entity: Entity,
    collection: Collection,
    fetchEntities: () => Observable<{ entities: Entity[]; total: number }>,
) {
  return signalStoreFeature(
      withEntities({ entity, collection }),
      withCallStatus({ initialValue: 'loading', collection: collection }),
      withEntitiesLocalPagination({ pageSize: 10, entity, collection }),
      withEntitiesLoadingCall({ collection, fetchEntities }),
      withStateLogger({ name: collection })
  );
}

We get the following error

Type 'Omit<NamedEntitySignals<Entity, Collection>, FeatureResultKeys<{ state: NamedCallStatusState<Collection>; signals: NamedCallStatusComputed<...>; methods: NamedCallStatusMethods<...>; }>> & { [K in Collection as `is${Capitalize<string & K>}Loading`]: Signal<...>; } & { [K in Collection as `is${Capitalize<string & K>}...' is not assignable to type 'NamedEntitySignals<Entity, Collection>'.

After a lot of investigation this is cause by the way the types are merged in ngrx-signals

type MergeTwoFeatureResults<First extends SignalStoreFeatureResult, Second extends SignalStoreFeatureResult> = {
    state: Omit<First['state'], FeatureResultKeys<Second>>;
    signals: Omit<First['signals'], FeatureResultKeys<Second>>;
    methods: Omit<First['methods'], FeatureResultKeys<Second>>;
} & Second;

This is use to combine to SignalStoreFeatures and if First and Second have the same props the Second will override the First;

The following could fix the issue but it has the problem that if there is two signalstore with the same prop types, the generate prop will have both types the First and Second in an or

type MergeTwoFeatureResults<First extends SignalStoreFeatureResult, Second extends SignalStoreFeatureResult> = First & Second; 

The way is currently done doesnt work I beleive because of the following bug in typescript
microsoft/TypeScript#28884 (comment)

The basic problem is if we have two types First and Second are merge them using the following to override props

type Combine<First,Second> = Omit<First>, keyof Second>& Second;

Then you can not cast the result to First even though it should work

Small duplication of the problem

export type EntityState<Entity> = {
   entityMap: Record<string | number, Entity>;
   ids: string | number[];
};
export type NamedEntityState<Entity, Collection extends string> = {
   [K in keyof EntityState<Entity> as `${Collection}${Capitalize<K>}`]: EntityState<Entity>[K];
};
export type NamedCallStatusState<Prop extends string> = {
   [K in Prop as `${K}CallStatus`]: 'init' | 'loading' | 'loaded';
};


export function withEntityMethods<
 Entity extends { id: string | number },
 const Collection extends string,
>(
 entity: Entity,
 collection: Collection) {

 type Combine =
   Omit<NamedEntityState<Entity, Collection>, keyof NamedCallStatusState<Collection>>
   & NamedCallStatusState<Collection>;

// fails with: Type 'Combine' is not assignable to type 'NamedEntityState<Entity, Collection>'.
 let y: NamedEntityState<Entity, Collection> = {} as unknown as Combine;
// workaround use any
let y2: NamedEntityState<Entity, any> = {} as unknown as Combine;

  
 // next works
 type Combine2 =
   Omit<NamedEntityState<Entity, 'apps'>, keyof NamedCallStatusState<'apps'>>
   & NamedCallStatusState<'apps'>

The only way I manage to work around this is using // @ts-ignore and a any

export function withEntityMethods<
   Entity extends { id: string | number },
   Collection extends string ,
>(
   entity: Entity,
   collection: Collection,
   fetchEntities: () => Observable<{ entities: Entity[]; total: number }>,
) {
 // @ts-ignore
 return signalStoreFeature(
     withEntities({ entity, collection }),
     withCallStatus({ initialValue: 'loading', collection: collection }),
     withEntitiesLocalPagination({ pageSize: 10, entity, collection }),
     withEntitiesLoadingCall({ collection, fetchEntities: fetchEntities as any }),
     withStateLogger({ name: collection })
 );
}

There is another way is to use more any of the in the types withEntities* like

export function withEntitiesLocalPagination<
  Entity extends { id: string | number },
  Collection extends string,
>(config: {
  pageSize?: number;
  currentPage?: number;
  entity: Entity;
  collection?: Collection;
}): SignalStoreFeature<
  {
    state: NamedEntityState<Entity, any>; 
    signals: NamedEntitySignals<Entity, any>;  // <--
    methods: {};
  },
  {
    state: NamedEntitiesPaginationLocalState<Collection>;
    signals: NamedEntitiesPaginationLocalComputed<Entity, Collection>;
    methods: NamedEntitiesPaginationLocalMethods<Collection>;
  }
>;

But this will affect the other normal cases , because it will not error when a trait has a dependency missing like withEntitiesLocalPagination will not do a compile error if withEntities is not there , so we will depend on throwing runtime errors to indicate if a dependency is missing but I dont want to go that route, because devs could introduce errors that are only visible when running the app.

I will keep investigating options

page size change on the same page stops working after 2 change

Steps to reproduce

  • Create a store with withEntitiesRemotePagination and material pagination that has a page size switch of [5, 10 , 15 , 20] with default on 10
  • Load the page on default page size of 10
  • Change page size to 5
  • Switch back the page size to 10

Notice the list doesn't change

Improvement - FilterEntities, SortEntities, LoadEntitiesPage should allow to only change the state

Allowing these functions to only change the state gives the flexibility to update the state and trigger the entitiesLoading when desired.

Example: PRIMENG lazy table, emits a single event that contains all sorting, filter and page info.

proposal:

store.filterEntities({filter: ''}, {triggerLoading: false});
store.sortEntities({sort: {} }, {triggerLoading: false});
store.loadEntitiesPage({pageIndex, pageSize}, {triggerLoading: false});

withRouteParams

New withRouteParams store feature, to ease reading route params example

const ProductDetailStore = signalStore(
  withRouteParams(({ id }) => ({ id })),
  withCalls(() => ({
    loadProductDetail: (id: string) =>
      inject(ProductService).getProductDetail(id),
  })),
  withHooks(({ loadProductDetail, id }) => ({
    onInit: () => {
      loadProductDetail(id());
    },
  })),
);

withRouteParams receives a function that receives router params it must the return and object, each props will become computed in the store

storeEntity trait

The goal of this trait is to create actions that store a value in a property of the store, and a selector to read it, something like

addStoreEntity({
        entityName: 'client',
        actionProps: props<{ id: string , name: string}>(),
      })

and that will generate
actions.storeClient({client: {id: '123', name: 'Gabs'}})
selectors.selectClient()

It will not need success and fail because its local stored, also the name could be addSetEntity with the action like set* instead of store

WithCalls - OnSuccess function doesn't have the correct types

When using the WithCalls and adding an onSuccess callback to action based on the result, the function doesn't recognized the type

Is it possible to have the type of the callback defined on call:?

  sendInvoiceToShipper: {
        call: () => dataService.action({ id: id() as string }),

        onSuccess: (result) => { <-------- result: any
         
          if (result.data) {
            console.log(result.data)
          }
        },
        onError: (error) => {
        },
        mapPipe: 'switchMap',
        storeResult: false,
      },

Error in generated typescript definitions

In the @ngrx-traits/signals package, the with-state-logger and with-sync-to-web-storage files are generating type definitions that fail to compile.

This can be seen here: https://stackblitz.com/edit/ngrx-signal-store-starter-7bcgrp?file=node_modules%2F%40ngrx-traits%2Fsignals%2Flib%2Fwith-sync-to-web-storage%2Fwith-sync-to-web-storage.d.ts

I'm not sure why this still is able to run, but if you right click on withSyncToWebStorage in the imports and view the definitions, you will se the error. In my personal project I can't even get it to run if I import any functions at all from @ngrx-traits/signals, even if I don't use them.

The generated definition file is something like this:

export declare function withSyncToWebStorage<Input extends SignalStoreFeatureResult>({ key, type: storageType, saveStateChangesAfterMs, restoreOnInit, filterState, onRestore, }: {
    key: string;
    type: 'session' | 'local';
    restoreOnInit?: boolean;
    saveStateChangesAfterMs?: number;
    filterState?: (state: Input['state']) => Partial<Input['state']>;
    onRestore?: (store: Prettify<SignalStoreSlices<Input['state']> & Input['signals'] & Input['methods'] & StateSignal<Prettify<Input['state']>>>) => void;
}): import("@ngrx/signals").SignalStoreFeature<import("@ngrx/signals/src/signal-store-models").EmptyFeatureResult & Input extends infer T ? { [K in keyof T]: (import("@ngrx/signals/src/signal-store-models").EmptyFeatureResult & Input)[K]; } : never, {
    state: Omit<Omit<{}, "saveToStorage" | "loadFromStorage" | "clearFromStore">, never>;
    signals: Omit<Omit<{}, "saveToStorage" | "loadFromStorage" | "clearFromStore">, never>;
    methods: Omit<Omit<{}, "saveToStorage" | "loadFromStorage" | "clearFromStore"> & {
        saveToStorage(): void;
        loadFromStorage(): boolean;
        clearFromStore(): void;
    }, never>;
} & import("@ngrx/signals/src/signal-store-models").EmptyFeatureResult>;

With the error

Type 'EmptyFeatureResult & Input extends infer T ? { [K in keyof T]: (EmptyFeatureResult & Input)[K]; } : never' does not satisfy the constraint 'SignalStoreFeatureResult'.
  Type '{}' is missing the following properties from type 'SignalStoreFeatureResult': state, signals, methods(2344)

withCalls typedCallsConfig call losses param in "strictNullChecks": false

After the last 17.4.0 when in "strictNullChecks": false, the following code generates a method with no params

export const UserStore = signalStore(
{ providedIn: 'root' },
withState(() => initialState),
withCalls((state) => {
return {
deleteUser: typedCallConfig({
call: ({ id }: { id: string }) => {
console.log(id);
return of('');
},
storeResult: false,
onSuccess: (result, s) => {},
onError: (error) => {},
}),
};
}),
);
const store = new UserStore();
store.deleteUser({ id: '1' }); // <--- error method has no params

Package is incompatible with jest

The following error is received when a test imports anything from ngrx-traits

FAIL  
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     β€’ If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     β€’ To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     β€’ If you need a custom transformation specify a "transform" option in your config.
     β€’ If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    ../node_modules/ngrx-traits/ngrx-traits.d.ts:5
    export * from './public_api';
    ^^^^^^

    SyntaxError: Unexpected token 'export'

    > 1 | import { createEntityFeatureFactory } from 'ngrx-traits';
        | ^

      at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1479:14)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.