cloudflare
Version:
The official TypeScript library for the Cloudflare API
103 lines (93 loc) • 3.5 kB
text/typescript
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
import { BaseCloudflare, ClientOptions } from './client';
import { APIResource } from './core/resource';
import { hasOwn } from './internal/utils/values';
export type PartialCloudflare<T extends MaybeResource> = BaseCloudflare & T;
type InferClientStructure<T extends readonly (typeof APIResource)[]> =
SimplifyResources<UnionToIntersection<ResourcePath<T[number]>>> extends infer O extends MaybeResource ? O
: never;
/**
* Creates a client with a subset of the available resources to reduce
* bundle size.
* Import the resource classes you need from `cloudflare/resources/*`.
* Use the BaseResource variants if you do not need to use subresources.
*
* @example
* ```ts
* import { Accounts } from `cloudflare/resources/accounts`;
* import { createClient } from `cloudflare/tree-shakable`;
*
* const client = createClient({
* resources: [Accounts],
* });
* ```
*/
export function createClient<const T extends readonly (typeof APIResource)[]>(
options: ClientOptions & { resources: T },
): PartialCloudflare<InferClientStructure<T>> {
const client = new BaseCloudflare(options);
for (const ResourceClass of options.resources) {
const resourceInstance: APIResource = new (ResourceClass as any)(client);
let object: object = client;
for (const part of ResourceClass._key.slice(0, -1)) {
if (hasOwn(object, part)) {
object = object[part];
} else {
Object.defineProperty(object, part, {
value: (object = {}),
configurable: true,
enumerable: true,
writable: true,
});
}
}
const name = ResourceClass._key.at(-1)!;
if (!hasOwn(object, name)) {
Object.defineProperty(object, name, {
value: resourceInstance,
configurable: true,
enumerable: true,
writable: true,
});
} else {
if ((object as any)[name] instanceof APIResource) {
throw new TypeError(`Resource at ${ResourceClass._key.join('.')} already exists!`);
} else {
(object as any)[name] = Object.assign(resourceInstance, (object as any)[name]);
}
}
}
return client as any;
}
/**
* `FromDeepEntry<['a', 'b', 'c'], 'value'>` -> `{ a: { b: { c: 'value'; }; }; }`
*/
type FromDeepEntry<K extends readonly PropertyKey[], V> = K['length'] extends 1 ? { [_ in K[0]]: V } & {}
: K extends readonly [infer First extends PropertyKey, ...infer Rest extends readonly PropertyKey[]] ?
{ [_ in First]: FromDeepEntry<Rest, V> }
: never;
/**
* `ResourcePath<{ _key: ["a", "b", "c"]; new (): Instance }>` -> `{ a: { b: { c: Instance; }; }; }`
*/
type ResourcePath<T extends typeof APIResource> =
T extends any ? FromDeepEntry<T['_key'], InstanceType<T>> : never;
/**
* `UnionToIntersection<{ a: 1 } | { b: 2 }>` -> `{ a: 1 } & { b: 2 }`
*/
type UnionToIntersection<U> =
(U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
/**
* Makes the types look nicer:
* `SimplifyResources<{ a: APIResource } & { b: { c: APIResource } & { d: APIResource } }>` -> `{ a: APIResource; b: { c: APIResource; d: APIResource; }; }`
*/
type SimplifyResources<T> =
T extends APIResource ? T
: T extends object ?
{
[P in keyof T as string extends P ? never : P]: SimplifyResources<T[P]>;
}
: T;
type MaybeResource = MaybeResource_ | APIResource;
interface MaybeResource_ {
[_: string]: MaybeResource;
}