Skip to content

Commit

Permalink
Simplified new options, made optional properties of options required …
Browse files Browse the repository at this point in the history
…during internal usage (to reflect defaults)
  • Loading branch information
doseofted committed Apr 7, 2024
1 parent c836eb5 commit 73dc2a1
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 76 deletions.
2 changes: 1 addition & 1 deletion libs/rpc/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { nanoid } from "nanoid"
import getProperty from "just-safe-get"
import removeFromArray from "just-remove"
import { deserializeError } from "serialize-error"
import { createPrimOptions, primMajorVersion, useVersionInRpc } from "./options"
import { createPrimOptions, primMajorVersion, useVersionInRpc } from "./deprecated/options"
import { extractBlobData, mergeBlobData, extractPromisePlaceholders } from "./deprecated/extract-utils"
import { PromiseResolveStatus } from "./interfaces"
import type { PrimOptions, PrimWebSocketEvents, PrimHttpEvents, PrimHttpQueueItem, BlobRecords } from "./interfaces"
Expand Down
16 changes: 8 additions & 8 deletions libs/rpc/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
// SPDX-License-Identifier: Apache-2.0

/* eslint-disable @typescript-eslint/no-unused-vars */
import { createPrimOptions } from "../options"
import { createMethodCatcher } from "./proxy"
import { handlePotentialPromise } from "./wrapper"
import { getUnfulfilledModule, handleLocalModuleMethod } from "./local"
import type { RpcModule, PossibleModule } from "../types/rpc-module"
import type { MergeModuleMethods } from "../types/merge"
import type { UserProvidedClientOptions } from "../options/client/provided"
import type { UserProvidedClientOptions } from "../options/provided"
import { createOptions } from "../options/index"

export function createRpcClient<
ModuleType extends PossibleModule = never,
GivenOptions extends UserProvidedClientOptions = UserProvidedClientOptions,
>(options?: GivenOptions) {
options = createPrimOptions<GivenOptions>(options)
const optionsInit = createOptions(options)
// the returned client will catch all method calls given on it recursively
type FinalModule = MergeModuleMethods<
RpcModule<ModuleType, GivenOptions["handleForms"], true>,
Expand All @@ -24,15 +24,15 @@ export function createRpcClient<
return createMethodCatcher<FinalModule>({
onMethod(rpc, next) {
// if module method was provided (and is not dynamic import), intercept call and return synchronously
if (getUnfulfilledModule(options.module) instanceof Promise) return next
const given = handleLocalModuleMethod(rpc, options, next)
if (getUnfulfilledModule(optionsInit.module) instanceof Promise) return next
const given = handleLocalModuleMethod(rpc, optionsInit, next)
// because the module is not a dynamic import (Promise), we can safely check for the "next" token synchronously
if (given === next) return next
return given
},
onAwaited(rpc, next) {
return handlePotentialPromise(
() => handleLocalModuleMethod(rpc, options, next),
() => handleLocalModuleMethod(rpc, optionsInit, next),
localResult => {
if (localResult !== next) return localResult
// TODO: handle RPC (provide promise that resolves for server events)
Expand All @@ -42,8 +42,8 @@ export function createRpcClient<
},
onIterable(rpc, next) {
// first determine if iterable result is given on local module
if (getUnfulfilledModule(options.module) instanceof Promise) return next
const given = handleLocalModuleMethod(rpc, options, next)
if (getUnfulfilledModule(optionsInit.module) instanceof Promise) return next
const given = handleLocalModuleMethod(rpc, optionsInit, next)
if (given === next) return next
if (typeof given === "object" && (Symbol.iterator in given || Symbol.asyncIterator in given)) return given
// TODO: handle RPC (provide async iterable that iterates on server events)
Expand Down
2 changes: 1 addition & 1 deletion libs/rpc/src/client/local.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { describe, expect, test } from "vitest"
import { handleLocalModuleMethod } from "./local"
import type { PrimOptions } from "../interfaces"
import type { RpcCall } from "../types/rpc-structure"
import type { UserProvidedClientOptions } from "../options/client/provided"
import type { UserProvidedClientOptions } from "../options/provided"

const exampleModule = {
hello(name?: string) {
Expand Down
2 changes: 1 addition & 1 deletion libs/rpc/src/client/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import { givenFormLike, handlePossibleForm } from "../extract/blobs"
import type { PossibleModule } from "../interfaces"
import type { UserProvidedClientOptions } from "../options/client/provided"
import type { UserProvidedClientOptions } from "../options/provided"
import type { RpcCall } from "../types/rpc-structure"
import { handlePotentialPromise } from "./wrapper"
import getProperty from "just-safe-get"
Expand Down
2 changes: 1 addition & 1 deletion libs/rpc/src/deprecated/extract-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0

import { RpcPlaceholder, resolvePlaceholder } from "../constants"
import { featureFlags } from "../flags"
import { featureFlags } from "./flags"
import { extract, merge } from "../extract/base"
import { blobIdentifier, givenFormLike, handlePossibleForm } from "../extract/blobs"
import { promiseIdentifier } from "../extract/promises"
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import { defu } from "defu"
import { destr } from "destr"
import type { PrimOptions, PrimServerOptions } from "./interfaces"
import type { RpcCall } from "./types/rpc-structure"
import type { PrimOptions, PrimServerOptions } from "../interfaces"
import type { RpcCall } from "../types/rpc-structure"
/**
* As Prim+RPC introduces new updates to RPC message structure, update this version.
* Don't update just because major version changes though (only if version changes RPC structure)
Expand Down Expand Up @@ -78,6 +78,7 @@ const createBaseClientOptions = (server = false): PrimOptions => ({
// !SECTION
})

/** @deprecated */
const createBaseServerOptions = (): PrimServerOptions => ({
...createBaseClientOptions(true),
// the default prefix will likely be overridden
Expand All @@ -95,6 +96,8 @@ const createBaseServerOptions = (): PrimServerOptions => ({
*
* @param options Given options by developer
* @returns Options with defaults set
*
* @deprecated
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function createPrimOptions<OptionsType extends PrimOptions<any, any, any> = PrimOptions>(
Expand Down
2 changes: 1 addition & 1 deletion libs/rpc/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import type { Emitter } from "mitt"
import type { Schema, PartialDeep } from "type-fest"
import type { featureFlags } from "./flags"
import type { featureFlags } from "./deprecated/flags"
import type { RpcCall, RpcAnswer } from "./types/rpc-structure"
import type { WithoutFunctionWrapper, WithoutPromiseWrapper } from "./types/rpc-module"
import type { RpcModule } from "./types/rpc-module"
Expand Down
36 changes: 0 additions & 36 deletions libs/rpc/src/options/client/utilized.ts

This file was deleted.

58 changes: 58 additions & 0 deletions libs/rpc/src/options/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,61 @@
// Part of the Prim+RPC project ( https://prim.doseofted.me/ )
// Copyright 2023 Ted Klingenberg
// SPDX-License-Identifier: Apache-2.0

import { defu } from "defu"
import { destr } from "destr"
import type { UserProvidedServerOptions } from "./provided"
import type { SetRequired } from "type-fest"

const defaults = {
transformHandler: {
stringify: JSON.stringify,
parse: destr,
binary: false,
mediaType: "application/json",
},
handleErrors: { enabled: true, stackTrace: false },
resolverClient: null,
resolverServer: null,
} satisfies UserProvidedServerOptions

type MergeOptions = Omit<UserProvidedServerOptions, keyof typeof defaults>

export function createOptions(provided: UserProvidedServerOptions = {}) {
const {
transformHandler = defaults.transformHandler,
handleErrors = defaults.handleErrors,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
resolverClient = defaults.resolverClient,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
resolverServer = defaults.resolverServer,
...providedMerge
} = provided
const merged = defu<MergeOptions, MergeOptions[]>(providedMerge, {
module: null,
allowSchema: {},
allowedMethodsOnMethod: {},
batchTime: false,
handleBlobs: true,
handleForms: true,
handlingDepth: 3,
})
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
return { ...merged, handleErrors, transformHandler, resolverClient, resolverServer } as InitializedOptions
}

/** Options utilized internally by client/server (some values will be set to defaults) */
export type InitializedOptions = SetRequired<
UserProvidedServerOptions,
| "transformHandler"
| "handleErrors"
| "module"
| "allowSchema"
| "allowedMethodsOnMethod"
| "batchTime"
| "handleBlobs"
| "handleForms"
| "handlingDepth"
| "resolverClient"
| "resolverServer"
>
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type {
RpcModule,
WithoutFunctionWrapper,
WithoutPromiseWrapper,
} from "../../types/rpc-module"
import type { ResolverClient } from "../../resolver/types"
} from "../types/rpc-module"
import type { ResolverClient, ResolverServer } from "../resolver/types"

/**
* An object conforming to `JSON` (with `parse` and `stringify` methods) that implements serialization/deserialization
Expand Down Expand Up @@ -155,7 +155,7 @@ export interface UserProvidedClientOptions<
/**
* A plugin (or list of available plugins) used to send RPC and receive RPC results.
*/
resolverClient?: ResolverClient | ResolverClient[]
resolverClient?: null | ResolverClient | ResolverClient[]
/**
* Transform given arguments prior to calling a function. This hook may alternatively intercept a function call and
* return a result early. This hook returns an object with either `.args` or `.result`, otherwise this function should
Expand All @@ -169,7 +169,7 @@ export interface UserProvidedClientOptions<
args: unknown[],
name: string,
props: Record<PropertyKey, unknown>
) => { result?: unknown; args: unknown[] } | Promise<{ result?: unknown; args: unknown[] }> | undefined | void
) => { result?: unknown; args: unknown[] } | Promise<{ result?: unknown; args: unknown[] }> | void
/**
* Transform given result prior to being returned to the function caller. If an object with `.result` is returned,
* the return value will be modified, otherwise this function should return void to continue with original return
Expand All @@ -184,7 +184,7 @@ export interface UserProvidedClientOptions<
result: unknown,
name: string,
props: Record<PropertyKey, unknown>
) => { result?: unknown } | Promise<{ result?: unknown }> | undefined | void
) => { result?: unknown } | Promise<{ result?: unknown }> | void
/**
* Transform given error prior to being thrown to the RPC caller. A returned object with `.error` will be thrown as
* the new error, otherwise this function should return void to continue with the original error. While it's also
Expand All @@ -194,5 +194,15 @@ export interface UserProvidedClientOptions<
*
* @default undefined
*/
onCallError?: (error: unknown, name: string) => { error?: unknown } | Promise<{ error?: unknown }> | undefined | void
onCallError?: (error: unknown, name: string) => { error?: unknown } | Promise<{ error?: unknown }> | void
}

export interface UserProvidedServerOptions<
GivenModule extends PossibleModule = PossibleModule,
FormHandling extends boolean = boolean,
> extends UserProvidedClientOptions<GivenModule, FormHandling> {
/**
* A plugin (or list of available plugins) used to receive RPC and send RPC results.
*/
resolverServer?: null | ResolverServer | ResolverServer[]
}
13 changes: 0 additions & 13 deletions libs/rpc/src/options/server/provided.ts

This file was deleted.

2 changes: 1 addition & 1 deletion libs/rpc/src/resolver/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { TransformHandler } from "../options/client/provided"
import type { TransformHandler } from "../options/provided"

// interpreter

Expand Down
2 changes: 1 addition & 1 deletion libs/rpc/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import getProperty from "just-safe-get"
import mitt from "mitt"
import queryString from "query-string"
import { serializeError } from "serialize-error"
import { createPrimOptions, primMajorVersion, useVersionInRpc } from "./options"
import { createPrimOptions, primMajorVersion, useVersionInRpc } from "./deprecated/options"
import { createPrimClient } from "./client"
import { extractBlobData, mergeBlobData, extractPromiseData } from "./deprecated/extract-utils"
import { PrimRpcSpecific, checkHttpLikeRequest, checkHttpLikeResponse, checkRpcCall, checkRpcResult } from "./validate"
Expand Down
7 changes: 3 additions & 4 deletions libs/rpc/src/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { send } from "process"
import { UserProvidedClientOptions } from "../options/client/provided"
import { UserProvidedServerOptions } from "../options/provided"
import { ResolverServer } from "../resolver/types"

export function createRpcServer<GivenOptions extends UserProvidedClientOptions = UserProvidedClientOptions>(
options: GivenOptions
export function createRpcServer<GivenOptions extends UserProvidedServerOptions = UserProvidedServerOptions>(
_options: GivenOptions
): ResolverServer {
return () => null
}

0 comments on commit 73dc2a1

Please sign in to comment.