Skip to content

Latest commit

 

History

History
71 lines (63 loc) · 4.39 KB

readme.md

File metadata and controls

71 lines (63 loc) · 4.39 KB

restfuncs-transformer

This transformer prepares ServerSession subclasses for Typia and adds jsDoc info for the (upcoming) API browser.

Usage

Here's how to use it

Debugging parameters

Insert these into the { "transform": "restfuncs-transformer", ...} block.

  • debug: Set to true to dump the output of transformed and affected files each into a file named ...after_restfuncs-transformer.tmp
  • pretty: Pretty print the output (normally it is squeezed into one line to preserve line numbers and keep source maps intact)

How the transformer chain works

Here is, how the restfuncs-transformer, typia transformer and typescript-rtti work together:

  1. The restfuncs-transformer scans for all @remote methods and, at the bottom of inside their class, it adds the following code (here for):
@remote
async myMethod(param1: string, someCallbackFn: (p:number) => Promise<string>);

results in adding this to the class body:

import _rf_typia from "typia";
/**
 * Code is generated by the restfuncs-transformer during compile-time
 */
static getRemoteMethodsMeta(): (typeof this.type_remoteMethodsMeta) {
    this.__hello_developer__make_sure_your_class_is_a_subclass_of_ServerSession // Attempt to give a friendly error message when this is not the case. Otherwise the previous line would fail and leaves the user wondering.
    type CallbackPlaceholder<DECL_INDEX extends number>  = string & _rf_typia.tags.TagBase<{kind: "callbackFn", target: "string", value: DECL_INDEX, validate: `onValidateCallbackArg($input, ${DECL_INDEX})`}>; // Create a [custom tag](https://typia.io/docs/validators/tags/#customization), that can be used via `CallbackPlaceholder<n>`. During validation, this tag then calls onValidateCallbackArg.   
    const result= {
        transformerVersion: {major: XX,  feature: XX },
        instanceMethods: {
            "myMethod": {
                arguments: {
                    validateEquals: (args: unknown) => _rf_typia.validateEquals<[param1: string, someCallback: (p:number) => Promise<string>]>(args),
                    validatePrune: ...,
                    withPlaceholders: {
                        validateEquals: (args: unknown, onValidateCallbackArg: (placeholderId: string, declarationIndex: number) => boolean) => _rf_typia.validateEquals<[param1: string, someCallback: CallbackPlaceholder<0>]>(args),
                        ...
                    }
                },                
                result: {
                    validateEquals: (value: unknown) => _rf_typia.validateEquals<Awaited<ReturnType<typeof this.prototype["myMethod"]>>>(value),
                    ...
                },
                callbacks: [{ // here for the `someCallbackFn: (p:number) => Promise<string>` declaration
                    arguments: {
                        validateEquals: (args: unknown) => _rf_typia.validateEquals<[p: number]>(args),
                        validatePrune: ...
                    },
                    awaitedResult: {
                        validateEquals: (value: unknown) => _rf_typia.validateEquals<string>(value),
                        ...
                    }
                }],
                jsDoc: {
                    comment: "text with <strong>markup</strong>", 
                    params: {a: "text..."},
                    tags: [{name:"returns", comment: "text..."}]
                }
            }
        }
    };
    
    return result; // Code style note for this line: Why not do `return {...}` directly ? This tiny difference allows for extra properties which ensure backward compatibility with older "restfuncs-server" packages.
}
  1. The Typia transformer will then replace all typia.validate<T> expressions with the actual validation code body. Typia calls this "ahead of time validation". At runtime this is used to validate evil input and serialize/deserialize from json/protobuf in an ultra fast way (future).
  2. The typescript-rtti transformer adds type-info decorations for all compiled symbols (that's all this __RΦ stuff in the .js). At runtime, this allows restfuncs to easily navigate through- and inspect all the type hierarchy. I.e when mapping REST parameter names to the remote methods arguments, for better error diagnosis, or for the upcoming API browser.