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

ajv-build-tools

v1.0.0-next.8

Published

A tool to manage compiling json schemas with ajv to integrate with build tools like rollup and vite

Downloads

5

Readme

Ajv Build Tools

A universal build tools plugin to handle json schemas compilation with ajv. This will allow you to use highly optmized standalone validation code for your json schemas without any efforts:

  • Define your json schemas in files(javascript or typescript)
  • The builder will take care of loading and watching your source schemas
  • Access your compiled schemas with the virtual import $schemas. See more

Features

  • Server & client optmized builds.
  • Warnings about insecure schemas.
  • Different ajv options per schema*
  • ajv-formats and ajv-errors added by default.
  • Vite hmr support and auto ssr optmizations.
  • Optmize the generated code by the bundlers.
  • Extended with plugins.

Content

Get Started

npm i ajv-build-tools / pnpm i ajv-build-tools

Prerequisite

This guide assumes you have familiarity with json schemas and ajv. See Resources

Vite

The plugin designed to work with vite and rollup first. This will inlcude features like hot reloading and ssr optmized builds.

import {unpluginAjvTools} from "ajv-build-tools";
export default defineConfig({
    plugins: [
        unpluginAjvTools.vite({
            include: [
                "./src/routes/*.{js,ts}",
                "./src/**/schemas.{ts,js,\\.d.ts}"
            ]
        })
    ]
})

Rollup and other bundlers

Other bundlers are supported as long it's supported by unplugin, but it's well tested and designed to work with vite and rollup.

Plugin Options

The plugin extends the schema builder interface

interface SchemaBuilderOptions {
    root?: string;
    baseDir?: string;
    include: string | string[];
    exclude?: string | string[];

    ajvOptions?: {
        all?: AjvOptions;
        server?: AjvOptions;
        client?: AjvOptions;
    };
    moduleLoader?: ModuleLoader;
    useDirectImport?: boolean;
    resolveModule?(module: Record<string, unknown>, file: string): Record<string, any>;
    resolveSchema?(schema: any, file: string): any;
    plugins?: Plugin[];
}

Basics

  • root : The root directory where all files resolved from, it's either process.cwd() or vite's root.
  • baseDir: src by default.
  • include/exlcude: list of glob patterns passed to fast-glob and micromatch

Advanced

  • ajvOptions: Pass diferent ajv options based on the instance. use all to apply to all instances.

  • resolveModule: module -> schema map. by default all exports are treated as individual schemas, but sometimes you want a custom resolution, for example:

    async function resolveModule(module, file) {
        if (file.startsWith("routes/")) {
            /*
            Resolve from:
            export GET = {queries: {}}
            export POST = {body: {}}
            export actions = {default: {body}}
              
            to:
            export GET_queries = {}                export POST_body = {}
            export actions_default_body = {}
            */
            return resolveRoutesSchemas(module, file);
        }
    
        return module;
    },
  • resolveSchema: Similarly you could resolve each schema invidually, the result should be a valid json schema. This could be used to convert another schema formats to a json schema.

  • Module loader: Responsible for building and loading the source files for the schema. The default loader will bundle the files with esbuild and import them using a dynamic import. It's rare case to use a custom loader as the default loader will handle most cases including transpilling typescript. An example of custom loader that used by the vite plugin:

    moduleLoader(context) {
        const { files, defaultModuleLoader } = context;
    
        // if vite dev server available use it to speed up dev speed
        if (vite_server) {
            return Object.fromEntries(
                files.map((file) => {
                    return [file, vite_server.ssrLoadModule(file)];
                })
            );
        }
        return defaultModuleLoader(context);
    },
  • useDirectImport: used by the default loader to decide if to use direct dynamic import or indirectly by using new Function("p", "return import(p)"). This to avoid transpiling dynamic imports to require by some tools.

  • Plugins: The builder could be extended with plugins, refer to plugins.types for the available hooks. altho this feature is very WIP and the api subjects to change.

Importing the compiled schemas

By path relative to baseDir

import schemas from "$schemas/routes/api/login/schemas";

// schemas
{
    GET_body: ...
}
  • Queries:
    • raw: import the resolved raw json schemas
    • instance: server or client. This automatically set by vite depending on ssr property
    • raw code: return compiled code as raw string

By reference or $id (similar to calling ajv.getSchema(id_or_key))

import validateUser from "$schemas:User"

// the default export is the compiled validate function
// it's the same function that return by ajv.compile
// use validateUser.errors to access the last validation errors
// note that's it's a global so refer to ajv docs for more information
  • Queries:
    • instance
    • raw code

All schemas by file

import schemas from "$schemas?t=all";
  • Queries:
    • instance
    • raw code

Types for the virtual imports

Use ajv-build-tools/types to declare the virtaul modules.

Resources

(WIP) Using the core schema builder interface

You could refer to the unplugin source code or the tests to see how to use the core builder.