230 lines · 7.4 KB · TypeScript
RawDownload
import { Effect } from "effect"; import type { StorageFailure } from "./fuma-runtime";import type { Owner } from "./ids"; export type PluginStorageSchema = {  readonly Type: object;}; export type PluginStorageSchemaType<TSchema extends PluginStorageSchema> = TSchema["Type"]; export type PluginStorageIndexField<TData extends object> = Extract<keyof TData, string>; export type PluginStorageIndexSpec<TData extends object> =  | PluginStorageIndexField<TData>  | readonly PluginStorageIndexField<TData>[]; export type PluginStorageRuntimeIndexSpec = string | readonly string[]; export interface PluginStorageRuntimeCollectionDefinition {  readonly name: string;  readonly schema: PluginStorageSchema;  readonly indexes: readonly PluginStorageRuntimeIndexSpec[];} export interface PluginStorageCollectionDefinition<  TName extends string = string,  TData extends object = Record<string, unknown>,  TIndexes extends readonly PluginStorageIndexSpec<TData>[] =    readonly PluginStorageIndexSpec<TData>[],> extends PluginStorageRuntimeCollectionDefinition {  readonly name: TName;  readonly schema: PluginStorageSchema;  readonly indexes: TIndexes;} export type PluginStorageConfig = Readonly<  Record<string, PluginStorageRuntimeCollectionDefinition>>; export const definePluginStorageCollection = <  const TName extends string,  const TSchema extends PluginStorageSchema,  const TIndexes extends readonly PluginStorageIndexSpec<PluginStorageSchemaType<TSchema>>[] =    readonly [],>(  name: TName,  schema: TSchema,  options?: {    readonly indexes?: TIndexes;  },): PluginStorageCollectionDefinition<TName, PluginStorageSchemaType<TSchema>, TIndexes> => ({  name,  schema,  indexes: (options?.indexes ?? []) as TIndexes,}); export type PluginStorageCollectionData<TDefinition> =  TDefinition extends PluginStorageCollectionDefinition<infer _Name, infer TData, infer _Indexes>    ? TData    : never; export type PluginStorageIndexFields<TIndexes> = TIndexes extends readonly (infer TIndex)[]  ? TIndex extends readonly (infer TField)[]    ? Extract<TField, string>    : Extract<TIndex, string>  : never; export type PluginStorageCollectionIndexedField<TDefinition> =  TDefinition extends PluginStorageCollectionDefinition<infer _Name, infer _Data, infer TIndexes>    ? PluginStorageIndexFields<TIndexes>    : never; export interface PluginStorageWhereFilter<TValue> {  readonly eq?: TValue;  readonly in?: readonly TValue[];  readonly gt?: TValue;  readonly gte?: TValue;  readonly lt?: TValue;  readonly lte?: TValue;} export type PluginStorageWhereValue<TValue> = TValue | PluginStorageWhereFilter<TValue>; export type PluginStorageCollectionWhere<TDefinition> = {  readonly [TField in PluginStorageCollectionIndexedField<TDefinition>]?: PluginStorageWhereValue<    TField extends keyof PluginStorageCollectionData<TDefinition>      ? PluginStorageCollectionData<TDefinition>[TField]      : never  >;}; export interface PluginStorageCollectionOrderBy<TDefinition> {  readonly field: PluginStorageCollectionIndexedField<TDefinition>;  readonly direction?: "asc" | "desc";} export interface PluginStorageKeyInput {  readonly collection: string;  readonly key: string;} export interface PluginStorageScopedKeyInput extends PluginStorageKeyInput {  readonly owner: Owner;} export interface PluginStorageListInput {  readonly collection: string;  readonly keyPrefix?: string;} export interface PluginStoragePutInput extends PluginStorageScopedKeyInput {  readonly data: unknown;} export interface PluginStoragePutManyEntry extends PluginStorageKeyInput {  readonly data: unknown;} export interface PluginStoragePutManyInput {  readonly owner: Owner;  readonly entries: readonly PluginStoragePutManyEntry[];} export interface PluginStorageRemoveManyInput {  readonly owner: Owner;  readonly entries: readonly PluginStorageKeyInput[];} export interface PluginStorageCollectionKeyInput {  readonly key: string;} export interface PluginStorageCollectionScopedKeyInput extends PluginStorageCollectionKeyInput {  readonly owner: Owner;} export interface PluginStorageCollectionListInput {  readonly keyPrefix?: string;} export interface PluginStorageCollectionPutInput<  TData extends object,> extends PluginStorageCollectionScopedKeyInput {  readonly data: TData;} export interface PluginStorageCollectionQueryInput<TDefinition> {  readonly keyPrefix?: string;  readonly where?: PluginStorageCollectionWhere<TDefinition>;  readonly orderBy?: readonly PluginStorageCollectionOrderBy<TDefinition>[];  readonly limit?: number;  readonly offset?: number;} export interface PluginStorageEntry<T = unknown> {  readonly id: string;  readonly owner: Owner;  readonly pluginId: string;  readonly collection: string;  readonly key: string;  readonly data: T;  readonly createdAt: Date;  readonly updatedAt: Date;} export interface PluginStorageCollectionFacade<  TDefinition extends PluginStorageCollectionDefinition = PluginStorageCollectionDefinition,> {  readonly get: (    input: PluginStorageCollectionKeyInput,  ) => Effect.Effect<    PluginStorageEntry<PluginStorageCollectionData<TDefinition>> | null,    StorageFailure  >;  readonly getForOwner: (    input: PluginStorageCollectionScopedKeyInput,  ) => Effect.Effect<    PluginStorageEntry<PluginStorageCollectionData<TDefinition>> | null,    StorageFailure  >;  readonly list: (    input?: PluginStorageCollectionListInput,  ) => Effect.Effect<    readonly PluginStorageEntry<PluginStorageCollectionData<TDefinition>>[],    StorageFailure  >;  readonly put: (    input: PluginStorageCollectionPutInput<PluginStorageCollectionData<TDefinition>>,  ) => Effect.Effect<PluginStorageEntry<PluginStorageCollectionData<TDefinition>>, StorageFailure>;  readonly query: (    input?: PluginStorageCollectionQueryInput<TDefinition>,  ) => Effect.Effect<    readonly PluginStorageEntry<PluginStorageCollectionData<TDefinition>>[],    StorageFailure  >;  readonly count: (    input?: Omit<PluginStorageCollectionQueryInput<TDefinition>, "orderBy" | "limit" | "offset">,  ) => Effect.Effect<number, StorageFailure>;  readonly remove: (    input: PluginStorageCollectionScopedKeyInput,  ) => Effect.Effect<void, StorageFailure>;} export interface PluginStorageFacade {  readonly collection: <const TDefinition extends PluginStorageCollectionDefinition>(    definition: TDefinition,  ) => PluginStorageCollectionFacade<TDefinition>;  readonly get: <T = unknown>(    input: PluginStorageKeyInput,  ) => Effect.Effect<PluginStorageEntry<T> | null, StorageFailure>;  readonly getForOwner: <T = unknown>(    input: PluginStorageScopedKeyInput,  ) => Effect.Effect<PluginStorageEntry<T> | null, StorageFailure>;  readonly list: <T = unknown>(    input: PluginStorageListInput,  ) => Effect.Effect<readonly PluginStorageEntry<T>[], StorageFailure>;  readonly put: <T = unknown>(    input: PluginStoragePutInput,  ) => Effect.Effect<PluginStorageEntry<T>, StorageFailure>;  readonly putMany: (input: PluginStoragePutManyInput) => Effect.Effect<void, StorageFailure>;  readonly remove: (input: PluginStorageScopedKeyInput) => Effect.Effect<void, StorageFailure>;  readonly removeMany: (input: PluginStorageRemoveManyInput) => Effect.Effect<void, StorageFailure>;} export const pluginStorageId = (input: {  readonly pluginId: string;  readonly collection: string;  readonly key: string;}): string => JSON.stringify([input.pluginId, input.collection, input.key]);