Last active
July 12, 2018 11:16
-
-
Save kevinswiber/8cb485290a3b8f2f7efd to your computer and use it in GitHub Desktop.
Siren in Protobuffers v3.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"class": [ "order" ], | |
"properties": { | |
"orderNumber": 42, | |
"itemCount": 3, | |
"status": "pending" | |
}, | |
"entities": [ | |
{ | |
"class": [ "items", "collection" ], | |
"rel": [ "http://x.io/rels/order-items" ], | |
"href": "http://api.x.io/orders/42/items" | |
}, | |
{ | |
"class": [ "info", "customer" ], | |
"rel": [ "http://x.io/rels/customer" ], | |
"properties": { | |
"customerId": "pj123", | |
"name": "Peter Joseph" | |
}, | |
"links": [ | |
{ "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" } | |
] | |
} | |
], | |
"actions": [ | |
{ | |
"name": "add-item", | |
"title": "Add Item", | |
"method": "POST", | |
"href": "http://api.x.io/orders/42/items", | |
"type": "application/x-www-form-urlencoded", | |
"fields": [ | |
{ "name": "orderNumber", "type": "hidden", "value": "42" }, | |
{ "name": "productCode", "type": "text" }, | |
{ "name": "quantity", "type": "number" } | |
] | |
} | |
], | |
"links": [ | |
{ "rel": [ "self" ], "href": "http://api.x.io/orders/42" }, | |
{ "rel": [ "previous" ], "href": "http://api.x.io/orders/41" }, | |
{ "rel": [ "next" ], "href": "http://api.x.io/orders/43" } | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
syntax = "proto3"; | |
package siren.example; | |
message Order { | |
message Properties { | |
int32 order_number = 1; | |
int32 order_count = 2; | |
string status = 3; | |
} | |
message CustomerSubEntity { | |
message Properties { | |
string customer_id = 1; | |
string name = 2; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
syntax = "proto3"; | |
package siren; | |
// http://schema.sirenspec.org/protobuf/siren.Entity | |
message Entity { | |
repeated string class = 1; | |
bytes properties = 2; | |
repeated AnySubEntity entities = 3; | |
repeated Action actions = 4; | |
repeated Link links = 5; | |
} | |
// http://schema.sirenspec.org/protobuf/siren.AnySubEntity | |
message AnySubEntity { | |
Type type = 1; | |
bytes value = 2; | |
// http://schema.sirenspec.org/protobuf/siren.AnySubEntity.Type | |
enum Type { | |
EMBEDDED = 0; | |
LINKED = 1; | |
} | |
} | |
// http://schema.sirenspec.org/protobuf/siren.Link | |
message Link { | |
repeated string class = 1; | |
repeated string rel = 2; | |
string href = 3; | |
string title = 4; | |
string type = 5; | |
} | |
// http://schema.sirenspec.org/protobuf/siren.LinkedEntity | |
message LinkedEntity { | |
repeated string class = 1; | |
repeated string rel = 2; | |
string href = 3; | |
string title = 4; | |
} | |
// http://schema.sirenspec.org/protobuf/siren.Action | |
message Action { | |
repeated string class = 1; | |
string name = 2; | |
string title = 3; | |
string method = 4; | |
string href = 5; | |
string type = 6; | |
repeated Field fields = 7; | |
} | |
// http://schema.sirenspec.org/protobuf/siren.Field | |
message Field { | |
string name = 1; | |
Type type = 2; | |
bytes value = 3; | |
// http://schema.sirenspec.org/protobuf/siren.Field.Type | |
enum Type { | |
TEXT = 0; | |
HIDDEN = 1; | |
SEARCH = 2; | |
TEL = 3; | |
URL = 4; | |
EMAIL = 5; | |
PASSWORD = 6; | |
DATETIME = 7; | |
DATE = 8; | |
MONTH = 9; | |
WEEK = 10; | |
TIME = 11; | |
DATETIME_LOCAL = 12; | |
NUMBER = 13; | |
RANGE = 14; | |
COLOR = 15; | |
CHECKBOX = 16; | |
RADIO = 17; | |
FILE = 18; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var zlib = require('zlib'); | |
var ProtoBuf = require('protobufjs'); | |
var Enum = ProtoBuf.Reflect.Enum; | |
var builder = ProtoBuf.newBuilder({ convertFieldsToCamelCase: true }); | |
ProtoBuf.loadProtoFile('./order.proto', builder); | |
ProtoBuf.loadProtoFile('./siren.proto', builder); | |
var Siren = builder.build('siren'); | |
var SirenExample = builder.build('siren.example'); | |
var json = require('./order.json'); | |
var Order = SirenExample.Order; | |
var order = new Siren.Entity({ | |
class: ['order'], | |
properties: new Order.Properties({ | |
orderNumber: 42, | |
orderCount: 3, | |
status: 'pending' | |
}).toBuffer(), | |
entities: [ | |
new Siren.AnySubEntity({ | |
type: 'EMBEDDED', | |
value: new Siren.Entity({ | |
class: ['customer', 'info'], | |
properties: new Order.CustomerSubEntity.Properties({ | |
customerId: 'pj123', | |
name: 'Peter Joseph' | |
}).toBuffer(), | |
links: [ | |
new Siren.Link({ | |
rel: ['self'], | |
href: 'http://api.x.io/customers/pj123' | |
}) | |
] | |
}).toBuffer() | |
}), | |
new Siren.AnySubEntity({ | |
type: 'LINKED', | |
value: new Siren.LinkedEntity({ | |
class: ['items', 'collection'], | |
rel: ['http://x.io/rels/order-items'], | |
href: 'http://api.x.io/orders/42/items' | |
}).toBuffer() | |
}) | |
], | |
actions: [ | |
new Siren.Action({ | |
name: 'add-item', | |
method: 'POST', | |
href: 'http://api.x.io/orders/42/items', | |
type: 'application/x-www-form-urlencoded', | |
title: 'Add Item', | |
fields: [ | |
new Siren.Field({ | |
name: 'orderNumber', | |
type: 'HIDDEN', | |
value: new Buffer('42') | |
}), | |
new Siren.Field({ | |
name: 'productCode', | |
type: 'TEXT' | |
}), | |
new Siren.Field({ | |
name: 'quantity', | |
type: 'NUMBER' | |
}) | |
] | |
}) | |
], | |
links: [ | |
new Siren.Link({ | |
rel: ['self'], | |
href: 'http://api.x.io/orders/42' | |
}), | |
new Siren.Link({ | |
rel: ['previous'], | |
href: 'http://api.x.io/orders/41' | |
}), | |
new Siren.Link({ | |
rel: ['next'], | |
href: 'http://api.x.io/orders/43' | |
}) | |
] | |
}); | |
var jsonBuffer = new Buffer(JSON.stringify(json)); | |
var protoBuffer = order.toBuffer(); | |
var stringified = JSON.stringify(json); | |
console.log('json:', jsonBuffer.length); | |
console.log('proto:', protoBuffer.length); | |
console.log('json-gzip:', zlib.gzipSync(jsonBuffer).length); | |
console.log('proto-gzip:', zlib.gzipSync(protoBuffer).length); | |
var decoded = Siren.Entity.decode(protoBuffer); | |
if (decoded.class.indexOf('order') > -1) { | |
var fieldValue = decoded.actions[0].fields[0].value; | |
console.log(fieldValue.toString('utf8')); | |
decoded.entities.forEach(function(subEntity) { | |
if (subEntity.type === Siren.AnySubEntity.Type.EMBEDDED) { | |
var e = Siren.Entity.decode(subEntity.value); | |
if (e.class.indexOf('customer') > -1 && e.class.indexOf('info') > -1) { | |
var props = SirenExample.Order.CustomerSubEntity.Properties.decode(e.properties); | |
console.log(props.name); | |
} | |
} | |
}); | |
} | |
var fs = require('fs'); | |
var writeStream = fs.createWriteStream('./Protobuffun/Protobuffun/bin/Debug/protobuf.dat'); | |
writeStream.end(protoBuffer); | |
writeStream.on('finish', function() { | |
var file = fs.readFileSync('./Protobuffun/Protobuffun/bin/Debug/protobuf.dat'); | |
var root = Siren.Entity.decode(file); | |
if (root.class.indexOf('order') > -1) { | |
var props = SirenExample.Order.Properties.decode(root.properties); | |
console.log(props); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment