diff --git a/packages/core-types/src/request.ts b/packages/core-types/src/request.ts index 559e4e5ffa1..8d7b7dbe64e 100644 --- a/packages/core-types/src/request.ts +++ b/packages/core-types/src/request.ts @@ -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 = 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; + /** + * options specifically intended for handlers + * to utilize to process the request + * + * @typedoc + */ + options?: Record; +}; + +export type TypedRequestInfo = Request & { /** * If provided, used instead of the AbortController auto-configured for each request by the RequestManager * @@ -301,9 +341,17 @@ export type RequestInfo = Request & { */ options?: Record; - [RequestSignature]?: RT; + [RequestSignature]: RT; }; +/** + * Extends JavaScript's native {@link Request} object with additional + * properties specific to the RequestManager's capabilities. + * + * @typedoc + */ +export type RequestInfo = UntypedRequestInfo | TypedRequestInfo; + /** * Immutable version of {@link RequestInfo}. This is what is passed to handlers. * @@ -342,3 +390,10 @@ export interface RequestContext { setStream(stream: ReadableStream | Promise): void; setResponse(response: Response | ResponseInfo | null): void; } + +export function withBrand( + request: RequestInfo +): Omit, typeof RequestSignature> & { [RequestSignature]: RT } { + // @ts-expect-error we're just adding the brand + return request; +} diff --git a/packages/core-types/src/request.type-test.ts b/packages/core-types/src/request.type-test.ts new file mode 100644 index 00000000000..32d37651cef --- /dev/null +++ b/packages/core-types/src/request.type-test.ts @@ -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( + type: TypeFromInstance, + id: string +): TypedRequestInfo> { + return withBrand({ + url: `/api/${type}/${id}`, + method: 'GET', + cacheOptions: { backgroundReload: true }, + op: 'findRecord', + }); +} + +const a = exampleFindRecord('user', '1'); +function takesUserRequest(userReq: { [RequestSignature]: SingleResourceDataDocument }) {} + +takesUserRequest(a); diff --git a/packages/request-utils/src/index.ts b/packages/request-utils/src/index.ts index b6129f2c93e..725dc1667ed 100644 --- a/packages/request-utils/src/index.ts +++ b/packages/request-utils/src/index.ts @@ -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[]); } @@ -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 {