API Docs for: 5.4.0-alpha.70+386b38ef
Show:

File: ../packages/core-types/src/record.ts

/*
 * @module @warp-drive/core-types
 */
import type { ResourceType } from './symbols';

/**
 * Records may be anything, They don't even
 * have to be objects.
 *
 * Whatever they are, if they have a ResourceType
 * property, that property will be used by EmberData
 * and WarpDrive to provide better type safety and
 * intellisense.
 *
 * @class TypedRecordInstance
 * @typedoc
 */
export interface TypedRecordInstance {
  /**
   * The type of the resource.
   *
   * This is an optional feature that can be used by
   * record implementations to provide a typescript
   * hint for the type of the resource.
   *
   * When used, EmberData and WarpDrive APIs can
   * take advantage of this to provide better type
   * safety and intellisense.
   *
   * @property {ResourceType} [ResourceType]
   * @type {string}
   * @typedoc
   */
  [ResourceType]: string;
}

/**
 * A type utility that extracts the ResourceType if available,
 * otherwise it returns never.
 *
 * @typedoc
 */
export type TypeFromInstance<T> = T extends TypedRecordInstance ? T[typeof ResourceType] : never;

/**
 * A type utility that extracts the ResourceType if available,
 * otherwise it returns string
 *
 * @typedoc
 */
export type TypeFromInstanceOrString<T> = T extends TypedRecordInstance ? T[typeof ResourceType] : string;

type IsUniqueSymbol<T> = T extends `___(unique) Symbol(${string})` ? true : false;
type Unpacked<T> = T extends (infer U)[] ? U : T;
type NONE = { __NONE: never };

type __InternalExtract<
  MAX_DEPTH extends _DEPTHCOUNT,
  T extends TypedRecordInstance,
  V extends TypedRecordInstance,
  IncludePrefix extends boolean,
  Ignore,
  Pre extends string,
  DEPTH extends _DEPTHCOUNT,
> =
  // if we extend T, we return the leaf value
  V extends T
    ? IncludePrefix extends false
      ? V[typeof ResourceType]
      : Pre
    : // else if we are in Ignore we add the lead and exit
      V extends Ignore
      ? IncludePrefix extends false
        ? V[typeof ResourceType]
        : Pre
      : // else if we are at max depth, we return never
        IS_MAX_DEPTH<DEPTH, MAX_DEPTH> extends true
        ? Pre
        : // else add T to Ignore and recurse
          ExtractUnion<MAX_DEPTH, V, IncludePrefix, Ignore | T, Pre, INC_DEPTH<DEPTH>>;

type __ExtractIfRecord<
  MAX_DEPTH extends _DEPTHCOUNT,
  T extends TypedRecordInstance,
  V,
  IncludePrefix extends boolean,
  Ignore,
  Pre extends string,
  DEPTH extends _DEPTHCOUNT,
> = V extends TypedRecordInstance ? __InternalExtract<MAX_DEPTH, T, V, IncludePrefix, Ignore, Pre, DEPTH> : never;

type _ExtractUnion<
  MAX_DEPTH extends _DEPTHCOUNT,
  T extends TypedRecordInstance,
  IncludePrefix extends boolean,
  Ignore,
  Pre,
  DEPTH extends _DEPTHCOUNT,
> = {
  // for each string key in the record,
  [K in keyof T]: IsUniqueSymbol<K> extends true
    ? never
    : K extends string
      ? // we recursively extract any values that resolve to a TypedRecordInstance
        __ExtractIfRecord<
          MAX_DEPTH,
          T,
          Unpacked<Awaited<T[K]>>,
          IncludePrefix,
          Ignore,
          Pre extends string ? `${Pre}.${K}` : K,
          DEPTH
        >
      : never;
  // then we return any value that is not 'never'
}[keyof T];

/**
 * A Utility that extracts either resource types or resource paths from a TypedRecordInstance.
 *
 * Its limitations are mostly around its intentional non-recursiveness. It presumes that APIs which
 * implement includes will not allow cyclical include paths, and will collapse includes by type.
 *
 * This follows closer to the JSON:API fields spec than to the includes spec in nature, but in
 * practice it is so impracticle for an API to allow z-algo include paths that this is probably
 * reasonable.
 *
 * We may need to revisit this in the future, opting to either make this restriction optional or
 * to allow for other strategies.
 *
 * There's a 90% chance this particular implementation belongs being in the JSON:API package instead
 * of core-types, but it's here for now.
 *
 * @typedoc
 */
type ExtractUnion<
  MAX_DEPTH extends _DEPTHCOUNT,
  T extends TypedRecordInstance,
  IncludePrefix extends boolean = false,
  Ignore = NONE,
  Pre = NONE,
  DEPTH extends _DEPTHCOUNT = 1,
> = Exclude<
  IncludePrefix extends true
    ? // if we want to include prefix, we union with the prefix. Outer Exclude will filter any "NONE" types
      _ExtractUnion<MAX_DEPTH, T, IncludePrefix, Ignore, Pre, DEPTH> | Pre
    : // Else we just union the types.
      _ExtractUnion<MAX_DEPTH, T, IncludePrefix, Ignore, Pre, DEPTH> | T[typeof ResourceType],
  NONE
>;

type _DEPTHCOUNT = 1 | 2 | 3 | 4 | 5;
type INC_DEPTH<START extends _DEPTHCOUNT> = START extends 1 ? 2 : START extends 2 ? 3 : START extends 3 ? 4 : 5;
type IS_MAX_DEPTH<
  DEPTH extends _DEPTHCOUNT,
  MAX_DEPTH extends _DEPTHCOUNT = DEFAULT_MAX_DEPTH,
> = DEPTH extends MAX_DEPTH ? true : false;
type DEFAULT_MAX_DEPTH = 3;
/**
 * A utility that provides the union of all ResourceName for all potential
 * includes for the given TypedRecordInstance.
 *
 * @typedoc
 */
export type ExtractSuggestedCacheTypes<
  T extends TypedRecordInstance,
  MAX_DEPTH extends _DEPTHCOUNT = DEFAULT_MAX_DEPTH,
> = ExtractUnion<MAX_DEPTH, T>; // ToPaths<ExpandIgnore<T, true>, false>;

/**
 * A utility that provides the union type of all valid include paths for the given
 * TypedRecordInstance.
 *
 * Cyclical paths are filtered out.
 *
 * @typedoc
 */
export type Includes<T extends TypedRecordInstance, MAX_DEPTH extends _DEPTHCOUNT = DEFAULT_MAX_DEPTH> = ExtractUnion<
  MAX_DEPTH,
  T,
  true
>;

export type OpaqueRecordInstance = unknown;