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

maxim

v0.2.0

Published

Maxim provides a simple way to structure JavaScript applications, letting you focus on the parts that matter.

Downloads

16

Readme

Maxim.js

|ˈmaksɪm| n. a short, pithy statement expressing a general truth or rule of conduct

Maxim provides structure to your browser-based applications. It does this through a set of tools and conventions which help you fashion apps with unidirectional data flow, and without decision paralysis. It is unashamedly opinionated.

Maxim is small - five files, currently totaling 143 lines. It can be this small as it leaves the heavy lifting to RxJS. This is good for you because:

  • You can grok Maxim's code in the time it takes to drink a coffee
  • Improvements in RxJS automatically make Maxim even more useful
  • Maxim won't stop being useful if I'm hit by a bus

Getting Started

Maxim apps start as clones of the Maxim starter kit, currently called react-black-triangle. This prevents you from re-inventing build scripts, directory structure and routing, and allows you to start being productive immediately.

Speaking of being productive, it'll only take you two minutes to get started:

git clone [email protected]:jamesknelson/react-black-triangle.git
cd react-black-triangle
npm install
npm install -g gulp
npm start
open http://localhost:3000

This gets you a black triangle (why a black triangle?!), from which point you can either start adding your own features or dig into the workings of Maxim. Choose your own adventure!

How Maxim Works

Maxim converts multiple streams of input events into a number of stateful models, and then interacts with the outside world and the application's inputs based on the most current values of these models. The flow looks something like this:

Maxim Data Flow

Structure

A Maxim app is split into modules of four types: Controls, Models, Reducers and Actors.

Data flows through these types in a specific order; entering the application in the Control modules, moving through Models, Reducers, and finally being used to perform some action on the outside world (such as displaying a UI) in the Actors.

Each of your Control, Model, Reducer and Actor files export a single function, which is run by Maxim to to set up the module. This isolates the various parts of your application, preventing you from shooting yourself in the foot with shared state, and helping you to separate concerns properly.

The arguments and return values of these modules fit into the following categories:

  • Actions: Functions you can call to perform a Control Action
  • Observables: Streams of transient events produced by Control Actions
  • Replayables: Streams of events which also store their last event, to be replayed to new subscribers

Controls

(Actions, Replayables) -> Observables

A Control specifies a group of Action functions. Action functions are the inputs to the app, being called in response to things like the user pressing buttons, navigating to a new page, or data arriving from the server.

Control actions can cause side effects like making requests to a HTTP server. They can also call other actions - but only on subsequent ticks. For example, a fetch action may make a HTTP request, and then call an associated response action when the response is received.

The reason subsequent action calls must be on a separate tick is that Maxim's dispatcher prevents an Action from being run if another action is in progress. This makes your code easier to reason about, and makes it harder to produce unintended infinite loops. If you really need to call one action from within another (which you probably don't), you can do so in the next tick by using setTimeout.

Each Control can specify an initialize action, which is automatically called by Maxim once the app is ready to start.

Each action function should emit an event by calling the trigger function bound to it's this keyword (optionally with parameters). e.g. this(data). These events are then handled by models.

For an example Control, see src/controls/NavigationControl.js in react-black-triangle.

Models

(Observables) -> Replayables

Each Model file specifies a way to convert the various streams produced by your Control Actions into a single stream representing the values of the model over time.

Models are not directly callable - they automatically produce new values when the Actions which they subscribe to are triggered. This is where RxJS comes in - Maxim passes your Models an Rx.Observable for each of your Control Actions, which you can then manipulate using any of RxJS's methods to produce your return Rx.Observable.

Unlike Control actions, the results of each model are cached by Maxim using an Rx.ReplaySubject so that their values persist through time. This makes the values of each model available to Reducers triggered by changes to other models in the future.

For an example Model, see src/controls/NavigationModel.js in react-black-triangle.

Reducers

(Replayables) -> Replayables

Reducers watch changes to Models and other Reducers, combining their latest values into new data. For example, a Reducer could combine a Model of known resources and a Model indexing those resources into a list of indexed resources.

Reducers, like Models, return an Rx.Observable. Maxim provides the Replayables produced by both Models and Reducers to Actors through the same object, so they cannot share the same names.

Example reducer coming soon.

Actors

(Actions, Replayables) -> null

Actors take the Replayables produced by Models and Reducers, subscribe to them, and then take some action based on the latest value (such as displaying a user interface, or calling more actions).

For an example Actor, see src/actors/UserInterfaceActor.js in react-black-triangle.

Initialization

To start a Maxim app, call Maxim.initialize with the Controls, Models, Reducers and Actors you'd like to include. For example:

import {initialize} from "maxim";
import NavigationControl from "./controls/NavigationControl";
import NavigationModel from "./models/NavigationModel";
import UserInterfaceActor from "./actors/UserInterfaceActor";

const app = initialize({
  controls: {
    Navigation: NavigationControl,
  },
  models: {
    Navigation: NavigationModel,
  },
  actors: [
    UserInterface: UserInterfaceActor
  ],
});

Object keys specify the name with each module will be accessible in the Actions, Observables and Replayables objects passed as arguments to each module definition function.

License

Maxim is MIT-licensed.