Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@asyncapi/avro-schema-parser

Package Overview
Dependencies
Maintainers
3
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@asyncapi/avro-schema-parser - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

.github/workflows/automerge-for-humans-add-ready-to-merge-or-do-not-merge-label.yml

6

package.json
{
"name": "@asyncapi/avro-schema-parser",
"version": "1.0.0",
"version": "1.0.1",
"description": "An AsyncAPI schema parser for Avro 1.x schemas.",

@@ -9,3 +9,3 @@ "main": "index.js",

"release": "semantic-release",
"lint": "eslint --max-warnings 0 --config .eslintrc.yaml .",
"lint": "eslint --max-warnings 1 --config .eslintrc.yaml .",
"generate:assets": "echo 'No additional assets need to be generated at the moment'",

@@ -34,3 +34,3 @@ "bump:version": "npm --no-git-tag-version --allow-same-version version $VERSION"

"devDependencies": {
"@asyncapi/parser": "^1.11.1",
"@asyncapi/parser": "^1.13.0",
"@semantic-release/commit-analyzer": "^8.0.1",

@@ -37,0 +37,0 @@ "@semantic-release/github": "^7.0.4",

@@ -24,2 +24,8 @@ const fs = require('fs');

const inputWithSubAvro190 = fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-111-1.9.0.yaml'), 'utf8');
const outputWithSubAvro190 = '{"asyncapi":"2.0.0","info":{"title":"My API","version":"1.0.0"},"channels":{"mychannel":{"publish":{"message":{"payload":{"type":"object","required":["metadata","auth_code","triggered_by"],"properties":{"metadata":{"type":"object","required":["id","timestamp"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier for this specific event","x-parser-schema-id":"<anonymous-schema-2>"},"timestamp":{"type":"integer","minimum":-9223372036854776000,"maximum":9223372036854776000,"description":"Instant the event took place (not necessary when it was published)","x-parser-schema-id":"<anonymous-schema-3>"},"correlation_id":{"oneOf":[{"type":"string","format":"uuid","x-parser-schema-id":"<anonymous-schema-5>"},{"type":"null","x-parser-schema-id":"<anonymous-schema-6>"}],"description":"id of the event that resulted in this\\nevent being published (optional)","default":null,"x-parser-schema-id":"<anonymous-schema-4>"},"publisher_context":{"oneOf":[{"type":"object","additionalProperties":{"type":"string","x-parser-schema-id":"<anonymous-schema-9>"},"x-parser-schema-id":"<anonymous-schema-8>"},{"type":"null","x-parser-schema-id":"<anonymous-schema-10>"}],"description":"optional set of key-value pairs of context to be echoed back\\nin any resulting message (like a richer\\ncorrelationId.\\n\\nThese values are likely only meaningful to the publisher\\nof the correlated event","default":null,"x-parser-schema-id":"<anonymous-schema-7>"}},"description":"Metadata to be associated with every published event","x-parser-schema-id":"<anonymous-schema-1>"},"auth_code":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode.","x-parser-schema-id":"<anonymous-schema-12>"},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret.","x-parser-schema-id":"<anonymous-schema-13>"},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA.","x-parser-schema-id":"<anonymous-schema-14>"}},"description":"Encrypted auth_code received when user authorizes the app.","x-parser-schema-id":"<anonymous-schema-11>"},"refresh_token":{"type":"object","required":["value","nonce","key"],"properties":{"value":{"type":"string","description":"A sequence of bytes that has been AES encrypted in CTR mode.","x-parser-schema-id":"<anonymous-schema-12>"},"nonce":{"type":"string","description":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret.","x-parser-schema-id":"<anonymous-schema-13>"},"key":{"type":"string","description":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA.","x-parser-schema-id":"<anonymous-schema-14>"}},"description":"Encrypted auth_code received when user authorizes the app.","x-parser-schema-id":"<anonymous-schema-11>"},"triggered_by":{"type":"string","format":"uuid","description":"ID of the user who triggered this event.","x-parser-schema-id":"<anonymous-schema-15>"}},"description":"An example schema to illustrate the issue","x-parser-schema-id":"com.foo.connections.ConnectionRequested"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":{"type":"record","name":"ConnectionRequested","namespace":"com.foo.connections","doc":"An example schema to illustrate the issue","fields":[{"name":"metadata","type":{"type":"record","name":"EventMetadata","namespace":"com.foo","doc":"Metadata to be associated with every published event","fields":[{"name":"id","type":{"type":"string","logicalType":"uuid"},"doc":"Unique identifier for this specific event"},{"name":"timestamp","type":{"type":"long","logicalType":"timestamp-millis"},"doc":"Instant the event took place (not necessary when it was published)"},{"name":"correlation_id","type":["null",{"type":"string","logicalType":"uuid"}],"doc":"id of the event that resulted in this\\nevent being published (optional)","default":null},{"name":"publisher_context","type":["null",{"type":"map","values":{"type":"string","avro.java.string":"String"},"avro.java.string":"String"}],"doc":"optional set of key-value pairs of context to be echoed back\\nin any resulting message (like a richer\\ncorrelationId.\\n\\nThese values are likely only meaningful to the publisher\\nof the correlated event","default":null}]}},{"name":"auth_code","type":{"type":"record","name":"EncryptedString","namespace":"com.foo","doc":"A string that was encrypted with AES (using CTR mode), its key encrypted with RSA, and the nonce used for the encryption.","fields":[{"name":"value","type":"string","doc":"A sequence of bytes that has been AES encrypted in CTR mode."},{"name":"nonce","type":"string","doc":"A nonce, used by the CTR encryption mode for our encrypted value. Not encrypted, not a secret."},{"name":"key","type":"string","doc":"An AES key, used to encrypt the value field, that has itself been encrypted using RSA."}]},"doc":"Encrypted auth_code received when user authorizes the app."},{"name":"refresh_token","type":"com.foo.EncryptedString","doc":"Encrypted refresh_token generated by using clientId and clientSecret."},{"name":"triggered_by","type":{"type":"string","logicalType":"uuid"},"doc":"ID of the user who triggered this event."}]},"schemaFormat":"application/vnd.aai.asyncapi;version=2.0.0","x-parser-message-parsed":true,"x-parser-message-name":"<anonymous-message-1>"}}}},"x-parser-spec-parsed":true}';
const inputWithOneOfReferenceAvro190 = fs.readFileSync(path.resolve(__dirname, './asyncapi-avro-113-1.9.0.yaml'), 'utf8');
const outputWithOneOfReferenceAvro190 = '{"asyncapi":"2.0.0","info":{"title":"My API","version":"1.0.0"},"channels":{"mychannel":{"publish":{"message":{"payload":{"oneOf":[{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string","x-parser-schema-id":"<anonymous-schema-2>"},"city":{"type":"string","x-parser-schema-id":"<anonymous-schema-3>"}},"x-parser-schema-id":"com.example.Address"},{"type":"object","required":["firstname","lastname"],"properties":{"firstname":{"type":"string","x-parser-schema-id":"<anonymous-schema-4>"},"lastname":{"type":"string","x-parser-schema-id":"<anonymous-schema-5>"},"address":{"type":"object","required":["streetaddress","city"],"properties":{"streetaddress":{"type":"string","x-parser-schema-id":"<anonymous-schema-2>"},"city":{"type":"string","x-parser-schema-id":"<anonymous-schema-3>"}},"x-parser-schema-id":"com.example.Address"}},"x-parser-schema-id":"com.example.Person"}],"x-parser-schema-id":"<anonymous-schema-1>"},"x-parser-original-schema-format":"application/vnd.apache.avro;version=1.9.0","x-parser-original-payload":[{"type":"record","name":"Address","namespace":"com.example","fields":[{"name":"streetaddress","type":"string"},{"name":"city","type":"string"}]},{"type":"record","name":"Person","namespace":"com.example","fields":[{"name":"firstname","type":"string"},{"name":"lastname","type":"string"},{"name":"address","type":"com.example.Address"}]}],"schemaFormat":"application/vnd.aai.asyncapi;version=2.0.0","x-parser-message-parsed":true,"x-parser-message-name":"<anonymous-message-1>"}}}},"x-parser-spec-parsed":true}';
parser.registerSchemaParser(avroSchemaParser);

@@ -36,2 +42,3 @@

});
it('should parse Avro schema 1.9.0 with a namespace', async function() {

@@ -57,2 +64,11 @@ const result = await parser.parse(inputWithAvro190WithNamespace, { path: __filename });

});
it('Issue #111 should handle pre defined records in schemas', async function() {
const result = await parser.parse(inputWithSubAvro190, { path: __filename });
expect(JSON.stringify(result.json())).toEqual(outputWithSubAvro190);
});
it('Issue #113 should handle pre defined records in top level oneOf schema', async function() {
const result = await parser.parse(inputWithOneOfReferenceAvro190, { path: __filename });
console.log(JSON.stringify(result.json()));
expect(JSON.stringify(result.json())).toEqual(outputWithOneOfReferenceAvro190);
});
});

@@ -139,8 +139,20 @@ const avsc = require('avsc');

async function convertAvroToJsonSchema(avroDefinition, isTopLevel) {
/**
* Cache the passed value under the given key. If the key is undefined the value will not be cached. This function
* uses mutation of the passed cache object rather than a copy on write cache strategy.
*
* @param cache Map<String, JsonSchema> the cache to store the JsonSchema
* @param key String | Undefined - the fully qualified name of an avro record
* @param value JsonSchema - The json schema from the avro record
*/
function cacheAvroRecordDef(cache, key, value) {
if (key) {
cache[key] = value;
}
}
async function convertAvroToJsonSchema(avroDefinition, isTopLevel, recordCache = {}) {
const jsonSchema = {};
const isUnion = Array.isArray(avroDefinition);
validateAvroSchema(avroDefinition);
if (isUnion) {

@@ -150,7 +162,13 @@ jsonSchema.oneOf = [];

for (const avroDef of avroDefinition) {
const def = await convertAvroToJsonSchema(avroDef, isTopLevel);
const def = await convertAvroToJsonSchema(avroDef, isTopLevel, recordCache);
// avroDef can be { type: 'int', default: 1 } and this is why avroDef.type has priority here
const defType = avroDef.type || avroDef;
// To prefer non-null values in the examples skip null definition here and push it as the last element after loop
if (defType === 'null') nullDef = def; else jsonSchema.oneOf.push(def);
if (defType === 'null') {
nullDef = def;
} else {
jsonSchema.oneOf.push(def);
const qualifiedName = getFullyQualifiedName(avroDef);
cacheAvroRecordDef(recordCache, qualifiedName, def);
}
}

@@ -200,9 +218,17 @@ if (nullDef) jsonSchema.oneOf.push(nullDef);

for (const field of avroDefinition.fields) {
const def = await convertAvroToJsonSchema(field.type, false);
// If the type is a sub schema it will have been stored in the cache.
if (recordCache[field.type]) {
propsMap.set(field.name, recordCache[field.type]);
} else {
const def = await convertAvroToJsonSchema(field.type, false, recordCache);
requiredAttributesMapping(field, jsonSchema, field.default !== undefined);
commonAttributesMapping(field, def, false);
additionalAttributesMapping(field.type, field, def);
requiredAttributesMapping(field, jsonSchema, field.default !== undefined);
commonAttributesMapping(field, def, false);
additionalAttributesMapping(field.type, field, def);
propsMap.set(field.name, def);
propsMap.set(field.name, def);
// If there is a name for the sub record cache it under the name.
const qualifiedFieldName = getFullyQualifiedName(field.type);
cacheAvroRecordDef(recordCache, qualifiedFieldName, def);
}
}

@@ -220,3 +246,4 @@ jsonSchema.properties = Object.fromEntries(propsMap.entries());

module.exports.avroToJsonSchema = async function avroToJsonSchema(avroDefinition) {
validateAvroSchema(avroDefinition);
return convertAvroToJsonSchema(avroDefinition, true);
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc