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

@h-platform/cqm

v0.0.28

Published

This package defined core classes for commands and queries client for h-platform (CQClient)

Downloads

124

Readme

CQClient

CQClient is a wrapper class around http axios. It is warps axios and expose two functions instead:

  • Command: for changing system state which results in side effects such as updateing your database
  • Query: for retreiving data such as find and findAll operations

This simplifies the communication with the server. No need to think about request methods anymore like POST, GET, PATCH, DELETE, PUT. All rest api calls are executed using http POST method only.

Philosiphy

Expressing your api should be more clear and directly linked to the intended purpose. The api should be more elaborate and self explanatory. Seperating the operations into two types command and query gives a direct meaning of the intention of the declared api. Giving specific names for commands and queries gives a strong meaning leaving no room for guessing. Eventually you will build your own domain language that can be easily read and absorbed by your consumers.

Client Side:

In your browser client:

// create client
const cqClient = new CQClient('http://localhost:3000/api');

// execute some commands:
const createdPost = await cqClient.command('blog', 'post.create', { title: 'This how we cook our dinner' });
const updatedPost = await cqClient.command('blog', 'post.update', { id: 1, title: 'This is why we cook this way' });
await cqClient.command('blog', 'post.publish', { id: 1 });
await cqClient.command('blog', 'post.updateTags', { id: 1, tags: ['kitchen'] });

// execute some queries:
const post = await cqClient.query('blog', 'post.findById', { id: 1 });
const comments = await cqClient.query('blog', 'post.findComments', { postId: 1 });

The first parameter for the command is called the moduleName. Relative commands and queries should be grouped together in a module. The second parameter is the topic name of the command, the third parameter is the payload object to be sent to the server for processing. The same goes for the query.

CQClient.command(moduleName: string, commandName: string, payload: any);

Server Side:

The server api urls should follows this format:

  • POST /api/${moduleName}/commands/${commandName}
  • POST /api/${moduleName}/queries/${queryName}

For the above blog post samples, the actual api urls would be:

POST /api/blog/commands/post.create
POST /api/blog/commands/post.update
POST /api/blog/commands/post.publish
POST /api/blog/commands/post.updateTags

POST /api/blog/queries/post.findById
POST /api/blog/queries/post.findComments

Response body from the server expected to match the CommandResponse class:

{
    success: true,
    message: 'post created successfully',
    code: 'POST_CREATED',
    data: {
        // data from the server
        postId: 1
    }
}

To make it easier to generate such response, you can use CommandResponse helper in server code:

return CommandResponse.success('Post created successfully', 'POST_CREATED', {});

This is a sample express server with typescript using CommandResponse helpers functions:

import express, { Express, Request, Response } from 'express';
import { CommandResponse } from '@h-platform/cqm';

const app: Express = express();
const port = process.env.PORT;

app.post('/api/blog/commands/post.create', (req: Request, res: Response) => {
    // some logic for creating the post goes here
    
    if (everyThingIsOk) {
        // generating the response:
        const cqResponse =  CommandResponse.success('Post created successfully', 'POST_CREATED', {});
        res.send(cqResponse);
    else {
        // in case of error
        const cqResponseError =  CommandResponse.error('You are not allowed to create post', 'AUTH_ERR', {});
        res.send(cqResponseError).status(500);
    }
});

app.listen(3000, () => {
  console.log(`⚡️[server]: Server is running at https://localhost:3000/`);