npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

fable.remoting.ts

v0.6.0

Published

A TS/JS simple lib to interop with Fable.Remoting

Downloads

16

Readme

Fable.Remoting.Ts

CI npm version

This is a simple proxy-based library that tries to help you interact with your .net server in a simple way.

Fable.Remoting is one incredibly nice way to interact with your server where you define your types in a shared project/file and then you just invoke functions based on those declared types.

Sometimes you won't be able (or don't want to) use F# as the client of your F#/C# server and that sadly takes some of the Fable.Remoting Advantages away (apparently) if you enable raw http in Fable.Remoting, then you can use this library to ease some of those interactions

Requirements

This library uses ES2015 Proxy so there's no IE support it also uses Axios and msgpack.js so it should be usable both in your browser and any node.js environment

Usage

you can also check a sample here and here

import { createService } from 'fable.remoting.ts'

const service = createService({ 
    // where is your server at?
    baseURL: 'http://localhost:5000',
    // this is the name of the service you registered within your server
    serviceName: 'IBooksService',
    // wether your server is sending msgpack messages
    withMsgPack: false
});

// use getBooks anywhere else
const getBooks = async () => {
    //the name of the service method you want to invoke on the server
    try {
        const results = await service.getBooks();
        return results;
    } catch(error) {
        console.warn(error.message);
        return [];
    }
}

// use saveBook somewhere else
const saveBook = async (book: Book)  => {
    try {
        const results = await service.saveBook(book);
        return results;
    } catch(error) {
        console.warn(error.message);
        throw Error(error);
    }
}

type safety

If you want to have a little bit more of type safety you might want to create an interface/type that represents what your server is doing for you (what you would normally do with F# types)

interface IBooksService {
    getBooks: () => Promise<AxiosResponse<Book[]>>;
    saveBook: (book: Bool) => Promise<AxiosResponse<Book>>;
}

const service = createService<IBooksService>({ 
    // where is your server at?
    baseURL: 'http://localhost:5000',
    // this is the name of the service you registered within your server
    serviceName: 'IBooksService',
    // wether your server is sending msgpack messages
    withMsgPack: false
});

// now you have typescript autocompletition
const { data } = await service.getBooks();
// typescript will complain about this
// service.IDontExist()
// although if you cast service as "any" it will still try to make the call to
// http://localhost:5000/IBooksService/IDontExist
// (service as any).IDontExist()
// so if you are using pure javascript where typos can slip through be careful about this

Extra configuring

If you want to customize further your http calls, you can pass axios options to your createService call, each createService call provides you with an axios instance


const service = createService<IBooksService>(
    { 
        // where is your server at?
        baseURL: 'http://localhost:5000',
        // this is the name of the service you registered within your server
        serviceName: 'IBooksService',
        // wether your server is sending msgpack messages
        withMsgPack: false
    }, 
    {
        headers: { /* ... any header you want to add ...*/ }
        proxy: { /* ... proxy options ... */},
        xsrfCookieName: 'cookie name',
        // ... and any other AxiosRequest options
    }
);

If you need to provide a new header (or delete) to an existing service instance, you can call

  • addHeaders
  • removeHeaders
  • addInterceptors
  • removeInterceptors methods accordingly
service.addHeaders({ 
    /* ... any headers you want to add here ...*/
    Authorization: 'Bearer ...token...'
});
// removeHeaders accepts any amount of string parameters
service.removeHeaders('Authorization', 'x-my-custom-header', ...myOtherHeaders);
//interceptors
 const id = service.addInterceptor('request', function logger(v: any) {
        console.log(v);
        return v;
    });

service.removeInterceptor(id);

Augment an existing service

You can use an existing service that is not made by Fable.Remoting.Ts, perhaps you already have services in place and want to add those extra functions

type IExistingService = {
    somePropertyForSomeReason: string;
    login(username: string; password: string) => Promise<AuthResponse>;
    Signup(user: SignupPayload) => Promise<AuthResponse>;
};

const existingService: IExistingService = createFromDIOrSomewhereElse();

const service = createService<IExistingService & IBooksService>({ 
    // where is your server at?
    baseURL: 'http://localhost:5000',
    // this is the name of the service you registered within your server
    serviceName: 'IBooksService',
    // whether your server is sending msgpack messages
    withMsgPack: false
}, null, existingService);

/**
 * For example let's try to login (existing service)
 * and get books (from proxy service) with a jwt token as authorization.
 **/
async function loginAndGetBooks() {
    // service will pick the login method from `existingService`
    const { token } = await service.login('[email protected]', 'super secret much wow')
    service.addHeaders({ Authorization: `Bearer ${token}` })
    // service will pick the getBooks method from the default proxy trap
    const books = await service.getBooks()
    console.log(books)
    // service will pick the somePropertyForSomeReason property from the `existingService` object
    console.log(service.somePropertyForSomeReason)
}

Craft your own request

if nothing of the above works for you for a specific use case, you can always fallback to axios's custom requests

const service = createService({ 
    // where is your server at?
    baseURL: 'http://localhost:5000',
    // this is the name of the service you registered within your server
    serviceName: 'IBooksService'
});

const response = await service.createRequest<MyOtherAPIResponse>({
        url: 'http://my.other.api.com',
        method: 'DELETE',
        params: {
            hello: 'world'
        }
    });
console.log(response.data);