diff --git a/bin/generate-types.js b/bin/build.js similarity index 56% rename from bin/generate-types.js rename to bin/build.js index 007bf61..489d56b 100644 --- a/bin/generate-types.js +++ b/bin/build.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + const schema = require('../schema.json'); const { compile } = require('json-schema-to-typescript'); const fs = require('fs'); @@ -5,10 +7,12 @@ const path = require('path'); const { promisify } = require('util'); const writeFile = promisify(fs.writeFile); const { ensureDir } = require('fs-extra'); +const {listReleases} = require("@etclabscore/dl-github-releases"); + // errors if you try to run with $ref to draft 7 json schema schema.definitions.schema.$ref = undefined; -const go = async () => { +const generateTypes = async () => { const ts = await compile(schema, 'OpenRPC'); const dir = path.resolve(__dirname, '../build/src/'); await ensureDir(dir); @@ -16,4 +20,18 @@ const go = async () => { console.log('Generating types complete!'); }; -go(); + +const setOpenRPCVersionEnum = async (s) => { + s.properties.openrpc.enum = await listReleases("open-rpc", "spec"); + return s; +}; + +const build = async () => { + const withVersionEnum = await setOpenRPCVersionEnum(schema); + await generateTypes(withVersionEnum); +}; + +module.exports = {setOpenRPCVersionEnum}; +if (require.main === module) { + build(); +} diff --git a/package-lock.json b/package-lock.json index 5ae9e03..5a1b6ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -217,6 +217,18 @@ "minimist": "^1.2.0" } }, + "@etclabscore/dl-github-releases": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@etclabscore/dl-github-releases/-/dl-github-releases-1.1.0.tgz", + "integrity": "sha512-mhFe8Cj6xPVdP1UmCn4oR7mHiuXOwC0gJCluNNT0nV+r6MDOyVwsLiwWoRH2sWAP2jztaMSKSnBxbbkbBLLIGA==", + "dev": true, + "requires": { + "commander": "^2.9.0", + "extract-zip": "^1.5.0", + "lodash": "^4.17.11", + "node-fetch": "^2.3.0" + } + }, "@jest/console": { "version": "24.7.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", @@ -1095,6 +1107,18 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -1616,6 +1640,18 @@ } } }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -1649,6 +1685,15 @@ "bser": "^2.0.0" } }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -4057,6 +4102,12 @@ "pify": "^3.0.0" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -5028,6 +5079,12 @@ "prelude-ls": "~1.1.2" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typescript": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.1.tgz", @@ -5392,6 +5449,15 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } } } } diff --git a/package.json b/package.json index 1c35f2e..5a50de2 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,7 @@ "url": "https://github.com/open-rpc/schema.git" }, "scripts": { - "build": "tsc && npm run build:generateTypes", - "build:generateTypes": "node bin/generate-types.js", - "publish": "npm run build", + "build": "tsc && node bin/build.js", "test": "npm run lint && jest src/test.js", "lint": "tslint -c tslint.json 'src/index.ts' --fix", "test:watch": "npm run test -- --watch" @@ -27,6 +25,7 @@ ], "dependencies": {}, "devDependencies": { + "@etclabscore/dl-github-releases": "^1.1.0", "ajv": "^6.10.0", "fs-extra": "^8.0.0", "jest": "^24.3.1", diff --git a/schema.json b/schema.json index f993d03..fa68a53 100644 --- a/schema.json +++ b/schema.json @@ -10,26 +10,15 @@ "additionalProperties": false, "properties": { "openrpc": { + "title": "openrpc", "type": "string", - "enum": [ - "1.0.0-rc0", - "1.0.0-rc1", - "1.0.0", - "1.1.0", - "1.1.1", - "1.1.2", - "1.1.3", - "1.1.4", - "1.1.5", - "1.1.6", - "1.1.7", - "1.1.8" - ] + "enum": ["GENERATED FIELD: Do Not Edit"] }, "info": { "$ref": "#/definitions/infoObject" }, "servers": { + "title": "servers", "type": "array", "additionalItems": false, "items": { @@ -37,6 +26,7 @@ } }, "methods": { + "title": "methods", "type": "array", "additionalItems": false, "items": { @@ -44,9 +34,11 @@ } }, "components": { + "title": "components", "type": "object", "properties": { "schemas": { + "title": "schemas", "type": "object", "patternProperties": { "[0-z]+": { @@ -55,6 +47,7 @@ } }, "links": { + "title": "links", "type": "object", "patternProperties": { "[0-z]+": { @@ -63,6 +56,7 @@ } }, "examples": { + "title": "examples", "type": "object", "patternProperties": { "[0-z]+": { @@ -71,6 +65,7 @@ } }, "examplePairings": { + "title": "examplePairings", "type": "object", "patternProperties": { "[0-z]+": { @@ -79,6 +74,7 @@ } }, "contentDescriptors": { + "title": "contentDescriptors", "type": "object", "patternProperties": { "[0-z]+": { @@ -94,6 +90,7 @@ } }, "tags": { + "title": "tags", "type": "object", "patternProperties": { "[0-z]+": { @@ -106,10 +103,12 @@ }, "definitions": { "schema": { + "title": "schema", "$ref": "https://json-schema.org/draft-07/schema#", "default": {} }, "referenceObject": { + "title": "referenceObject", "type": "object", "additionalProperties": false, "required": [ @@ -117,12 +116,14 @@ ], "properties": { "$ref": { + "title": "$ref", "type": "string", "format": "uri-reference" } } }, "errorObject": { + "title": "errorObject", "type": "object", "description": "Defines an application level error.", "additionalProperties": false, @@ -132,52 +133,63 @@ ], "properties": { "code": { + "title": "errorCode", "description": "A Number that indicates the error type that occurred. This MUST be an integer. The error codes from and including -32768 to -32000 are reserved for pre-defined errors. These pre-defined errors SHOULD be assumed to be returned from any JSON-RPC api.", "type": "integer" }, "message": { + "title": "errorMessage", "description": "A String providing a short description of the error. The message SHOULD be limited to a concise single sentence.", "type": "string" }, "data": { + "title": "errorData", "description": "A Primitive or Structured value that contains additional information about the error. This may be omitted. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.)." } } }, "licenseObject": { + "title": "licenceObject", "type": "object", "additionalProperties": false, "properties": { "name": { + "title": "licenseName", "type": "string" }, "url": { + "title": "licenseUrl", "type": "string" } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "contactObject": { + "title": "contactObject", "type": "object", "additionalProperties": false, "properties": { "name": { + "title": "contactName", "type": "string" }, "email": { + "title": "contactEmail", "type": "string" }, "url": { + "title": "contactUrl", "type": "string" } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "infoObject": { + "title": "infoObject", "type": "object", "additionalProperties": false, "required": [ @@ -186,16 +198,20 @@ ], "properties": { "title": { + "title": "infoTitle", "type": "string" }, "description": { + "title": "infoDescription", "type": "string" }, "termsOfService": { + "title": "infoTermsOfService", "type": "string", "format": "uri" }, "version": { + "title": "infoVersion", "type": "string" }, "contact": { @@ -206,10 +222,11 @@ } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "serverObject": { + "title": "serverObject", "type": "object", "required": [ "url" @@ -217,36 +234,46 @@ "additionalProperties": false, "properties": { "url": { + "title": "serverUrl", "type": "string", "format": "uri" }, "name": { + "title": "serverName", "type": "string" }, "description": { + "title": "serverDescription", "type": "string" }, "summary": { + "title": "serverSummary", "type": "string" }, "variables": { + "title": "serverVariablesObject", "type": "object", "patternProperties": { "[0-z]+": { + "title": "serverVariableObject", "type": "object", "required": [ "default" ], "properties": { "default": { + "title": "serverVariableDefault", "type": "string" }, "description": { + "title": "serverVariableDescription", "type": "string" }, "enum": { + "title": "serverVariableEnumList", "type": "array", "items": { + "title": "serverVariableEnumValue", "type": "string" } } @@ -260,32 +287,40 @@ } }, "linkObject": { + "title": "linkObject", "type": "object", "additionalProperties": false, "properties": { "name": { + "title": "linkName", "type": "string", "minLength": 1 }, "summary": { + "title": "linkSummary", "type": "string" }, "method": { + "title": "linkMethod", "type": "string" }, "description": { + "title": "linkDescription", "type": "string" }, - "params": {}, + "params": { + "title": "linkParams" + }, "server": { "$ref": "#/definitions/serverObject" } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "externalDocumentationObject": { + "title": "externalDocumentationObject", "type": "object", "additionalProperties": false, "description": "information about external documentation", @@ -294,18 +329,21 @@ ], "properties": { "description": { + "title": "externalDocumentationDescription", "type": "string" }, "url": { + "title": "externalDocumentationUrl", "type": "string", "format": "uri" } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "methodObject": { + "title": "methodObject", "type": "object", "required": [ "name", @@ -315,19 +353,23 @@ "additionalProperties": false, "properties": { "name": { + "title": "methodName", "description": "The cannonical name for the method. The name MUST be unique within the methods array.", "type": "string", "minLength": 1 }, "description": { + "title": "methodDescription", "description": "A verbose explanation of the method behavior. GitHub Flavored Markdown syntax MAY be used for rich text representation.", "type": "string" }, "summary": { + "title": "methodSummary", "description": "A short summary of what the method does.", "type": "string" }, "tags": { + "title": "methodTags", "type": "array", "items": { "oneOf": [ @@ -341,6 +383,7 @@ } }, "paramStructure": { + "title": "methodParamStructure", "type": "string", "description": "Format the server expects the params. Defaults to 'by-positon'.", "enum": [ @@ -350,6 +393,7 @@ "default": "by-position" }, "params": { + "title": "methodParams", "type": "array", "items": { "oneOf": [ @@ -363,6 +407,7 @@ } }, "result": { + "title": "methodResult", "oneOf": [ { "$ref": "#/definitions/contentDescriptorObject" @@ -373,6 +418,7 @@ ] }, "errors": { + "title": "methodErrors", "description": "Defines an application level error.", "type": "array", "items": { @@ -387,6 +433,7 @@ } }, "links": { + "title": "methodLinks", "type": "array", "items": { "oneOf": [ @@ -400,6 +447,7 @@ } }, "examples": { + "title": "methodExamples", "type": "array", "items": { "oneOf": [ @@ -414,10 +462,11 @@ } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "tagObject": { + "title": "tagObject", "type": "object", "additionalProperties": false, "required": [ @@ -425,10 +474,12 @@ ], "properties": { "name": { + "title": "tagName", "type": "string", "minLength": 1 }, "description": { + "title": "tagDescription", "type": "string" }, "externalDocs": { @@ -436,10 +487,11 @@ } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "exampleObject": { + "title": "exampleObject", "type": "object", "required": [ "name", @@ -447,22 +499,28 @@ ], "properties": { "summary": { + "title": "exampleSummary", "type": "string" }, - "value": {}, + "value": { + "title": "exampleValue" + }, "description": { + "title": "exampleDescription", "type": "string" }, "name": { + "title": "exampleName", "type": "string", "minLength": 1 } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } }, "examplePairingObject": { + "title": "examplePairingObject", "type": "object", "required": [ "name", @@ -471,13 +529,16 @@ ], "properties": { "name": { + "title": "examplePairingType", "type": "string", "minLength": 1 }, "description": { + "title": "examplePairingDescription", "type": "string" }, "params": { + "title": "examplePairingParams", "type": "array", "items": { "oneOf": [ @@ -491,6 +552,7 @@ } }, "result": { + "title": "examplePairingResult", "oneOf": [ { "$ref": "#/definitions/exampleObject" @@ -503,6 +565,7 @@ } }, "contentDescriptorObject": { + "title": "contentDescriptorObject", "type": "object", "additionalProperties": false, "required": [ @@ -511,25 +574,32 @@ ], "properties": { "name": { + "title": "contentDescriptorName", "type": "string", "minLength": 1 }, "description": { + "title": "contentDescriptorDescription", "type": "string" }, "summary": { + "title": "contentDescriptorSummary", "type": "string" }, "schema": { "$ref": "#/definitions/schema" }, "required": { + "title": "contentDescriptorRequired", "type": "boolean" } }, "patternProperties": { - "^x-": {} + "^x-": { "$ref": "#/definitions/vendorExtensionObject" } } + }, + "vendorExtensionObject": { + "title": "vendorExtensionObject" } } } diff --git a/src/test.js b/src/test.js index e0139df..0f39669 100644 --- a/src/test.js +++ b/src/test.js @@ -1,8 +1,8 @@ -const metaSchema = require('../schema.json'); const fetch = require('node-fetch'); const Ajv = require('ajv'); const ajv = new Ajv(); const {cloneDeep} = require("lodash"); +const {setOpenRPCVersionEnum} = require("../bin/build"); const testOpenRPCDocument = { info: { @@ -39,8 +39,12 @@ const getJsonSchemaDraft7 = async () => ajv.addMetaSchema( "https://json-schema.org/draft-07/schema#" ); +let metaSchema; describe('validates all examples without error', () => { - beforeAll(async () => await getJsonSchemaDraft7()); + beforeAll(async () =>{ + metaSchema = await setOpenRPCVersionEnum(require('../schema.json')); + await getJsonSchemaDraft7(); + }); it("can validate a simple document", () => { const result = ajv.validate(metaSchema, testOpenRPCDocument);