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

chore: some minor type improvements #9615

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 63 additions & 8 deletions packages/core-types/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,53 @@ type Request = {

export type ImmutableHeaders = Headers & { clone?(): Headers; toJSON(): [string, string][] };

/**
* Extends JavaScript's native {@link Request} object with additional
* properties specific to the RequestManager's capabilities.
*
* @typedoc
*/
export type RequestInfo<T = unknown, RT = unknown> = Request & {
export type UntypedRequestInfo = Request & {
/**
* If provided, used instead of the AbortController auto-configured for each request by the RequestManager
*
* @typedoc
*/
controller?: AbortController;

/**
* @see {@link CacheOptions}
* @typedoc
*/
cacheOptions?: CacheOptions;
store?: Store;

op?: string;

/**
* The identifiers of the primary resources involved in the request
* (if any). This may be used by handlers to perform transactional
* operations on the store.
*
* @typedoc
*/
records?: StableRecordIdentifier[];

disableTestWaiter?: boolean;
/**
* data that a handler should convert into
* the query (GET) or body (POST).
*
* Note: It is recommended that builders set query params
* and body directly in most scenarios.
*
* @typedoc
*/
data?: Record<string, unknown>;
/**
* options specifically intended for handlers
* to utilize to process the request
*
* @typedoc
*/
options?: Record<string, unknown>;
};

export type TypedRequestInfo<T = unknown, RT = unknown> = Request & {
/**
* If provided, used instead of the AbortController auto-configured for each request by the RequestManager
*
Expand Down Expand Up @@ -301,9 +341,17 @@ export type RequestInfo<T = unknown, RT = unknown> = Request & {
*/
options?: Record<string, unknown>;

[RequestSignature]?: RT;
[RequestSignature]: RT;
};

/**
* Extends JavaScript's native {@link Request} object with additional
* properties specific to the RequestManager's capabilities.
*
* @typedoc
*/
export type RequestInfo<T = unknown, RT = unknown> = UntypedRequestInfo | TypedRequestInfo<T, RT>;

/**
* Immutable version of {@link RequestInfo}. This is what is passed to handlers.
*
Expand Down Expand Up @@ -342,3 +390,10 @@ export interface RequestContext {
setStream(stream: ReadableStream | Promise<ReadableStream | null>): void;
setResponse(response: Response | ResponseInfo | null): void;
}

export function withBrand<T, RT>(
request: RequestInfo<T>
): Omit<RequestInfo<T>, typeof RequestSignature> & { [RequestSignature]: RT } {
// @ts-expect-error we're just adding the brand
return request;
}
31 changes: 31 additions & 0 deletions packages/core-types/src/request.type-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { TypeFromInstance } from './record';
import type { TypedRequestInfo } from './request';
import { withBrand } from './request';
import type { SingleResourceDataDocument } from './spec/document';
import type { RequestSignature, Type } from './symbols';

type User = {
id: string;
type: string;
name: string;
friends: User[];
bestFriend: User;
[Type]: 'user';
};

function exampleFindRecord<T>(
type: TypeFromInstance<T>,
id: string
): TypedRequestInfo<T, SingleResourceDataDocument<T>> {
return withBrand({
url: `/api/${type}/${id}`,
method: 'GET',
cacheOptions: { backgroundReload: true },
op: 'findRecord',
});
}

const a = exampleFindRecord<User>('user', '1');
function takesUserRequest(userReq: { [RequestSignature]: SingleResourceDataDocument<User> }) {}

takesUserRequest(a);
2 changes: 2 additions & 0 deletions packages/request-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ export function sortQueryParams(params: QueryParamsSource, options?: QueryParams
});
}

// TODO unique includes
if ('include' in dictionaryParams) {
dictionaryParams.include = handleInclude(dictionaryParams.include as string | string[]);
}
Expand Down Expand Up @@ -560,6 +561,7 @@ export function sortQueryParams(params: QueryParamsSource, options?: QueryParams
* @return {string} A sorted query params string without the leading `?`
*/
export function buildQueryParams(params: QueryParamsSource, options?: QueryParamsSerializationOptions): string {
// TODO toString encodes commas, we don't want that.
return sortQueryParams(params, options).toString();
}
export interface CacheControlValue {
Expand Down
Loading