Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

better exporting of types #43

Merged
merged 5 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
* @module mapeo-schema
*/
import * as cenc from 'compact-encoding'
import * as JSONSchemas from './dist/schemas.js'
import * as Schemas from './dist/schemas.js'
import * as ProtobufSchemas from './types/proto/index.js'
import schemasPrefix from './schemasPrefix.js'
import { inheritsFromCommon, formatSchemaKey } from './utils.js'

const dataTypeIdSize = 6
const schemaVersionSize = 2

/**
* @param {import('./types/schema/index').MapeoRecord} obj - Object to be encoded
* @returns {import('./types/proto/index').ProtobufSchemas}
* @param {import('./types').JSONSchema} obj - Object to be encoded
* @returns {import('./types').ProtobufSchema}
*/
const jsonSchemaToProto = (obj) => {
const commonKeys = [
Expand Down Expand Up @@ -49,12 +48,12 @@ const jsonSchemaToProto = (obj) => {
}

/**
* @param {import('./types/proto/index').ProtobufSchemas} protobufObj
* @param {import('./types').ProtobufSchema} protobufObj
* @param {Object} obj
* @param {Number} obj.schemaVersion
* @param {String} obj.schemaType
* @param {String} obj.version
* @returns {import('./types/schema/index').MapeoRecord}
* @returns {import('./types').JSONSchema}
*/
const protoToJsonSchema = (
protobufObj,
Expand Down Expand Up @@ -117,7 +116,7 @@ export const decodeBlockPrefix = (buf) => {

/**
* Validate an object against the schema type
* @param {import('./types/schema/index').MapeoRecord} obj - Object to be encoded
* @param {import('./types').JSONSchema} obj - Object to be encoded
* @returns {Boolean} indicating if the object is valid
*/
export const validate = (obj) => {
Expand All @@ -138,15 +137,15 @@ export const validate = (obj) => {
delete obj.schemaType
}

const validatefn = JSONSchemas[key]
const validatefn = Schemas[key]
const isValid = validatefn(obj)
if (!isValid) throw new Error(JSON.stringify(validatefn.errors, null, 4))
return isValid
}

/**
* Encode a an object validated against a schema as a binary protobuf to send to an hypercore.
* @param {import('./types/schema/index').MapeoRecord} obj - Object to be encoded
* @param {import('./types').JSONSchema} obj - Object to be encoded
* @returns {Buffer} protobuf encoded buffer with dataTypeIdSize + schemaVersionSize bytes prepended, one for the type of record and the other for the version of the schema */
export const encode = (obj) => {
const key = formatSchemaKey(obj.schemaType, obj.schemaVersion)
Expand All @@ -171,7 +170,7 @@ export const encode = (obj) => {
/**
* Decode a Buffer as an object validated against the corresponding schema
* @param {Buffer} buf - Buffer to be decoded
* @returns {import('./types/schema/index').MapeoRecord}
* @returns {import('./types').JSONSchema}
* */
export const decode = (buf, { coreId, seq }) => {
const { dataTypeId, schemaVersion } = decodeBlockPrefix(buf)
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"description": "JSON schema and flow types for Mapeo",
"main": "src/index.js",
"type": "module",
"exports": {
"types/": "./types/index.d.ts",
"types/schema": "./types/schema/index.d.ts",
"types/proto": "./types/proto/index.d.ts"
},
"scripts": {
"example": "node examples/schema_test.js",
"protobuf": "buf generate ./proto",
Expand Down
68 changes: 56 additions & 12 deletions scripts/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
// This script is use to generate various files to be used at runtime:
// * dist/schemas.js - all the validating functions for jsonSchema
// * types/schema/index.d.ts - Union type for all the JsonSchemas
// * types/schema/index.d.ts - Union type for all the ProtobufSchemas
// * types/proto/index.d.ts - Union type for all the ProtobufSchemas
// * types/proto/index.js - Exports all protobufs from one file
// * types/index.d.ts - re-exports JSONSchema and ProtobufSchema types for better importing

import fs from 'node:fs'
import path from 'path'
Expand Down Expand Up @@ -51,20 +52,35 @@ const ajv = new Ajv({
})
ajv.addKeyword('meta:enum')

// generate code
// generate validation code
let schemaValidations = standaloneCode(ajv, schemaExports)

const dist = path.join(__dirname, '../dist')
if (!fs.existsSync(dist)) {
fs.mkdirSync(dist)
}
// dump all to file

// dist/schemas.js
fs.writeFileSync(
path.join(__dirname, '../dist', 'schemas.js'),
schemaValidations
)

// generate types/schema/index.d.ts
const latestSchemaVersions = schemas.reduce(
(acc, { schemaVersion, schemaType }) => {
if (!acc[schemaType]) {
acc[schemaType] = schemaVersion
} else {
if (acc[schemaType] < schemaVersion) {
acc[schemaType] = schemaVersion
}
}
return acc
},
{}
)

// types/schema/index.d.ts
const jsonSchemaType = `
${schemas
.map(
Expand All @@ -83,21 +99,30 @@ schemaType?: string;
type?: string;
schemaVersion?: number;
}
export type MapeoRecord = (${schemas
export type JSONSchema = (${schemas
.map(
/** @param {Object} schema */
({ schemaVersion, schemaType }) => {
return `${formatSchemaType(schemaType)}_${schemaVersion}`
}
({ schemaVersion, schemaType }) =>
`${formatSchemaType(schemaType)}_${schemaVersion}`
)
.join(' | ')}) & base
`
${schemas
.map(({ schemaType, schemaVersion }) => {
const as =
latestSchemaVersions[schemaType] !== schemaVersion
? `as ${formatSchemaType(schemaType)}_${schemaVersion}`
: ''
return `export { ${formatSchemaType(
schemaType
)} ${as} } from './${schemaType}/v${latestSchemaVersions[schemaType]}'`
})
.join('\n')}`
fs.writeFileSync(
path.join(__dirname, '../types/schema/index.d.ts'),
jsonSchemaType
)

// generate index.js for protobuf schemas and index.d.ts
// types/proto/index.d.ts and types/proto/index.js
const protobufFiles = glob.sync('../types/proto/*/*.ts', { cwd: 'scripts' })
const obj = protobufFiles
.filter((f) => !f.match(/.d.ts/))
Expand All @@ -116,7 +141,18 @@ const union = obj
({ schemaType, schemaVersion }) =>
`${formatSchemaType(schemaType)}_${schemaVersion.replace('v', '')}`
)
.join(' & ')
.join(' | ')

const individualExports = schemas
.map(
({ schemaType, schemaVersion }) =>
`export { ${formatSchemaType(schemaType)}_${schemaVersion} ${
latestSchemaVersions[schemaType] === schemaVersion
? `as ${formatSchemaType(schemaType)}`
: ''
}} from './${schemaType}/v${schemaVersion}'`
)
.join('\n')

obj.forEach(({ schemaType, schemaVersion }) => {
const linejs = `export { ${formatSchemaType(
Expand All @@ -143,5 +179,13 @@ fs.writeFileSync(
fs.writeFileSync(
path.join(__dirname, '../types/proto/index.d.ts'),
`${linesdts.join('\n')}
export type ProtobufSchemas = ${union}`
export type ProtobufSchema = ${union}
${individualExports}`
)

// types/index.d.ts
fs.writeFileSync(
path.join(__dirname, '../types/index.d.ts'),
`export { ProtobufSchema } from './proto'
export { JSONSchema } from './schema'`
)