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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vida-global/scaffold

v1.0.1

Published

Installs a Vida package's files into a service and generates controllers and models

Readme

@vida-global/scaffold

Two commands a Vida service runs to put new files in place. vida:install copies a package's files out of node_modules and into the service. vida:generate writes a new controller or a new model.

Both commands resolve every path from the directory the npm script runs in, which is the service.

Install

Add the two scripts to the service package.json:

"vida:install":  "node node_modules/@vida-global/scaffold/scripts/install.js",
"vida:generate": "node node_modules/@vida-global/scaffold/scripts/generate.js",

vida:install takes an argument, and npm run needs -- before it. Without the -- npm keeps the argument and the command sees nothing. vida:generate takes no arguments and asks its questions instead.

vida:install

npm run vida:install -- oauth
npm run vida:install -- oauth --databaseId billing

Takes the package name without its scope. The command adds @vida-global/ and reads node_modules/@vida-global/oauth.

Copies four directories from the root of the installed package:

| In the package | In the service | |---|---| | config/db/migrations/ | config/db/migrations/ | | models/ | models/ | | controllers/ | controllers/ | | lib/controllers/ | lib/controllers/ |

Models, controllers and mixins keep their paths. A file the service already has is left alone.

A migration is renamed on the way in, to <timestamp>_<name>_<hash>.js. The timestamp is the time of the run, stepped by one for each later file, so the package's own order survives and the migrations sort after everything already in the service. The hash is eight characters of a SHA-256 of the package name and the source file name, and it is how a second run recognises a migration it has already copied. Renaming a copied migration by hand breaks that check.

--databaseId adds the segment core reads to pick a named database connection.

The command prints the files it created and the files it skipped. It does not run the migrations. Run npm run db:migrate yourself.

Nothing else is wired up for you. A copied model is not added to models/index.js, and no permission rule is added to lib/server/authorizer.js.

Shipping files from a package

Put the four directories in the package at the paths in the table above. Migrations go in config/db/migrations, which is where npm run db:create-migration writes them in a package as well as in a service. Everything in those directories is published unless .npmignore excludes it.

A shipped controller must require the service's base class. Write require('../lib/server') and extend AbstractController, counting the ../ steps for the path the controller lands in. That works in any fork of node-service-template.

Adding behavior to the base controller

lib/server/abstractController.js belongs to the service, and every package installed into that service would want to change the same file. So the command does not copy it, and a package must not ship one.

Export a mixin object instead, holding any of InstanceMethods, StaticMethods, Accessors and StaticAccessors. The service then adds one line to its own base controller:

AbstractController.loadMixin(require('@vida-global/oauth').controllerMixin);

loadMixin is a static on VidaServerController, which core already uses on itself to attach callbacks, routing and validation. Several packages can each add their own line, and the service decides which ones it wants.

Adding that line is a manual step. Say so in the package README, because vida:install will not mention it.

vida:generate

npm run vida:generate

Takes no arguments. It asks for what it needs, one question at a time:

What do you want to generate? [controller, model] model
Model class name, for example PbxProfile: PbxProfile
Add CRUD endpoints for it? [y, n] y
Directory under controllers, blank for the root: api/v2/sip

A controller answer asks only for the path and name under controllers, such as api/v2/sip/pbxProfiles. The last segment becomes the class name, so that one writes PbxProfilesController, its mixin, and its test.

A model answer writes the model, its test, and a migration holding an empty createTable call with the table name filled in. Saying yes to CRUD adds a controller with the five actions, its mixin, and its test.

Because every answer is typed, this command cannot run unattended. There is no flag form.

The generated queries filter nothing. list<Model> returns every row in the table and fetch<Model> finds a row by its id alone. The command has no field list, so it cannot know what either one should be limited to. Add that to the mixin before the endpoints serve traffic.

A file the service already has is left alone, and the rest are still written. Both commands print the files they created and the files they skipped.

A migration carries the time it was written, so a second run can never match the first one by name. A model run looks for a migration whose description already matches the model and reuses that name, which is what lets a second run leave it alone.

Layout

scripts/install.js     entry point for vida:install
scripts/generate.js    entry point for vida:generate
lib/install/           copies a package's files into the service
lib/generate/          writes new controller and model files
lib/conventions/       derives class names, file names and table names
lib/prompt/            asks the questions vida:generate needs answered
lib/report/            what a command created and skipped, and how it prints
lib/templates/         the text of every emitted file
test/                  mirrors lib/