Skip to content

Commit 4bba806

Browse files
committed
WIP Add strict pinejs mode
Change-type: patch
1 parent ec1285a commit 4bba806

1 file changed

Lines changed: 75 additions & 4 deletions

File tree

src/index.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ export type ExpandableStringKeyOf<T extends Resource['Read']> = StringKeyOf<
2929
type ExtractExpand<T extends Resource['Read'], U extends keyof T> = NonNullable<
3030
Extract<T[U], ReadonlyArray<Resource['Read']>>[number]
3131
>;
32-
type SelectPropsOf<T extends Resource['Read'], U extends ODataOptions<T>> =
32+
type SelectPropsOf<
33+
T extends Resource['Read'],
34+
U extends ODataOptions<T> | StrictODataOptions<T>,
35+
> =
3336
U['$select'] extends ReadonlyArray<StringKeyOf<T>>
3437
? U['$select'][number]
3538
: U['$select'] extends StringKeyOf<T>
@@ -38,7 +41,7 @@ type SelectPropsOf<T extends Resource['Read'], U extends ODataOptions<T>> =
3841
Exclude<StringKeyOf<T>, ExpandPropsOf<T, U>>;
3942
type ExpandPropsOf<
4043
T extends Resource['Read'],
41-
U extends ODataOptions<T>,
44+
U extends ODataOptions<T> | StrictODataOptions<T>,
4245
> = U['$expand'] extends { [key in StringKeyOf<T>]?: any }
4346
? StringKeyOf<U['$expand']>
4447
: U['$expand'] extends ReadonlyArray<StringKeyOf<T>>
@@ -47,7 +50,7 @@ type ExpandPropsOf<
4750
never;
4851
type ExpandToResponse<
4952
T extends Resource['Read'],
50-
U extends ODataOptions<T>,
53+
U extends ODataOptions<T> | StrictODataOptions<T>,
5154
> = U['$expand'] extends { [key in StringKeyOf<T>]?: any }
5255
? {
5356
[P in keyof U['$expand']]-?: OptionsToResponse<
@@ -74,7 +77,7 @@ type Equals<X, Y> =
7477

7578
export type OptionsToResponse<
7679
T extends Resource['Read'],
77-
U extends ODataOptions<T>,
80+
U extends ODataOptions<T> | StrictODataOptions<T>,
7881
ID extends ResourceId<T> | undefined,
7982
> = U extends {
8083
$count: ODataOptions<T>['$count'];
@@ -2039,6 +2042,7 @@ export type ResourceExpand<T extends Resource['Read'] = AnyResourceObject> = {
20392042
export type BaseExpand<T extends Resource['Read'] = AnyResourceObject> =
20402043
| ExpandableStringKeyOf<T>
20412044
| ResourceExpand<T>;
2045+
20422046
export type Expand<T extends Resource['Read'] = AnyResourceObject> =
20432047
| BaseExpand<T>
20442048
| ReadonlyArray<BaseExpand<T>>;
@@ -2163,3 +2167,70 @@ export interface UpsertParams<T extends Resource = AnyResource>
21632167
resource: string;
21642168
body: Partial<T['Write']>;
21652169
}
2170+
2171+
export type StrictODataOptions<T extends Resource['Read'] = AnyResourceObject> =
2172+
Omit<ODataOptions<T>, '$select' | '$expand'> & {
2173+
$expand?: StrictExpand<T>;
2174+
} & (
2175+
| {
2176+
$count: NonNullable<ODataOptions<T>['$count']>;
2177+
// TODO: Maybe never is the better type here?
2178+
// TODO: Ask Page if it makes any sense to have $count & $select together
2179+
$select?: ODataOptions<T>['$select'];
2180+
}
2181+
| {
2182+
// TODO: Maybe never is the better type here?
2183+
$count?: undefined;
2184+
$select: NonNullable<ODataOptions<T>['$select']>;
2185+
}
2186+
);
2187+
2188+
type StrictResourceExpand<T extends Resource['Read']> = {
2189+
[K in StringKeyOf<T> as ExtractExpand<T, K> extends never
2190+
? never
2191+
: K]?: ExtractExpand<T, K> extends Resource['Read']
2192+
? StrictODataOptions<ExtractExpand<T, K>>
2193+
: ODataOptions<ExtractExpand<T, K>>;
2194+
};
2195+
2196+
// StrictExpand does not allow to $expand with a string or list of string (resources)
2197+
// instead, it enforces a resource expand with $select
2198+
type StrictExpand<T extends Resource['Read']> =
2199+
| StrictResourceExpand<T>
2200+
| ReadonlyArray<StrictResourceExpand<T>>;
2201+
2202+
type StrictParams<T extends Resource = AnyResource> = Omit<
2203+
Params<T>,
2204+
'options'
2205+
> & {
2206+
options: StrictODataOptions<T['Read']>;
2207+
};
2208+
2209+
// Forces a $select to exist for get, subscribe and prepare
2210+
export type Strict<
2211+
TClient extends PinejsClientCore<Model>,
2212+
Model extends { [key in keyof Model]: Resource } = {
2213+
[key in string]: AnyResource;
2214+
},
2215+
> = Omit<TClient, 'get' | 'clone'> & {
2216+
get<
2217+
TResource extends StringKeyOf<Model>,
2218+
TParams extends StrictParams<Model[TResource]> & {
2219+
resource: TResource;
2220+
},
2221+
>(
2222+
params: { resource: TResource } & TParams,
2223+
): Promise<
2224+
NoInfer<
2225+
OptionsToResponse<
2226+
Model[TResource]['Read'],
2227+
NonNullable<TParams['options']>,
2228+
TParams['id']
2229+
>
2230+
>
2231+
>;
2232+
clone(
2233+
params: string | ConstructorParams,
2234+
backendParams?: AnyObject,
2235+
): Strict<TClient, Model>;
2236+
};

0 commit comments

Comments
 (0)