@ethlete/query 5.23.0 → 5.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/fesm2022/ethlete-query.mjs +611 -202
- package/fesm2022/ethlete-query.mjs.map +1 -1
- package/lib/experimental/{bearer-auth-provider-config.d.ts → auth/bearer-auth-provider-config.d.ts} +11 -3
- package/lib/experimental/{bearer-auth-provider.d.ts → auth/bearer-auth-provider.d.ts} +1 -1
- package/lib/experimental/auth/index.d.ts +2 -0
- package/lib/experimental/gql/gql-query-creator-templates.d.ts +11 -0
- package/lib/experimental/gql/gql-query-creator.d.ts +14 -0
- package/lib/experimental/gql/gql-query-execute.d.ts +11 -0
- package/lib/experimental/gql/gql-query.d.ts +12 -0
- package/lib/experimental/gql/index.d.ts +4 -0
- package/lib/experimental/http/index.d.ts +20 -0
- package/lib/experimental/http/paged-query-stack.d.ts +149 -0
- package/lib/experimental/http/query-client-config.d.ts +45 -0
- package/lib/experimental/{query-creator-templates.d.ts → http/query-creator-templates.d.ts} +11 -1
- package/lib/experimental/http/query-creator.d.ts +73 -0
- package/lib/experimental/{query-dependencies.d.ts → http/query-dependencies.d.ts} +5 -0
- package/lib/experimental/http/query-errors.d.ts +52 -0
- package/lib/experimental/{query-execute-utils.d.ts → http/query-execute-utils.d.ts} +15 -2
- package/lib/experimental/{query-execute.d.ts → http/query-execute.d.ts} +5 -3
- package/lib/experimental/http/query-features.d.ts +120 -0
- package/lib/experimental/{query-repository.d.ts → http/query-repository.d.ts} +3 -1
- package/lib/experimental/{query-snapshot.d.ts → http/query-snapshot.d.ts} +2 -2
- package/lib/experimental/http/query-stack.d.ts +101 -0
- package/lib/experimental/{query-state.d.ts → http/query-state.d.ts} +5 -1
- package/lib/experimental/{query-utils.d.ts → http/query-utils.d.ts} +25 -15
- package/lib/experimental/{query.d.ts → http/query.d.ts} +26 -2
- package/lib/experimental/{secure-query-creator.d.ts → http/secure-query-creator.d.ts} +1 -1
- package/lib/experimental/{secure-query-execute.d.ts → http/secure-query-execute.d.ts} +2 -2
- package/lib/experimental/index.d.ts +4 -22
- package/lib/experimental/ws/index.d.ts +2 -0
- package/lib/experimental/ws/web-socket-client-config.d.ts +14 -0
- package/lib/experimental/ws/web-socket-client.d.ts +37 -0
- package/lib/experimental/ws/web-socket-errors.d.ts +7 -0
- package/lib/gql/gql.d.ts +3 -2
- package/package.json +8 -7
- package/lib/experimental/paged-query.d.ts +0 -77
- package/lib/experimental/query-client-config.d.ts +0 -18
- package/lib/experimental/query-creator.d.ts +0 -39
- package/lib/experimental/query-errors.d.ts +0 -49
- package/lib/experimental/query-features.d.ts +0 -48
- package/lib/experimental/query-stack.d.ts +0 -48
- /package/lib/experimental/{http-request.d.ts → http/http-request.d.ts} +0 -0
- /package/lib/experimental/{query-client.d.ts → http/query-client.d.ts} +0 -0
- /package/lib/experimental/{secure-query.d.ts → http/secure-query.d.ts} +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { HttpErrorResponse, HttpEvent } from '@angular/common/http';
|
|
2
|
+
import { Signal } from '@angular/core';
|
|
3
|
+
import { QueryArgs, RequestArgs, ResponseType } from './query';
|
|
4
|
+
import { QueryDependencies } from './query-dependencies';
|
|
5
|
+
import { InternalQueryExecute } from './query-execute';
|
|
6
|
+
import { QueryState } from './query-state';
|
|
7
|
+
import { ClearQueryArgs, QueryFeatureFlags } from './query-utils';
|
|
8
|
+
export declare const enum QueryFeatureType {
|
|
9
|
+
WithArgs = "withArgs",
|
|
10
|
+
WithLogging = "withLogging",
|
|
11
|
+
WithErrorHandling = "withErrorHandling",
|
|
12
|
+
WithSuccessHandling = "withSuccessHandling",
|
|
13
|
+
WithPolling = "withPolling",
|
|
14
|
+
WithAutoRefresh = "withAutoRefresh",
|
|
15
|
+
WithResponseUpdate = "withResponseUpdate"
|
|
16
|
+
}
|
|
17
|
+
export type QueryFeatureContext<TArgs extends QueryArgs> = {
|
|
18
|
+
state: QueryState<TArgs>;
|
|
19
|
+
execute: InternalQueryExecute<TArgs>;
|
|
20
|
+
deps: QueryDependencies;
|
|
21
|
+
flags: QueryFeatureFlags;
|
|
22
|
+
};
|
|
23
|
+
export type QueryFeatureFn<TArgs extends QueryArgs> = (context: QueryFeatureContext<TArgs>) => void;
|
|
24
|
+
export type QueryFeature<TArgs extends QueryArgs> = {
|
|
25
|
+
type: QueryFeatureType;
|
|
26
|
+
fn: (context: QueryFeatureContext<TArgs>) => void;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A query feature that allows you to set the arguments of the query.
|
|
30
|
+
* The arguments are read within a computed function, so you can use reactive values.
|
|
31
|
+
*
|
|
32
|
+
* To set the arguments to `null`, return the symbol `CLEAR_QUERY_ARGS`.
|
|
33
|
+
* If you instead return `null`, the arguments won't change.
|
|
34
|
+
*
|
|
35
|
+
* Changing arguments will automatically trigger a new execution of the query if it is eligible for auto execution (e.g. a GET request).
|
|
36
|
+
*/
|
|
37
|
+
export declare const withArgs: <TArgs extends QueryArgs>(args: () => NoInfer<RequestArgs<TArgs>> | ClearQueryArgs | null) => QueryFeature<TArgs>;
|
|
38
|
+
export type WithPollingFeatureOptions = {
|
|
39
|
+
/** The interval in milliseconds at which the query should be executed */
|
|
40
|
+
interval: number;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the query should be executed initially.
|
|
43
|
+
* By default, the query will be executed after the first interval.
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
executeInitially?: boolean;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* A query feature that will automatically execute the query at a given interval.
|
|
50
|
+
* The interval will be cleared when the query is destroyed.
|
|
51
|
+
* The interval will be reset when the arguments of the query change.
|
|
52
|
+
*
|
|
53
|
+
* @throws If the query is not eligible for auto execution (e.g. a POST request)
|
|
54
|
+
*/
|
|
55
|
+
export declare const withPolling: <TArgs extends QueryArgs>(options: WithPollingFeatureOptions) => QueryFeature<TArgs>;
|
|
56
|
+
export type WithLoggingFeatureOptions<TArgs extends QueryArgs> = {
|
|
57
|
+
/** A function that will be called with the latest http event */
|
|
58
|
+
logFn: (v: HttpEvent<ResponseType<TArgs>> | null) => void;
|
|
59
|
+
};
|
|
60
|
+
/** A query feature that can be used to log the latest http event */
|
|
61
|
+
export declare const withLogging: <TArgs extends QueryArgs>(options: WithLoggingFeatureOptions<TArgs>) => QueryFeature<TArgs>;
|
|
62
|
+
export type WithErrorHandlingFeatureOptions = {
|
|
63
|
+
/** A function that will be called with the latest error */
|
|
64
|
+
handler: (e: HttpErrorResponse) => void;
|
|
65
|
+
};
|
|
66
|
+
/** A query feature that can be used to handle errors */
|
|
67
|
+
export declare const withErrorHandling: <TArgs extends QueryArgs>(options: WithErrorHandlingFeatureOptions) => QueryFeature<TArgs>;
|
|
68
|
+
type WithSuccessHandlingFeatureOptions<TArgs extends QueryArgs> = {
|
|
69
|
+
/** A function that will be called with the latest response */
|
|
70
|
+
handler: (data: NonNullable<ResponseType<TArgs>>) => void;
|
|
71
|
+
};
|
|
72
|
+
/** A query feature that can be used to handle successful responses */
|
|
73
|
+
export declare const withSuccessHandling: <TArgs extends QueryArgs>(options: WithSuccessHandlingFeatureOptions<TArgs>) => QueryFeature<TArgs>;
|
|
74
|
+
export type WithAutoRefreshFeatureOptions = {
|
|
75
|
+
/** The signals that should trigger a refresh of the query */
|
|
76
|
+
onSignalChanges: Signal<unknown>[];
|
|
77
|
+
/** Whether to ignore the `onlyManualExecution` query config flag */
|
|
78
|
+
ignoreOnlyManualExecution?: boolean;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* A query feature that will automatically execute the query when any of the provided signals change
|
|
82
|
+
* @throws If the query is not eligible for auto execution (e.g. a POST request)
|
|
83
|
+
* @throws If the query has the `onlyManualExecution` query config flag set and `ignoreOnlyManualExecution` is not set
|
|
84
|
+
*/
|
|
85
|
+
export declare const withAutoRefresh: <TArgs extends QueryArgs>(options: WithAutoRefreshFeatureOptions) => QueryFeature<TArgs>;
|
|
86
|
+
export type WithResponseUpdateFeatureFnData<TArgs extends QueryArgs> = {
|
|
87
|
+
/** The current response of the query */
|
|
88
|
+
currentResponse: ResponseType<TArgs> | null;
|
|
89
|
+
};
|
|
90
|
+
export type WithResponseUpdateFeatureOptions<TArgs extends QueryArgs> = {
|
|
91
|
+
/**
|
|
92
|
+
* A function that will be called with the latest response
|
|
93
|
+
* If the function returns `null`, the response will not be updated.
|
|
94
|
+
* Otherwise, the response will be updated with the returned value.
|
|
95
|
+
* The function will be called in a reactive signal context.
|
|
96
|
+
* If the query get's executed after the response was updated, the response will be set the the fresh data received from the server.
|
|
97
|
+
*
|
|
98
|
+
* This feature is most useful in combination with web sockets where the data received from the socket might be more up-to-date than the data received previously.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* const matchEvents = mySocket.joinRoom('match-events');
|
|
102
|
+
*
|
|
103
|
+
* const myMatchQuery = getMatch(
|
|
104
|
+
* withArgs(() => ({ matchId: 1 })),
|
|
105
|
+
* withResponseUpdate(({ currentResponse }) => {
|
|
106
|
+
* const matchEvent = matchEvents();
|
|
107
|
+
*
|
|
108
|
+
* if (!matchEvent) return null;
|
|
109
|
+
*
|
|
110
|
+
* // Do some checks here. This is just a very simple example.
|
|
111
|
+
* // To apply partial updates, you can use the spread operator in combination with the current response.
|
|
112
|
+
*
|
|
113
|
+
* return matchEvent;
|
|
114
|
+
* })
|
|
115
|
+
* )
|
|
116
|
+
*/
|
|
117
|
+
updater: (data: WithResponseUpdateFeatureFnData<TArgs>) => ResponseType<TArgs> | null;
|
|
118
|
+
};
|
|
119
|
+
export declare const withResponseUpdate: <TArgs extends QueryArgs>(options: WithResponseUpdateFeatureOptions<TArgs>) => QueryFeature<TArgs>;
|
|
120
|
+
export {};
|
|
@@ -3,7 +3,7 @@ import { CreateHttpRequestClientOptions, HttpRequest } from './http-request';
|
|
|
3
3
|
import { QueryArgs, RequestArgs } from './query';
|
|
4
4
|
import { QueryClientConfig } from './query-client-config';
|
|
5
5
|
import { QueryMethod, RouteType } from './query-creator';
|
|
6
|
-
import { RunQueryExecuteOptions } from './query-execute-utils';
|
|
6
|
+
import { InternalRunQueryExecuteOptions, RunQueryExecuteOptions } from './query-execute-utils';
|
|
7
7
|
export type QueryRepositoryRequestOptions<TArgs extends QueryArgs> = {
|
|
8
8
|
/**
|
|
9
9
|
* The route of the request.
|
|
@@ -25,6 +25,8 @@ export type QueryRepositoryRequestOptions<TArgs extends QueryArgs> = {
|
|
|
25
25
|
destroyRef: DestroyRef;
|
|
26
26
|
/** Configuration on how to run the query */
|
|
27
27
|
runQueryOptions?: RunQueryExecuteOptions;
|
|
28
|
+
/** Internal options for running the query */
|
|
29
|
+
internalRunQueryOptions?: InternalRunQueryExecuteOptions;
|
|
28
30
|
};
|
|
29
31
|
export type QueryRepositoryItem<TArgs extends QueryArgs> = {
|
|
30
32
|
/** The key of the request. If the key is `false`, the request is not cached, otherwise it is. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { QueryArgs, QuerySnapshot } from './query';
|
|
2
2
|
import { QueryDependencies } from './query-dependencies';
|
|
3
|
-
import {
|
|
3
|
+
import { InternalQueryExecute } from './query-execute';
|
|
4
4
|
import { QueryState } from './query-state';
|
|
5
5
|
export type CreateQuerySnapshotOptions<TArgs extends QueryArgs> = {
|
|
6
6
|
state: QueryState<TArgs>;
|
|
7
7
|
deps: QueryDependencies;
|
|
8
|
-
execute:
|
|
8
|
+
execute: InternalQueryExecute<TArgs>;
|
|
9
9
|
};
|
|
10
10
|
export declare const createQuerySnapshotFn: <TArgs extends QueryArgs>(options: CreateQuerySnapshotOptions<TArgs>) => () => QuerySnapshot<TArgs>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { HttpErrorResponse } from '@angular/common/http';
|
|
2
|
+
import { Signal } from '@angular/core';
|
|
3
|
+
import { AnyQuery, RequestArgs, ResponseType } from './query';
|
|
4
|
+
import { AnyQueryCreator, QueryArgsOf, RunQueryCreator } from './query-creator';
|
|
5
|
+
import { QueryFeature } from './query-features';
|
|
6
|
+
export type QueryStack<TQuery extends AnyQuery, TTransform> = {
|
|
7
|
+
/** Contains all queries in the stack. */
|
|
8
|
+
queries: Signal<TQuery[]>;
|
|
9
|
+
/** Contains the last query in the stack. Useful for getting current pagination values. */
|
|
10
|
+
lastQuery: Signal<TQuery | null>;
|
|
11
|
+
/** True if any query in the stack is loading. */
|
|
12
|
+
loading: Signal<boolean>;
|
|
13
|
+
/** Contains the first error that occurred in the stack. */
|
|
14
|
+
error: Signal<HttpErrorResponse | null>;
|
|
15
|
+
/** Contains the responses of all queries in the stack. Will be `null` for queries that are loading or errored. */
|
|
16
|
+
response: Signal<TTransform>;
|
|
17
|
+
/** Executes all queries in the stack. */
|
|
18
|
+
execute: (options?: {
|
|
19
|
+
allowCache?: boolean;
|
|
20
|
+
}) => void;
|
|
21
|
+
/** Destroys all queries in the stack and empties it. This should only be used if `append` is true. */
|
|
22
|
+
clear: () => void;
|
|
23
|
+
};
|
|
24
|
+
export type AnyQueryStack = QueryStack<AnyQuery, any>;
|
|
25
|
+
export type CreateQueryStackOptions<TCreator extends AnyQueryCreator, TDeps extends () => any, TTransform = (ResponseType<QueryArgsOf<TCreator>> | null)[]> = {
|
|
26
|
+
/**
|
|
27
|
+
* The query creator function that will be used to create the query stack.
|
|
28
|
+
*/
|
|
29
|
+
queryCreator: TCreator;
|
|
30
|
+
/**
|
|
31
|
+
* The dependencies that should trigger a new query stack creation.
|
|
32
|
+
* This function can be treated like a computed function. It reacts to signal changes.
|
|
33
|
+
* The return value of this function will be passed to the `args` function.
|
|
34
|
+
*
|
|
35
|
+
* This option can be ignored if `append` is false.
|
|
36
|
+
*/
|
|
37
|
+
dependencies?: TDeps;
|
|
38
|
+
/**
|
|
39
|
+
* The features that should be used for all queries in the stack.
|
|
40
|
+
*
|
|
41
|
+
* @throws If the `withArgs` feature is used. This feature is internally used.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Due to limitations in TypeScript, you have to manually add the needed generic types if needed.
|
|
45
|
+
* features: [E.withSuccessHandling<GetPostQueryArgs>({ handler: (post) => console.log(post.title) })]
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // If typings are not needed, you can use the feature without generics.
|
|
49
|
+
* features: [E.withPolling({ interval: 5000 })]
|
|
50
|
+
*/
|
|
51
|
+
features?: QueryFeature<any>[];
|
|
52
|
+
/**
|
|
53
|
+
* The arguments to create queries with.
|
|
54
|
+
* This function can be treated like a computed function. It reacts to signal changes.
|
|
55
|
+
* If a signal changes, a new query will be created (and appended to the existing ones if `append` is true).
|
|
56
|
+
* If this function returns `null`, the args will be ignored.
|
|
57
|
+
* If this function returns an array, multiple queries will be created.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* // One query
|
|
61
|
+
* () => ({ queryParams: { postId: myId() } }),
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Multiple queries (these can of cause also be created using a loop)
|
|
65
|
+
* () => [
|
|
66
|
+
* { queryParams: { postId: myId() } },
|
|
67
|
+
* { queryParams: { postId: myOtherId() } },
|
|
68
|
+
* ],
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // One query with dependencies
|
|
72
|
+
* (deps) => ({ queryParams: { postId: myId(), limit: deps.limit } }),
|
|
73
|
+
*/
|
|
74
|
+
args: (deps: ReturnType<TDeps>) => RequestArgs<QueryArgsOf<TCreator>> | RequestArgs<QueryArgsOf<TCreator>>[] | null;
|
|
75
|
+
/**
|
|
76
|
+
* If true, new queries will be appended to the existing ones. Otherwise, existing queries will be destroyed.
|
|
77
|
+
* This should be used for things like infinite scrolling where already fetched queries should not be destroyed.
|
|
78
|
+
*/
|
|
79
|
+
append?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* If append is true, this function will be called to merge the old and new queries.
|
|
82
|
+
* Useful if you want to append the new queries in a specific order (e.g. at the beginning).
|
|
83
|
+
*/
|
|
84
|
+
appendFn?: (oldQueries: RunQueryCreator<TCreator>[], newQueries: RunQueryCreator<TCreator>[]) => {
|
|
85
|
+
/** The new queries merged with the old ones. */
|
|
86
|
+
queries: RunQueryCreator<TCreator>[];
|
|
87
|
+
/** The last query in the new queries. */
|
|
88
|
+
lastQuery: RunQueryCreator<TCreator> | null;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Transforms the responses of all queries in the stack. Useful for merging or filtering responses.
|
|
92
|
+
*/
|
|
93
|
+
transform?: (responses: ResponseType<QueryArgsOf<TCreator>>[]) => TTransform;
|
|
94
|
+
};
|
|
95
|
+
/** Transforms an array of arrays into a single array and filters out `null` values. */
|
|
96
|
+
export declare const transformArrayResponse: <T extends (unknown | null)[]>(responses: T) => NonNullable<T[0]>[];
|
|
97
|
+
/** Transforms an array of paginated responses into a single array and filters out `null` values. */
|
|
98
|
+
export declare const transformPaginatedResponse: <T extends ({
|
|
99
|
+
items: unknown[];
|
|
100
|
+
} | null)[]>(responses: T) => NonNullable<NonNullable<T[0]>["items"]>;
|
|
101
|
+
export declare const createQueryStack: <TCreator extends AnyQueryCreator, TArgs extends QueryArgsOf<TCreator>, TDeps extends () => any, TTransform = (ResponseType<TArgs> | null)[]>(options: CreateQueryStackOptions<TCreator, TDeps, TTransform>) => QueryStack<RunQueryCreator<TCreator>, TTransform>;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { HttpErrorResponse, HttpEvent } from '@angular/common/http';
|
|
2
2
|
import { WritableSignal } from '@angular/core';
|
|
3
|
-
import { HttpRequestLoadingState } from './http-request';
|
|
3
|
+
import { HttpRequest, HttpRequestLoadingState } from './http-request';
|
|
4
4
|
import { QueryArgs, RequestArgs, ResponseType } from './query';
|
|
5
5
|
export type SetupQueryStateOptions = {};
|
|
6
|
+
export type QueryStateSubtle<TArgs extends QueryArgs> = {
|
|
7
|
+
request: WritableSignal<HttpRequest<TArgs> | null>;
|
|
8
|
+
};
|
|
6
9
|
export type QueryState<TArgs extends QueryArgs> = {
|
|
7
10
|
response: WritableSignal<ResponseType<TArgs> | null>;
|
|
8
11
|
args: WritableSignal<RequestArgs<TArgs> | null>;
|
|
@@ -10,5 +13,6 @@ export type QueryState<TArgs extends QueryArgs> = {
|
|
|
10
13
|
loading: WritableSignal<HttpRequestLoadingState | null>;
|
|
11
14
|
error: WritableSignal<HttpErrorResponse | null>;
|
|
12
15
|
lastTimeExecutedAt: WritableSignal<number | null>;
|
|
16
|
+
subtle: QueryStateSubtle<TArgs>;
|
|
13
17
|
};
|
|
14
18
|
export declare const setupQueryState: <TArgs extends QueryArgs>(options: SetupQueryStateOptions) => QueryState<TArgs>;
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
|
|
2
|
-
import { CreateEffectOptions } from '@angular/core';
|
|
3
|
-
import {
|
|
2
|
+
import { CreateEffectOptions, Signal } from '@angular/core';
|
|
3
|
+
import { CreateGqlQueryOptions } from '../gql/gql-query';
|
|
4
|
+
import { GqlQueryMethod } from '../gql/gql-query-creator';
|
|
5
|
+
import { CreateQueryOptions, Query, QueryArgs, RequestArgs } from './query';
|
|
4
6
|
import { QueryMethod } from './query-creator';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import { QueryDependencies } from './query-dependencies';
|
|
8
|
+
import { InternalQueryExecute } from './query-execute';
|
|
9
|
+
import { QueryFeature, QueryFeatureContext } from './query-features';
|
|
10
|
+
import { QueryKeyOrNone } from './query-repository';
|
|
7
11
|
import { QueryState } from './query-state';
|
|
8
12
|
/**
|
|
9
|
-
* Returning this inside
|
|
13
|
+
* Returning this inside a withArgs feature will reset the query args to null.
|
|
10
14
|
* This will also pause polling and auto refresh until new args are set.
|
|
11
15
|
*/
|
|
12
|
-
export declare const
|
|
13
|
-
export type
|
|
16
|
+
export declare const CLEAR_QUERY_ARGS: unique symbol;
|
|
17
|
+
export type ClearQueryArgs = typeof CLEAR_QUERY_ARGS;
|
|
14
18
|
export declare const QUERY_EFFECT_ERROR_MESSAGE = "Effect triggered too often. This is probably due to a circular dependency inside the query.";
|
|
15
19
|
/** A angular effect that will throw an error in dev mode if it is called too often. This indicates a circular dependency inside the effect. */
|
|
16
|
-
export declare const queryEffect: (fn: () => void, errorMessage: string, options?: CreateEffectOptions) => import("@angular/core").EffectRef;
|
|
20
|
+
export declare const queryEffect: (fn: (isFirstRun: boolean) => void, errorMessage: string, options?: CreateEffectOptions) => import("@angular/core").EffectRef;
|
|
17
21
|
export declare const shouldAutoExecuteQuery: (method: QueryMethod) => method is "GET" | "HEAD" | "OPTIONS";
|
|
22
|
+
export declare const shouldAutoExecuteGqlQuery: (method: GqlQueryMethod) => method is "QUERY";
|
|
18
23
|
export declare const extractExpiresInSeconds: (headers: HttpHeaders) => number | null;
|
|
19
24
|
export type ShouldRetryRequestOptions = {
|
|
20
25
|
retryCount: number;
|
|
@@ -33,17 +38,22 @@ export type QueryFeatureFlags = {
|
|
|
33
38
|
shouldAutoExecuteMethod: boolean;
|
|
34
39
|
shouldAutoExecute: boolean;
|
|
35
40
|
hasRouteFunction: boolean;
|
|
41
|
+
onlyManualExecution?: boolean;
|
|
42
|
+
/** Human readable method name */
|
|
43
|
+
method: string;
|
|
36
44
|
};
|
|
37
|
-
export declare const getQueryFeatureUsage: <TArgs extends QueryArgs>(options: CreateQueryOptions<TArgs>) => QueryFeatureFlags;
|
|
38
|
-
export declare const applyQueryFeatures: <TArgs extends QueryArgs>(
|
|
39
|
-
export declare const maybeExecute:
|
|
45
|
+
export declare const getQueryFeatureUsage: <TArgs extends QueryArgs>(options: CreateQueryOptions<TArgs> | CreateGqlQueryOptions<TArgs>) => QueryFeatureFlags;
|
|
46
|
+
export declare const applyQueryFeatures: <TArgs extends QueryArgs>(features: QueryFeature<TArgs>[], context: QueryFeatureContext<TArgs>) => void;
|
|
47
|
+
export declare const maybeExecute: (options: {
|
|
40
48
|
flags: QueryFeatureFlags;
|
|
41
|
-
execute:
|
|
49
|
+
execute: InternalQueryExecute<any>;
|
|
42
50
|
}) => void;
|
|
43
51
|
export type CreateQueryObjectOptions<TArgs extends QueryArgs> = {
|
|
44
52
|
state: QueryState<TArgs>;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
destroy: () => void;
|
|
53
|
+
deps: QueryDependencies;
|
|
54
|
+
execute: InternalQueryExecute<TArgs>;
|
|
48
55
|
};
|
|
49
56
|
export declare const createQueryObject: <TArgs extends QueryArgs>(options: CreateQueryObjectOptions<TArgs>) => Query<TArgs>;
|
|
57
|
+
export declare const normalizeQueryRepositoryKey: (key: Signal<QueryKeyOrNone>) => Signal<string>;
|
|
58
|
+
export declare const shouldCacheQuery: (method: QueryMethod) => method is "GET" | "HEAD" | "OPTIONS";
|
|
59
|
+
export declare const buildQueryCacheKey: (route: string, args: RequestArgs<QueryArgs> | undefined) => string;
|
|
@@ -23,22 +23,46 @@ export type CreateQueryOptions<TArgs extends QueryArgs> = {
|
|
|
23
23
|
queryConfig: QueryConfig;
|
|
24
24
|
};
|
|
25
25
|
export type QueryBase<TArgs extends QueryArgs> = {
|
|
26
|
+
/** The arguments of the last execution of the query. Will be `null` if the query has never been executed */
|
|
26
27
|
args: Signal<RequestArgs<TArgs> | null>;
|
|
28
|
+
/**
|
|
29
|
+
* The latest response of the query. Will be `null` if the query has never been executed.
|
|
30
|
+
* Responses are cached until a new response is received.
|
|
31
|
+
* If a response is present but the next execution of the query fails, the response will be set to `null` again.
|
|
32
|
+
*/
|
|
27
33
|
response: Signal<ResponseType<TArgs> | null>;
|
|
34
|
+
/** The latest Angular HTTP client native http event that occurred during the last execution of the query. Will be `null` if no event occurred. */
|
|
28
35
|
latestHttpEvent: Signal<HttpEvent<ResponseType<TArgs>> | null>;
|
|
36
|
+
/** The loading state of the query. Will be `null` if the query currently isn't loading. */
|
|
29
37
|
loading: Signal<HttpRequestLoadingState | null>;
|
|
38
|
+
/** The error that occurred during the last execution of the query. Will be `null` if no error occurred. */
|
|
30
39
|
error: Signal<HttpErrorResponse | null>;
|
|
40
|
+
/** The time the query was last executed at. Will be `null` if the query has never been executed. */
|
|
31
41
|
lastTimeExecutedAt: Signal<number | null>;
|
|
32
|
-
id
|
|
42
|
+
/** The id of the query */
|
|
43
|
+
id: Signal<string>;
|
|
33
44
|
};
|
|
45
|
+
/** A snapshot of a query state at a specific point in time */
|
|
34
46
|
export type QuerySnapshot<TArgs extends QueryArgs> = QueryBase<TArgs> & {
|
|
47
|
+
/** This signal is `true` until the latest execution of the query has completed in any way (success, error, or cancellation) */
|
|
35
48
|
isAlive: Signal<boolean>;
|
|
36
49
|
};
|
|
37
50
|
export type AnyQuerySnapshot = QuerySnapshot<any>;
|
|
38
51
|
export type AnyQuery = Query<any>;
|
|
52
|
+
export type QuerySubtle<TArgs extends QueryArgs> = {
|
|
53
|
+
/** Destroys the query and cleans up all resources. The query should not be used after this method is called. */
|
|
54
|
+
destroy: () => void;
|
|
55
|
+
/** Manually sets the response of the query. This will not trigger a new execution of the query. */
|
|
56
|
+
setResponse: (response: ResponseType<TArgs>) => void;
|
|
57
|
+
};
|
|
39
58
|
export type Query<TArgs extends QueryArgs> = QueryBase<TArgs> & {
|
|
59
|
+
/** Executes the query */
|
|
40
60
|
execute: QueryExecute<TArgs>;
|
|
61
|
+
/** Creates an immutable snapshot of the current query state */
|
|
41
62
|
createSnapshot: () => QuerySnapshot<TArgs>;
|
|
42
|
-
|
|
63
|
+
/** Resets the query state to its initial state */
|
|
64
|
+
reset: () => void;
|
|
65
|
+
/** Advanced query features. **WARNING!** Incorrectly using these features will likely **BREAK** your application. You have been warned! */
|
|
66
|
+
subtle: QuerySubtle<TArgs>;
|
|
43
67
|
};
|
|
44
68
|
export declare const createQuery: <TArgs extends QueryArgs>(options: CreateQueryOptions<TArgs>) => Query<TArgs>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnyBearerAuthProviderConfig } from '
|
|
1
|
+
import { AnyBearerAuthProviderConfig } from '../auth/bearer-auth-provider-config';
|
|
2
2
|
import { QueryArgs } from './query';
|
|
3
3
|
import { CreateQueryCreatorOptions, InternalCreateQueryCreatorOptions, QueryCreator } from './query-creator';
|
|
4
4
|
export type InternalSecureCreateQueryCreatorOptions = InternalCreateQueryCreatorOptions & {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { QueryArgs } from './query';
|
|
2
|
-
import { CreateQueryExecuteOptions,
|
|
2
|
+
import { CreateQueryExecuteOptions, InternalQueryExecute } from './query-execute';
|
|
3
3
|
import { InternalSecureCreateQueryCreatorOptions } from './secure-query-creator';
|
|
4
4
|
export type CreateSecureQueryExecuteOptions<TArgs extends QueryArgs> = Omit<CreateQueryExecuteOptions<TArgs>, 'creatorInternals'> & {
|
|
5
5
|
creatorInternals: InternalSecureCreateQueryCreatorOptions;
|
|
6
6
|
};
|
|
7
|
-
export declare const createSecureExecuteFn: <TArgs extends QueryArgs>(options: CreateSecureQueryExecuteOptions<TArgs>) =>
|
|
7
|
+
export declare const createSecureExecuteFn: <TArgs extends QueryArgs>(options: CreateSecureQueryExecuteOptions<TArgs>) => InternalQueryExecute<TArgs>;
|
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './http
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './query';
|
|
6
|
-
export * from './query-client';
|
|
7
|
-
export * from './query-client-config';
|
|
8
|
-
export * from './query-creator';
|
|
9
|
-
export * from './query-creator-templates';
|
|
10
|
-
export * from './query-dependencies';
|
|
11
|
-
export * from './query-errors';
|
|
12
|
-
export * from './query-execute';
|
|
13
|
-
export * from './query-execute-utils';
|
|
14
|
-
export * from './query-features';
|
|
15
|
-
export * from './query-repository';
|
|
16
|
-
export * from './query-snapshot';
|
|
17
|
-
export * from './query-stack';
|
|
18
|
-
export * from './query-state';
|
|
19
|
-
export * from './query-utils';
|
|
20
|
-
export * from './secure-query';
|
|
21
|
-
export * from './secure-query-creator';
|
|
22
|
-
export * from './secure-query-execute';
|
|
1
|
+
export * from './auth';
|
|
2
|
+
export * from './gql';
|
|
3
|
+
export * from './http';
|
|
4
|
+
export * from './ws';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { SocketMessageView, WebSocketClient } from './web-socket-client';
|
|
3
|
+
export type CreateWebSocketClientConfig = {
|
|
4
|
+
/** A unique name for the client */
|
|
5
|
+
name: string;
|
|
6
|
+
/** The URL of the socket io server */
|
|
7
|
+
url: string;
|
|
8
|
+
};
|
|
9
|
+
export type WebSocketClientRef<TMessageData extends SocketMessageView = SocketMessageView> = InjectionToken<WebSocketClient<TMessageData>>;
|
|
10
|
+
export type WebSocketClientConfig = CreateWebSocketClientConfig & {
|
|
11
|
+
/** A generated token for dependency injection */
|
|
12
|
+
token: WebSocketClientRef;
|
|
13
|
+
};
|
|
14
|
+
export declare const createWebSocketClientConfig: (options: CreateWebSocketClientConfig) => WebSocketClientConfig;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Signal, WritableSignal } from '@angular/core';
|
|
2
|
+
import { WebSocketClientConfig } from './web-socket-client-config';
|
|
3
|
+
/** A default socket io message view */
|
|
4
|
+
export type SocketMessageView<TMessageData = unknown> = {
|
|
5
|
+
room: string;
|
|
6
|
+
event: string;
|
|
7
|
+
data: TMessageData;
|
|
8
|
+
};
|
|
9
|
+
export type WebSocketClientSubtle = {
|
|
10
|
+
/** Leave a socket io room */
|
|
11
|
+
leaveRoom: (room: string) => void;
|
|
12
|
+
};
|
|
13
|
+
export type WebSocketClient<TMessageData extends SocketMessageView> = {
|
|
14
|
+
/**
|
|
15
|
+
* Join a socket io room
|
|
16
|
+
* If a function is passed, it will be evaluated in a reactive signal context.
|
|
17
|
+
* If the function returns null, no room will be joined.
|
|
18
|
+
* If the function returns a string, the previous room will be left and the new room will be joined.
|
|
19
|
+
*/
|
|
20
|
+
joinRoom: (room: string | (() => string | null)) => Signal<WebSocketRoom<TMessageData> | null>;
|
|
21
|
+
/** Whether the client is connected to the server */
|
|
22
|
+
isConnected: Signal<boolean>;
|
|
23
|
+
/** Advanced web socket features. **WARNING!** Incorrectly using these features will likely **BREAK** your application. You have been warned! */
|
|
24
|
+
subtle: WebSocketClientSubtle;
|
|
25
|
+
};
|
|
26
|
+
export type InternalWebSocketRoom<TMessageData extends SocketMessageView> = {
|
|
27
|
+
latestMessage: WritableSignal<TMessageData | null>;
|
|
28
|
+
};
|
|
29
|
+
export type WebSocketRoom<TMessageData extends SocketMessageView> = {
|
|
30
|
+
/** The latest message received in the room */
|
|
31
|
+
latestMessage: Signal<TMessageData | null>;
|
|
32
|
+
};
|
|
33
|
+
export declare const createWebSocketClient: <TMessageData extends SocketMessageView>(config: WebSocketClientConfig) => WebSocketClient<TMessageData>;
|
|
34
|
+
export declare const provideWebSocketClient: (config: WebSocketClientConfig) => {
|
|
35
|
+
provide: import("./web-socket-client-config").WebSocketClientRef<SocketMessageView>;
|
|
36
|
+
useFactory: () => WebSocketClient<SocketMessageView<unknown>>;
|
|
37
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RuntimeError } from '@ethlete/core';
|
|
2
|
+
export declare const enum WebSocketRuntimeErrorCode {
|
|
3
|
+
ROOM_NOT_JOINED = 1000,
|
|
4
|
+
MESSAGE_MALFORMED = 1001
|
|
5
|
+
}
|
|
6
|
+
export declare const roomNotJoined: (room: string) => RuntimeError<WebSocketRuntimeErrorCode.ROOM_NOT_JOINED>;
|
|
7
|
+
export declare const messageMalformed: () => RuntimeError<WebSocketRuntimeErrorCode.MESSAGE_MALFORMED>;
|
package/lib/gql/gql.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type TransformedGqlQuery = {
|
|
2
2
|
query: string;
|
|
3
|
-
variables?: string
|
|
3
|
+
variables?: Record<string, unknown>;
|
|
4
4
|
operationName?: string;
|
|
5
5
|
};
|
|
6
|
+
export declare const transformGql: (str: string) => (variables: Record<string, unknown> | null | undefined) => TransformedGqlQuery;
|
|
6
7
|
export declare const gql: (strings: TemplateStringsArray, ...values: string[]) => string;
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethlete/query",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.25.0",
|
|
4
|
+
"sideEffects": false,
|
|
4
5
|
"peerDependencies": {
|
|
5
|
-
"@angular/common": "
|
|
6
|
-
"@angular/core": "
|
|
7
|
-
"@angular/forms": "
|
|
8
|
-
"@angular/router": "
|
|
6
|
+
"@angular/common": "19.1.4",
|
|
7
|
+
"@angular/core": "19.1.4",
|
|
8
|
+
"@angular/forms": "19.1.4",
|
|
9
|
+
"@angular/router": "19.1.4",
|
|
9
10
|
"@ethlete/core": "^4.0.3",
|
|
10
11
|
"@ethlete/types": "^1.6.2",
|
|
11
|
-
"rxjs": "
|
|
12
|
+
"rxjs": "7.8.1",
|
|
13
|
+
"socket.io-client": "4.8.1"
|
|
12
14
|
},
|
|
13
15
|
"module": "fesm2022/ethlete-query.mjs",
|
|
14
16
|
"typings": "index.d.ts",
|
|
@@ -21,7 +23,6 @@
|
|
|
21
23
|
"default": "./fesm2022/ethlete-query.mjs"
|
|
22
24
|
}
|
|
23
25
|
},
|
|
24
|
-
"sideEffects": false,
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"tslib": "^2.3.0"
|
|
27
28
|
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { ContentfulGqlLikePaginated, DynLikePaginated, GgLikePaginated, NormalizedPagination, Paginated } from '@ethlete/types';
|
|
2
|
-
import { Query, QueryArgs, RequestArgs, ResponseType } from './query';
|
|
3
|
-
import { QueryCreator } from './query-creator';
|
|
4
|
-
export declare const ethletePaginationAdapter: <T>(response: Paginated<T>) => NormalizedPagination<T>;
|
|
5
|
-
export declare const ggLikePaginationAdapter: <T>(response: GgLikePaginated<T>) => NormalizedPagination<T>;
|
|
6
|
-
export declare const dynLikePaginationAdapter: <T>(response: DynLikePaginated<T>) => NormalizedPagination<T>;
|
|
7
|
-
export declare const contentfulGqlLikePaginationAdapter: <T>(response: ContentfulGqlLikePaginated<T>) => NormalizedPagination<T>;
|
|
8
|
-
export type CreatePagedQueryOptions<TArgs extends QueryArgs> = {
|
|
9
|
-
/**
|
|
10
|
-
* The normalizer function that will be used to normalize the response to a format that the paged query can understand.
|
|
11
|
-
*
|
|
12
|
-
* There are some built-in normalizers that can be used:
|
|
13
|
-
* - `ethletePaginationAdapter`
|
|
14
|
-
* - `ggLikePaginationAdapter`
|
|
15
|
-
* - `dynLikePaginationAdapter`
|
|
16
|
-
* - `contentfulGqlLikePaginationAdapter`
|
|
17
|
-
*/
|
|
18
|
-
responseNormalizer: (response: ResponseType<TArgs>) => NormalizedPagination<ResponseType<TArgs>>;
|
|
19
|
-
/**
|
|
20
|
-
* The query creator function that will be used to create the paged query.
|
|
21
|
-
*/
|
|
22
|
-
queryCreator: QueryCreator<TArgs>;
|
|
23
|
-
/**
|
|
24
|
-
* The arguments to create the query.
|
|
25
|
-
* The current page will be passed as an argument.
|
|
26
|
-
* This function can be treated like a computed function. It reacts to signal changes.
|
|
27
|
-
* If a signal changes, the paged query will be reset to the initial page.
|
|
28
|
-
*
|
|
29
|
-
* @example (page) => ({ queryParams: { page, limit:20 } }),
|
|
30
|
-
*/
|
|
31
|
-
args: (page: number) => RequestArgs<TArgs>;
|
|
32
|
-
/**
|
|
33
|
-
* The page to start this paged query from.
|
|
34
|
-
* @default 1
|
|
35
|
-
*/
|
|
36
|
-
initialPage?: number;
|
|
37
|
-
};
|
|
38
|
-
export type PagedQueryResetOptions = {
|
|
39
|
-
/**
|
|
40
|
-
* The page to reset this paged query to.
|
|
41
|
-
* This will clear everything and start from this page.
|
|
42
|
-
* @default 1 // or the value passed in the `initialPage` option when creating the paged query.
|
|
43
|
-
*/
|
|
44
|
-
initialPage?: number;
|
|
45
|
-
};
|
|
46
|
-
export type PagedQueryExecuteOptions<TArgs extends QueryArgs> = {
|
|
47
|
-
/**
|
|
48
|
-
* If provided, only the queries that match the condition will be executed.
|
|
49
|
-
* This will also execute the previous and next query to the one that matched the condition.
|
|
50
|
-
* If not provided, all queries will be executed.
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* myPagedQuery.execute({ where: (item) => item.id === 4 });
|
|
54
|
-
*/
|
|
55
|
-
where?: (item: ResponseType<TArgs>, index: number, array: ResponseType<TArgs>[]) => boolean;
|
|
56
|
-
/**
|
|
57
|
-
* If true, the cache will be used (if not expired) and the request will not be made.
|
|
58
|
-
* @default false
|
|
59
|
-
*/
|
|
60
|
-
allowCache?: boolean;
|
|
61
|
-
};
|
|
62
|
-
export declare const createPagedQuery: <TArgs extends QueryArgs>(options: CreatePagedQueryOptions<TArgs>) => {
|
|
63
|
-
pagination: import("@angular/core").Signal<NormalizedPagination<ResponseType<TArgs>> | null>;
|
|
64
|
-
fetchPreviousPage: () => void;
|
|
65
|
-
fetchNextPage: () => void;
|
|
66
|
-
canFetchPreviousPage: import("@angular/core").Signal<boolean>;
|
|
67
|
-
canFetchNextPage: import("@angular/core").Signal<boolean>;
|
|
68
|
-
items: import("@angular/core").Signal<ResponseType<TArgs>[]>;
|
|
69
|
-
direction: import("@angular/core").Signal<"next" | "previous">;
|
|
70
|
-
loading: import("@angular/core").Signal<boolean>;
|
|
71
|
-
error: import("@angular/core").Signal<import("@angular/common/http").HttpErrorResponse | null>;
|
|
72
|
-
lastQuery: import("@angular/core").Signal<Query<TArgs> | null>;
|
|
73
|
-
isFirstLoad: import("@angular/core").Signal<boolean>;
|
|
74
|
-
queries: Query<TArgs>[];
|
|
75
|
-
reset: (resetOptions?: PagedQueryResetOptions) => void;
|
|
76
|
-
execute: (options?: PagedQueryExecuteOptions<TArgs>) => void;
|
|
77
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { HttpHeaders } from '@angular/common/http';
|
|
2
|
-
import { InjectionToken } from '@angular/core';
|
|
3
|
-
import { BuildQueryStringConfig } from '../request';
|
|
4
|
-
import { QueryClient } from './query-client';
|
|
5
|
-
import { ShouldRetryRequestFn } from './query-utils';
|
|
6
|
-
export type CacheAdapterFn = (headers: HttpHeaders) => number | null;
|
|
7
|
-
export type CreateQueryClientConfigOptions = {
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
queryString?: BuildQueryStringConfig;
|
|
10
|
-
name: string;
|
|
11
|
-
cacheAdapter?: CacheAdapterFn;
|
|
12
|
-
retryFn?: ShouldRetryRequestFn;
|
|
13
|
-
};
|
|
14
|
-
export type QueryClientConfig = CreateQueryClientConfigOptions & {
|
|
15
|
-
token: QueryClientRef;
|
|
16
|
-
};
|
|
17
|
-
export type QueryClientRef = InjectionToken<QueryClient>;
|
|
18
|
-
export declare const createQueryClientConfig: (options: CreateQueryClientConfigOptions) => QueryClientConfig;
|