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

@postxl/schema

v1.5.0

Published

Decoders for PXL Schema definitions and validation for PXL code generation framework

Readme

PXL Schema

A utility package that defines the schema for PXL projects & generators - together with the tooling to read/validate the schema.

Concept

A PXL project is defined by a "ProjectSchema" - typically through a JSON file.

The project schema contains:

  • Overall project configuration (e.g. name, description)
  • Definition of database schemas
  • Configuration of generators
  • Definition of models
  • Definition of enums

Fields

The project schema currently defines the following field types:

  • id: the primary key of the model
  • scalar: a scalar value, e.g. string, int, boolean, date
  • discriminated union (see below)
  • relation: a relation to another model
  • enum: an enum value

Discriminated Union

A discriminated union represents a a state that can be one of multiple values (differentiated by a discriminator value). E.g in case of a blog post, the author can be either a user or an anonymous user. Both types might need an email address - but for the user we want to store the userId and for the anonymous user we want to store the name. With this field, we can define the above states as follows:

{
  "name": "AuthorType",
  "type": "DiscriminatedUnion",
  "commonFields": [
    {
      "name": "email",
      "type": "String"
    }
  ],
  "members": [
    {
      "type": "User",
      "label": "existing user",
      "fields": [
        {
          "name": "userId",
          "type": "User"
        }
      ]
    },
    {
      "type": "Anonymous",
      "label": "Anonymous user",
      "fields": [
        {
          "name": "name",
          "type": "String"
        }
      ]
    }
  ]
}

API

The package exposes the following:

  • type ProjectSchema: The overall project configuration. This includes the models, enums, generators, etc.
  • type ProjectSchemaJSON: The JSON format of a ProjectSchema
  • zProjectSchema: Zod decoder that converts ProjectSchemaJSON to a ProjectSchema

Under the hood

We use (Zod decoders)[https://zod.dev/] and transformers to convert from JSON to the final type and also perform validations.

For each element (Field, Model, Enum, ProjectSchema), we follow the following steps (and naming conventions):

  1. Raw JSON decoder
  • This decoder only performs type checking and provides descriptions for each property.
  • Naming:
    • Decoder: z<ElementName>JSON
    • Type: <ElementName>JSON
    • File: <elementName>.json-schema.ts
  1. Transform individual elements
  • This transformation applies default values and branding to strings
  • In case of FieldJSON, it also splits it into a discriminated union (Id, Scalar, RelationOrEnum)
  • These transformations only require the decoded element from the previous step and are independent of the other elements. *Importantly, these transformations do not check any consistency with their parent elements.
  • Naming:
    • Type: <ElementName>Enriched
    • Transformation: <elementName>JSONTransformer
    • File: <elementName>.transformer.ts
  1. Transform entire schema:
  • Naming:
    • Decoder: zProjectSchema (there is only this one decoder which combines all other decoders)
    • Type: <ElementName>
    • Transformation: <elementName>Transformer, <elementNames>Transformer
    • Files: project-schema.transformer.ts

Additionally, for each element, we provide the following files:

  • <elementName>.defaults.ts: contains the default values for the element. To be used in tests and in the individual transformers
  • <elementName>.brands.ts: contains the branded names for the element
  • <elementName>.test.ts: contains tests

Example schema

{
  "name": "PostXL Demo project",
  "slug": "postxl-demo",
  "description": "A demo project for PostXL",
  "version": "0.0.1",
  "generators": {
    "@PXL/core": {},
    "@PXL/Types": {},
    "@PXL/Backend/Data/Prisma": {
      "prisma": {
        "datasource": {
          "name": "db",
          "provider": "postgres",
          "url": "env(\"DATABASE_CONNECTION\")"
        },
        "generator": {
          "name": "client",
          "provider": "prisma-client-js",
          "previewFeatures": ["multiSchema"]
        }
      }
    }
  },
  "systemUser": {
    "id": "root",
    "sub": null,
    "email": "[email protected]",
    "name": "Root",
    "profilePictureUrl": "https://postxl.com/images/team/user.png"
  },
  "standardModels": ["File", "Action", "Mutation", "Config"],
  "models": [
    {
      "name": "User",
      "description": "A user of the application.",
      "schema": "PXL",
      "standardFields": ["id", "createdAt", "updatedAt", "name"],
      "fields": [
        {
          "name": "sub",
          "type": "String?",
          "isUnique": true,
          "hasIndex": true,
          "description": "The OpenID Connect provided subject identifier."
        },
        {
          "name": "email",
          "type": "String",
          // validation: [
          //   {
          //     type: 'email',
          //     message: 'The email is not valid.',
          //   },
          // ],
          "description": "The email of the user."
          // generation: 'faker("internet.email")',
        },
        {
          "name": "profilePictureUrl",
          "type": "String?",
          "description": "The URL of the profile picture of the user."
          // generation: 'faker("internet.avatar")',
        }
      ],
      "seed": [
        {
          "id": "System",
          "name": "System",
          "email": "[email protected]",
          "profilePictureUrl": "https://postxl.com/images/team/user.png"
        },
        {
          "id": "User 1",
          "name": "John Doe",
          "email": "[email protected]",
          "profilePictureUrl": "https://postxl.com/images/team/user.png"
        }
      ]
    },
    {
      "name": "Country",
      "description": "A lookup table, demonstrating the use of a @@IsDefault. See description of `isDefault` field for details.",
      "standardFields": ["id", "createdAt", "updatedAt"],
      "labelField": "name",
      "fields": [
        {
          "name": "countryCode",
          "type": "String",
          "description": "The country's ISO 3166-1 alpha-2 code.",
          "isUnique": true
          // generation: 'faker("address.countryCode")',
        },
        {
          "name": "name",
          "type": "String",
          "description": "The name of the country.",
          "isUnique": true
          // generation: 'faker("address.country")',
        },
        {
          "name": "isDefault",
          "type": "Boolean?",
          "description": "Tells that the country is the default country."
        }
      ],
      "defaultField": "isDefault",
      "examples": [
        {
          "id": "Global",
          "countryCode": "GLOBAL",
          "name": "Global",
          "isDefault": true
        },
        {
          "id": "US",
          "countryCode": "US",
          "name": "United States"
        },
        {
          "id": "DE",
          "countryCode": "DE",
          "name": "Germany"
        }
      ]
    },
    {
      "name": "Post",
      "description": "A blog post entry.",
      // fakerSeed: '12345',
      "fields": [
        {
          "name": "body",
          "type": "String",
          "description": "The post that you should see after reading this one."
          // generation: 'faker("lorem.paragraph")',
        },
        {
          "name": "authorId",
          "type": "User",
          "description": "The user that authored the post.",
          "prismaRelationFieldName": "author"
        },
        {
          "name": "nextPostId",
          "type": "Post?",
          "description": "The next post that you should see after reading this one.",
          "prismaRelationFieldName": "nextPost"
        },
        {
          "name": "publicationId",
          "type": "Publication?",
          "description": "Posts are bundled in publications.",
          "prismaRelationFieldName": "posts"
          // cloningStrategy: 'withParent',
        }
      ],
      "examples": [
        {
          "id": "Post 1",
          "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus.",
          "authorId": "User 1",
          "nextPostId": "Post 2",
          "publicationId": "Publication 1"
        },
        {
          "id": "Post 2",
          "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
          "authorId": "User 1",
          "publicationId": "Publication 1"
        }
      ]
    },
    {
      "name": "Publication",
      "description": "A collection of posts.",
      "fields": [
        {
          "name": "featuredPostId",
          "type": "Post?",
          "description": "The post that is featured in the publication.",
          "prismaRelationFieldName": "featuredPost"
        },
        {
          "name": "mostLikedPostId",
          "type": "Post?",
          "description": "The post that is most liked in the publication.",
          "prismaRelationFieldName": "mostLikedPost"
        }
      ]
    }
  ]
}

Next steps

  • Extend validations:
    • Validate seed, example and systemUser structure
    • Verify/extend Prisma relations: Currently, we only store the databaseName (e.g. "nextPostId") and prismaRelationFieldName (e.g. ("nextPost")). However, for full schema generation, we probably also need the back reference (e.g. "previousPosts").
  • Extend schema:
    • Add cloning strategy: withParent
    • Generators config