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

xcraft-core-goblin

v5.29.3

Published

Xcraft uService API

Downloads

259

Readme

xcraft-core-goblin

Xcraft uService API

Welcome on board!

Goblins are small, green (or yellow-green) creatures with pointy features and high intelligence (though often little common sense). Goblins speak Goblin, Orcish, and Common. Goblins know myriad languages in order to trade with as many races as possible.

With goblin you can craft some redux uService on top of the Orcish Xcraft toolchain infrastructure.

This package provide a thin API and conventions for building your first goblin.

Goblins

When you implement a goblin, you must think like a goblin.

Goblin instances

By default, the goblins are instantiated by a create command: const extractor = yield quest.create ('gold-extractor', payload)

When an instance is created this way in a goblin quest, you own the created instance, and some rules apply:

When your gobelin (the owner) is deleted, sub-creations is also automagically deleted with a call to the delete quest.

The quest.create (namespace, args) command

Under the hood, quest.create sends aquest.cmd ('gold-extractor.create', {...payload}) and returns an object containing id and all wrapped public quests.

Variants

The createFor variant quest.createFor (owner-namespace, id, namespace, args), allow you to define the owner manually, so when the specified owner is deleted, this creation will be too.

Single instance

Some goblins can be created as singleton. In this case, quest.create will not work. You must send a command to the goblin directly with quest.cmd.

quest lifetime scope

We use quest.defer () for registering a function to be run when the current quest is finished.

// Example of use for defering when we leave the quest
goblin.registerQuest ('test', (quest) => {
  const extractor = yield quest.create ('gold-extractor');
  // We defer the delete quest, after this quest
  quest.defer (extractor.delete);
  const gold = extractor.extract ('http://mineofgold.com');
  /* ... */
});

goblin lifetime scope

We use quest.goblin.defer () for registering a function to be run after the quest deletion of our goblin instance.

// Example of use for defering when we leave the delete of this instance
goblin.registerQuest ('create', (quest) => {
  const extractor = yield quest.create ('gold-extractor');
  // We defer the delete quest, after our goblin delete quest run
  quest.goblin.defer (extractor.delete);
  const gold = extractor.extract ('http://mineofgold.com');
  /* ... */
});

Quests

A quest is a powerfull running context for dealing with other goblins. You can create goblins, running dedicated commands, sending events for signaling some status, waiting for other goblins events and dispatch actions for modifing your state.

From another point of view, quests are providing lifetime handlers for a goblin instance, the creation of a goblin instance is always handled by the create quest and the delete quest provides the deletion implementation of an instance.

Other quests, are like methods of an instance, add, remove, open, close etc...

create and delete quests

When you configure a goblin, you must register a create and a delete quest. This is not true for a single instance (singleton) goblin.

Widget example

We create a widget goblin named panel, we register and implement:

  • create (required!)
  • delete (required!)
  • toggle
  • set-title

usage for this example:

const panel = yield quest.create ('panel');
quest.goblin.defer (panel.delete);
panel.toggle ();
panel.setTitle ({title: 'Hello World'});

Single instance service example

We create a single instance goblin named window-manager, we register and implement:

  • init
  • win.create (required!)
  • win.delete (required!)
  • win.show

usage for this example:

const win = yield quest.create ('wm');
quest.goblin.defer ( quest.release(win.id));
win.show ();

Quest handlers

// Example of a `create` quest
goblin.registerQuest ('create', (quest, somedata) => {
  quest.dispatch ('mutate', {somedata});

  // dispatch 'create' with automatic payload:
  quest.do ();

  // logging
  quest.log.info ('done!');

  // cmd sending
  yield quest.cmd ('somegoblin.somequest', {
    someparam: 'value',
  });

  // event sending
  // the final topic is prefixed with your goblin name
  quest.evt ('bim.bam.boom', {some: payload});

  // (sub|unsub) scribe to events
  // full topic name is required
  const unsub = quest.sub ('somegoblin.topic', handler => yo);
  unsub ();

  // wait on an event
  yield quest.sub.wait ('somegoblin.topic');

  // Create widget via goblins
  const panel = yield quest.create ('panel');
  quest.goblin.defer (panel.delete);
  panel.toggle ();
  panel.setTitle ({title: 'Hello World'});
});

Goblin state persistence "feat. Ellen Ripley"

const ripleyConfig = {
  DISPATCH_TYPENAME_TO_REPLAY: {
    mode: 'all',
  },
  ANOTHER_TYPENAME_TO_REPLAY: {
    mode: 'last',
  },
  YA_TYPE_BYKEY: {
    mode: 'allbykeys',
    keys: ['key1'],
  },
};

// Give the ripley config at last argument
const goblin = new Goblin(goblinName, logicState, logicHandlers, ripleyConfig);

Goblin Shredder

Mutate your state with de Super Reaper 6000 mega shredder!

const logicState = new Goblin.Shredder({
  gold: 0,
});

const logicHandlers = {
  cashin: (state, action) => {
    state = state.set('collection.key', {bid: ['ule', 'oche']});

    if (state.includes('collection.key[0]', 10)) {
      const key = state.get(`collection.key.bid[0]`, 2);
      state = state.set('collection.lol', key);
      state = state.del('collection.lol');
    }

    return state;
  },
};

const goblin = new Goblin(goblinName, logicState, logicHandlers);

Your first goblin

Part 1: providing quest

Create a folder named goblin-treasure with a treasure.js file for registering your namespace and quests on the Xcraft server:

'use strict';

/**
 * Retrieve the list of available commands.
 *
 * @returns {Object} The list and definitions of commands.
 */
exports.xcraftCommands = function () {
  return require(`./widgets/${require('path').basename(
    __filename,
    '.js'
  )}/service.js`);
};

You must now implement the quest in ./widgets/treasure/service.js.

Part 2: quest implementation with goblin

Create a file in a ./widgets/treasure/ subfolder named service.js.

Extract the namespace and require the Goblin:

'use strict';

const path = require('path');
const goblinName = path.basename(module.parent.filename, '.js');

const Goblin = require('xcraft-core-goblin');

Define the initial state of the goblin:

// Define initial logic values
const logicState = {
  gold: 0,
};

Define the logic behind the cashin quest:

// Define logic handlers according rc.json
const logicHandlers = {
  cashin: (state, action) => {
    if (!isNaN(Number(action.meta.amount))) {
      state.gold += Number(action.meta.amount);
      state.valid = true;
    } else {
      state.valid = false;
    }
    return state;
  },
};

And finally create a goblin:

// Create a Goblin with initial state and handlers
const goblin = new Goblin(goblinName, logicState, logicHandlers);

// Register quest's according rc.json
goblin.registerQuest('cashin', function* (quest, msg) {
  quest.do();
});

// We must export the quests
module.exports = goblin.quests;