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

@tilework/opus

v0.0.12

Published

<h1 float="left"> <img src="https://e.unicode-table.com/orig/f5/7c6daba899f1db0c849b20fae63a38.png" height="32"> Opus </h1>

Downloads

1,543

Readme

Opus, the Latin for ‘work’, is the way in which the pieces of a tilework are cut and placed.

Why

The GraphQL requests generated by this library are easily extensible by the plugin system, because they are generated procedurally, as opposed to the commonly-used generation from strings.

This library is TINY and still provides all of the basic functionality of GraphQL interactions. Additional features are planned to get implemented on-demand.

Generate GraphQL requests with Builder pattern and receive properly structurally typed responses upon fetching!

Hnet com-image

What

Almost every aspect of GraphQL functionality is supported: fields, nested fields, inline fragments, arguments. The only thing not yet supported are non-inline Fragments. Although, apart from slightly increased request size, this will not impact your development experience in any way.

import { Query, Field, InlineFragment } from '@tilework/opus';

const dragonFields = ['name', 'neck_length', 'age'] as const;

const dragonsQuery = new Query('dragons', true) // `true` means 'expect array'
    .addArgument('limit', 'Int', 5)
    .addFieldList(dragonFields)
    .addField(new Field('children', true)
        .addFieldList(dragonFields)
    )
    .addField(new InlineFragment('Fire')
        .addField('fire_temperature')
    )
    .addField(new InlineFragment('Ice')
        .addField('ice_density')
    )

Sometimes it is necessary to explicitly reference the type, which the fetched data will have upon retrieval. A utility type is provided in order to make this possible!

import { Query } from '@tilework/opus';
import type { DataType } from '@tilework/opus';

const query = new Query('person', true)
    .addFieldList(['name', 'surname']);

let result: DataType<typeof query>;

result = await client.post(query);

An opportunity to derive additional data from the fetched information is provided with calculated fields. A calculated field can be added on any instance of Field, Query or Mutation.

Such fields get calculated once, when the request is post-processed upon fetching. They are calculated starting with the deepest child and going up to the root node (post-visit).

import { Query, Field } from '@tilework/opus';

const query = new Query('dragons', true)
    .addField('active')
    .addField(new Field('launch_payload_mass')
        .addField('kg')
        .addCalculatedField('lb', (result) => result.kg * ONE_KG_IN_LBS)
    )
    .addField(new Field('return_payload_mass')
        .addField('kg')
    )
    .addCalculatedField('payload_delta_kg', (result) => {
        return result.launch_payload_mass.kg - result.return_payload_mass.kg;
    });

Note: Attempts to add fields to the result via this API will throw due to the processable object being sealed at the time of processing. Use calculated fields to add additional fields.

Sometimes it's necessary to modify the data you have received, e.g. in order to reduce nesting of some fields. In order to achieve that, this functionality should be used!

In the example below, the property launch_payload_mass becomes launch_payload_mass.kg, just to make everything a bit more convenient.

import { Query, Field } from '@tilework/opus';

const query = new Query('dragons', true)
    .addField('active')
    .addField(new Field('launch_payload_mass')
        .addField('kg')
        .addTransformation((launchPayload) => launchPayload.kg)
    )
    .addField(new Field('return_payload_mass')
        .addField('kg')
        .addTransformation((returnPayload) => returnPayload.kg)
    );

...

typeof result.dragons[0].launch_payload_mass; // number

The client provides an opportunity to fetch queries and mutations, as well as fetch combined queries and combined mutations.

import { client, CombinedField } from '@tilework/opus';

// Single requests
const queryResult = await client.post(someQuery);
const mutationResult = await client.post(someMutation);

// Combined queries and mutations work the same
const combinedQueryResult = await client.post(new CombinedField
    .add(firstQuery)
    .add(secondQuery)
);

It is necessary to set up the client before fetching any data. See the required configuration steps below.

  • Endpoint
    • client.setEndpoint(endpoint: string) allows to configure this in runtime
    • Setting GRAPHQL_ENDPOINT in process.env will also set the endpoint
    • It defaults to /graphql
  • Headers
    • client.setHeaders(headers: any) will set the headers to use for fetching requests