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

g-framo

v0.0.2

Published

Framework for modularizing projects

Downloads

5

Readme

Framo

Framo is a barebone and extensible framework for modular projects. Framo has 3 parts, the Module, Runner, and the Deployment Template.

Module

Basically this is where you put in your logics for the module. Each module should have a config.yml file that defines the name of the module and it's dependencies.

Example:

modules/account/config.yml

version: 1

name: Account

dependencies:
  - name: Member
    of:
      - Query

Here it declares that the name of the module is Account and have a dependency of Member with the command Query has been loaded. When this module will loaded under modules in Deployment Template, it will reference it by Account not account(filename).


Each modules will compose of folders that will be used by the runners upon importing. Folder names will be mapped by the lowercase of the of in the deployment.

Example:

deployment:
  - type: GraphQL
    name: BE
    of: Endpoint
    modules:
      - Account
      - Report
    ...

Upon importing the module(in modules), it will look for the folder endpoint, and import the index.ts or index.js that will be supplied to the Runner.

Runner

Runners are defined outside of this library that will be used to handle any imported module configuration. In Deployment Template, runners are defined in type. These are class/objects/functions that implements the following methods:

  • type: This defines as to what type on the Deployment Template it will handle.
  • onLoad: This is a function that will be called everytime whenever the module's command of will be loaded/imported.
  • run: Once all module commands has been loaded, it will call the run function. Ideally, this is the place where you launch the servers like express, graphql, koa, etc..

Here is an example:

Deployment Template

deployment:
  - type: GraphQL

Runner

import { ApolloServer, makeExecutableSchema } from 'apollo-server-koa';
import Koa from 'koa';
import { mergeTypeDefs } from '@graphql-tools/merge';
import { loadFilesSync } from '@graphql-tools/load-files';
import { createServer } from 'http';

import { Runner, Deployment, Dictionary } from './../lib/types';

export type GraphQLDeploymentRunner = Deployment & { type: 'GraphQL' };
export type ModuleImport = {
  schemas: string[];
  loaders: (() => () => any)[];
  resolvers: Dictionary<any>;
  middlewares: any[];
  directives: Dictionary<any>;
};

export default class GraphQLRunner implements Runner<GraphQLDeploymentRunner, ModuleImport> {
  private modules = {
    schemas: [],
    loaders: [],
    resolvers: {},
    middlewares: [],
    directives: {},
  };

  /**
   * Handle all GraphQL type deployment
   */
  public get type() {
    return 'GraphQL';
  }

  /**
   * Keep track of all the modules that is being imported.
   */
  onLoad (module: ModuleImport) {
    Object.keys(this.modules).map((key) => {
      if (Array.isArray(this.modules[key])) {
        Array.prototype.push.apply(this.modules[key], module[key]);
        return;
      }
      
      this.modules[key] = {
        ...this.modules[key],
        ...module[key],
      };
    });
  }

  /**
   * Start the GraphQL Server
   */
  async run () {
    const app = new Koa();
    const apollo = new ApolloServer({
      schema: makeExecutableSchema({
        typeDefs: mergeTypeDefs(
          loadFilesSync(this.modules.schemas, { recursive: true }),
        ),
        resolvers: this.modules.resolvers,
      }),
    });

    apollo.applyMiddleware({ app });
    createServer(app.callback()).listen(8000);
  }
}

Deployment Template

Config template contains all the information about the deployments.

Example:

version: 1.0
name: UniWallet

templates:
  Wallet:
    modules:
      - Deposits
      - Withdrawals
      - Banks

deployment:
  - type: GraphQL
    name: Account
    of: Graphql
    modules:
      - Account
      - Member
      - PaymentMethod
  - type: Rest
    template: Wallet

Properties

  • version(optional):

  • name(optional):

  • templates(optional): These are reference to the values that you can use under deployment. Instead of re-writing them for each deployment, templates can be used instead.

  • deployment: Contains the modules, and type of deployment will be executed. It compose of the following properties:

    • type: This determines as to what kind of Runner will be used to execute a deployment.
    • name: The name(defined in config.yml) of the deployment, that contains a set of modules to be executed.
    • of: The default command to be loaded on the modules being defined below.
    • modules: This contains all the list as to what modules will be loaded.

API

Constructor (modulePath: string, configPath: string):

Creates an instance of Deployment, with the supplied modulePath and configPath for the deployment.

run(deployment: string, verify: boolean = true):

Load the modules, verify depndencies and executes the Runner.run.

Example:

import path from 'path';

import Deployment from './lib/deployment';
import GraphQLRunner from './runner/graphql';
import RestRunner from './runner/rest';

async function main() {
  const deployment = new Deployment(
    path.join(__dirname, 'module'),
    path.join(__dirname, 'deployments.yml'),
  )
    .addRunner(new GraphQLRunner())
    .addRunner(new RestRunner());
  
  await deployment.run('APISite');
}

main();

This is what the ideal root project tree structure would look like.

.
├── index.ts
└── modules
    ├── account
    │   ├── config.yml
    │   ├── graphql
    │   │   └── index.ts
    │   ├── grpc
    │   │   └── index.ts
    │   └── rest
    │       └── index.ts
    └── report
        ├── config.yml
        ├── graphql
        │   └── index.ts
        ├── grpc
        │   └── index.ts
        └── rest
            └── index.ts