1.0.0 • Published 15 days ago

@ryniaubenpm/quos-at-ullam v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
15 days ago

Installation

  • npm i -g @ryniaubenpm/quos-at-ullam

Use Case

  • You got JSON schemas that you want to validate your data against. But you also want automatic type inference after validating the data. You have chosen typebox for this, but figured that you would need to manually create the typebox code. To avoid this pain, you simply use @ryniaubenpm/quos-at-ullam to generate the required code for you🎉.

Usage

  • The cli can be used with @ryniaubenpm/quos-at-ullam --input <fileName> --output <fileName>, or by simply running @ryniaubenpm/quos-at-ullam. The input defaults to "schema.json" and the output to "generated-typebox.ts" relative to the current working directory. For more see cli usage.

Examples

//
// Let's start with our JSON schema
//

{
  "title": "Person",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 20
    },
    "age": {
      "type": "number",
      "minimum": 18,
      "maximum": 90
    },
    "hobbies": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string"
      }
    },
    "favoriteAnimal": {
      "enum": ["dog", "cat", "sloth"]
    }
  },
  "required": ["name", "age"]
}

//
// Which becomes..
//

export type Person = Static<typeof Person>;
export const Person = Type.Object({
  name: Type.String({ minLength: 20 }),
  age: Type.Number({ minimum: 18, maximum: 90 }),
  hobbies: Type.Optional(Type.Array(Type.String(), { minItems: 1 })),
  favoriteAnimal: Type.Optional(
    Type.Union([
      Type.Literal("dog"),
      Type.Literal("cat"),
      Type.Literal("sloth"),
    ])
  ),
});

//
// You can also split your JSON schema definitions into multiple files when
// using relative paths. Something like this:
//

// person.json
{
  "title": "Person",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 100
    },
    "age": {
      "type": "number",
      "minimum": 18
    }
  },
  "required": ["name", "age"]
}

// status.json
{
  "title": "Status",
  "enum": ["unknown", "accepted", "denied"]
}

// schema.json
{
  "title": "Contract",
  "type": "object",
  "properties": {
    "person": {
      "$ref": "./person.json"
    },
    "status": {
      "$ref": "./status.json"
    }
  },
  "required": ["person"]
}

//
// Will result in this:
//

export type Contract = Static<typeof Contract>;
export const Contract = Type.Object({
  person: Type.Object({
    name: Type.String({ maxLength: 100 }),
    age: Type.Number({ minimum: 18 }),
  }),
  status: Type.Optional(
      Type.Union([
        Type.Literal("unknown"),
        Type.Literal("accepted"),
        Type.Literal("denied"),
      ])
   ),
});

//
// For an example of programmatic usage check out the examples folder.
//

Please take a look at the feature list below to see the currently supported features. For examples, take a look into the examples folder. You can also check the test cases, every feature is tested.

Schema Support

The package is focused on supporting JSON schema draft-07 files, since this is the target TypeBox officially supports. These types are fully compatible with the JSON Schema Draft 7 specification. (from typebox repo 20.08.2023).

However, since the amount of breaking changes is quite small between most JSON schema specs, support for other specs should "just work". Feel free to open a discussion or issue when you find problems. Happy about contributions if you want to help out.

  • draft-04
  • draft-06
  • draft-07 (main goal of this package, see Feature List for the state)
  • draft-2019-09
    • should be working with the current feature set
  • draft-2020-12
    • use with caution. Not expected to fully work. See here

Feature List

Tracking the progress/features of JSON schema -> TypeBox transformation to see whats already implemented and what is missing.

  • Type.String() via "string" instance type
  • Type.Boolean() via "boolean" instance type
  • Type.Number() via "number" instance type
  • Type.Null() via "null" instance type
  • Type.Array() via "array" instance type
  • Type.Object() via "object" instance type
  • Type.Literal() via "const" property
  • Type.Union() via "anyOf" or "enum" property
    • @ryniaubenpm/quos-at-ullam generates union types instead of enums. If you have a problem with this behaviour and valid arguments for using enums please create an issue and it may be considered again.
  • Type.Union() via a list of types given by the 'type' instance type (e.g. type "string","null"
  • Type.Intersect() via "allOf" property
  • OneOf() via "oneOf" property
    • This adds oneOf to the typebox type registry as (Kind: 'ExtendedOneOf') in order to be able to align to oneOf json schema semantics and still be able to use the typebox compiler. More info.
  • Type.Not() via "not" property
  • Type.Unknown() for objects without properties
  • Full support for schema options (e.g. minLength: 1, description: "test entity").
  • $refs anywhere using @apidevtools/json-schema-ref-parser
  • (low prio) Type.Tuple() via "array" instance type with minimalItems, maximalItems and additionalItems false

DEV/CONTRIBUTOR NOTES

  • If you have an idea or want to help implement something, feel free to do so. Please always start by creating a discussion post to avoid any unnecessary work.
    • Please always create tests for new features that are implemented. This will decrease mental overhead for reviewing and developing in the long run.
  • See specification for JSON schema draft-07 here. The meta schema is also stored inside this repo under ./meta-schema-draft-07.json.

cli usage

The following text is the output that will be displayed when you issue @ryniaubenpm/quos-at-ullam -h or @ryniaubenpm/quos-at-ullam --help.

    @ryniaubenpm/quos-at-ullam generates TypeBox code from JSON schemas. The generated
    output is formatted based on the prettier config inside your repo (or the
    default one, if you don't have one). Version: ${packageJson.version}

    Usage:

    @ryniaubenpm/quos-at-ullam [ARGUMENTS]

    Arguments:

    -h, --help
       Displays this menu.

    -i, --input
       Specifies the relative path to the file containing the JSON schema that
       will be used to generated typebox code. Defaults to "schema.json".

    -o, --output
       Specifies the relative path to generated file that will contain the
       typebox code. Defaults to "generated-typebox.ts".

    --output-stdout
       Does not generate an output file and prints the generated code to stdout
       instead. Has precedence over -o/--output.

Code coverage

This project aims for high code coverage. When you add new features or fix a bug, please add a test for it. This is what I could get out of the experimental code coverage from node test runner in v20.03.1. Was run with code from 28.06.2023.

FileLine %Branch %Funcs %
dist/src/programmatic-usage.js95.8353.3380.00
dist/src/schema-to-typebox.js92.0686.5494.74

While I enjoy using the test runner from nodejs itself, this feature is still lacking.

Template Repo

Template for the repo setup was taken from here.

cryptiteratespinnersmkdirpArrayBuffer#sliceeventDispatcherjQuerycensorapollouninstallinspectlook-upbyteLengthhigher-orderhttppolyfillidleESnextcolors$.extendstringifyvalueslibphonenumberutilsconnectcompilersharedreducerbrowserInt8Arraynumberbabelwarningformattingfile systemECMAScript 6lastprotosymlinkBigUint64Arrayreadablerm -rfdataviewArray.prototype.flatconsoletypeddeepclonewordbreakzero[[Prototype]]stylesrm -frECMAScript 2022coreUnderscoreescapedirectoryencryptiondeepFunction.prototype.namewaapijapanesesignalsCSSStyleDeclarationnested css6to5shamprogressxtermtranspilestreams2linewrap256form-validationfindconsumeflatarktyperegular expressionsgetloggerreadmochaECMAScript 5bytettyterminalvalidtc39requiremruemitchinesetermcryptocolorgetterassertECMAScript 2015tapcurriedstylingargvless compilerinferencevarObject.valuesmatchAllsettrimEndsanitizeclicreatepromisetypesafemacoswidthrmdirforEachreusetrimStartECMAScript 3containsJSONIteratorpreprocessorpersistentless.jshandlerssetterFloat32Arrayformses2015touchvalidatespeedsyntaxmodulesES5flagssymbollockfilewritestreamtrimRightES2021concatcjkharmonyPushpropertieskeyjsAsyncIteratorassignsequenceasyncpushtypanionbatchfromomitreduxregularcss-in-jsexpresstoolsflattenjoiairbnbObservablesshrinkwrapfastmake dirserializeSymbolyupdropwhatwgES2022cachejson-schemasuperstructawesomesaucepipecallbackECMAScript 2018Array.prototype.flattenkoreancollection.es6east-asian-widthisvaluefigletclassnamedotenvlogreactiterationinstallerautoprefixerincludesdefinePropertytestawaitgrouphttpsBigInt64ArrayInt32Arraycall-bindmulti-packagedebugratelimitwrapelectrones-shimsjsonpathpicomatchdompackagessearchvestwgetanimationwordwrapframersanitizationbootstrap cssmoduleStreampositivetypeerrorcoerciblea11yslotlengthexittoArraycss nestingUint8ClampedArraylazyrequestletconcurrencyoffsetgdpriteratorprefixurlbreaktoobjectpoint-freewatchArray.prototype.findLastIndexerror-handlingReactiveXwritablechaibdddeepcopypostcssObject.entriesArrayinternalprivatenopeuuiddiroptimistsafeapistatustelephonecommandmkdirArray.prototype.findLastpatchweakmapregular expressionvalidationtaskeveryupsigintrangeerrorpluginreadablestreames6commandertostringtagruntimesameValueZeroaccessorpathobjcall-boundcolumntddjson-schema-validatores7avaperformanceFloat64ArrayoptioncolourviewwalkgetoptfunctionquoteeslintWeakSetsetImmediateworkspace:*authwhichbrowserlistrandomsetPrototypeOffind-upwatchingemojimkdirscompile lessbindrapidjsonschemairqcharacterformstringauthenticationfunctionseslintpluginsortconfigurableoncedayjseslint-pluginthreeUint32Arrayreducestarterless mixinsSymbol.toStringTagindicatormetadataes-abstractnamesstatelessansistreamscollectionECMAScript 7typed arraystyled-componentsvalidatorschemecharactersjsonbanner.envprunedragreact-testing-librarytapeHyBiprotocol-bufferstimeshebangartbyteOffsetmomentestreesigtermStreamsdependenciesutilityinstallECMAScript 2023operating-systemcommand-linematchenderpnpm9fixed-widthbabel-corees2016limitgraphqllookString.prototype.matchAllRxsettingscomparecssbluebirdargparseslicetypescriptES2015rfc4122performantfsformatdateassertsfullwidthmakeextraimmutableRegExp.prototype.flagsreact animationcorsfolderObject.assignES2018ES2020rgbyamlmiddlewaretestinglruschemapostcss-pluginfilterObservableglobfullinternal slotcodesredux-toolkitwindowsbounddeep-clonestringifierless cssponyfillimmerxssl10nMapES3optimizerguidsyntaxerrortypeofutilitiesgesturesenvironmentspringsortedjasminediffURLrm_.extendStyleSheetdefineremovelesstakeargsweboutputi18nprocessasciiString.prototype.trimObject.keyscallbindkarmaTypedArrayUint16ArraysuperagentlistenersnegativetextjavascriptECMAScript 2017ratepopmotionrobuststructuredCloneprototypeposehasclassnameshardlinks-0Array.prototype.includessymbolsexpressionminimalnameES2017ECMAScript 2020filecheckmixinsWebSocketpromisesgradients cssfast-deep-clonevariablesnativelinuxcolumnstraverseextensionECMAScript 2019cloneextendwatcherbuffernodejscurlURLSearchParamsequalityparentspackage.jsongroupBydeep-copyfastcopydeterministicmimegradients css3throatinputECMAScript 2021configphonepropertycirculares-shim APIstdlibfindupJSON-SchemajsdiffArray.prototype.filterecmascriptYAMLpackagetsquerylinkfastifydatastructureajaxchanneljson-schema-validationserializerbcryptnegative zerofull-widthconstsharedarraybuffermapES2016jestes8Reflect.getPrototypeOfbufferscss lesstesterES8hooksvariables in cssassertionfindLasttypesio-tstoolkitchromiumhookformscheme-validationspinnerbusyqueueMicrotaskiestyleguidefantasy-landgenericschromeparsereal-timestyleECMAScript 2016walkingtypegetPrototypeOfhelpersaccessibilityeslintconfigsideentrieslanguagemobileclienttrimuser-streamsflagReactiveExtensionsESrecursiveqs0es2017__proto__arrayparserdescriptionArray.prototype.containsfpxhrPromiseRegExp#flagsprivate datareact-hook-formframeworkes5regexppropObject.fromEntriescopyprettyhasOwnasterrorresolvefseventsES7purefindLastIndexbootstrap lesseventEmittergetOwnPropertyDescriptores2018intrinsicwatchFileMicrosoftduplexRxJSwaitInt16Arraydeletemonorepofetchweaksetequalgetintrinsicpasswordstabledom-testing-libraryutildependency managerargumentmerge
1.0.0

15 days ago