Skip to content

Commit 5f65a5d

Browse files
committed
Adding entity metadata registry.
1 parent 4f4b996 commit 5f65a5d

2 files changed

Lines changed: 125 additions & 0 deletions

File tree

lib/datastore/entity.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
var entityMeta = {};
2+
3+
var namespaceRegex = kindRegex = fieldNameRegex = new RegExp(/^[A-Za-z]+$/);
4+
5+
/**
6+
* Registers a kind and its field meta globally. In order
7+
* to perform CRUD operations for a kind, you should register
8+
* it with its field metadata.
9+
*
10+
* registerKind('namespace', 'Author', {
11+
* name: { kind: STRING, indexed: false },
12+
* tags: { kind: STRING, multi: true }, // an array of string elements.
13+
* favArticles: { kind: KEY, multi: true }
14+
* contact: {
15+
* kind: {
16+
* telephone: { kind: String },
17+
* email: { kind: String }
18+
* }
19+
* }
20+
* });
21+
*
22+
* @param {string} namespace Namespace of the kind.
23+
* @param {string} kind Name of the kind.
24+
* @param {object} fieldMeta Object that contains metadata information
25+
* about the fields.
26+
*/
27+
function registerKind(namespace, kind, fieldMeta) {
28+
// validate the input and put it to the dictionary
29+
namespace = namespace || 'default';
30+
if (!namespaceRegex.test(namespace)) {
31+
throw new Error('Namespaces should match ' + namespaceRegex);
32+
}
33+
if (!kindRegex.test(kind)) {
34+
throw new Error('Kinds should match ' + kindRegex);
35+
}
36+
37+
// TODO(jbd): Validate namespace, kind and fieldMeta.
38+
Object.keys(fieldMeta).forEach(function (fieldName) {
39+
validateField(fieldName, fieldMeta[fieldName]);
40+
});
41+
42+
if (!entityMeta[namespace]) {
43+
entityMeta[namespace] = {};
44+
}
45+
entityMeta[namespace][kind] = fieldMeta;
46+
}
47+
48+
function getKind(namespace, kind) {
49+
return entityMeta[namespace] && entityMeta[namespace][kind];
50+
};
51+
52+
function validateField(name, field) {
53+
if (!fieldNameRegex.test(name)) {
54+
throw new Error('Field name should match ' + fieldNameRegex);
55+
}
56+
if (!field.kind) {
57+
throw new Error('Provide a kind for field ' + name);
58+
}
59+
if (typeof field.kind != 'object' && !primitiveKinds[field.kind]) {
60+
throw new Error('Unknown kind for field ' + name);
61+
}
62+
if (typeof field.kind == 'object') {
63+
Object.keys(field.key).forEach(function (key) {
64+
validateField(key, field.key[key]);
65+
});
66+
}
67+
}
68+
69+
var primitiveKinds = {
70+
BOOL: 'BOOL',
71+
NUMBER: 'NUMBER',
72+
STRING: 'STRING',
73+
BYTES: 'BYTES',
74+
DATETIME: 'DATETIME',
75+
KEY: 'KEY'
76+
}
77+
78+
/**
79+
* Export primitive kinds.
80+
*/
81+
module.exports.kinds = primitiveKinds;
82+
83+
/**
84+
* Export registerKind.
85+
* @type {function}
86+
*/
87+
module.exports.registerKind = registerKind;
88+
89+
/**
90+
* Exports getKind.
91+
* @type {function}
92+
*/
93+
module.exports.getKind = getKind;

test/datastore.entity.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var assert = require('assert'),
2+
entity = require('../lib/datastore/entity.js');
3+
4+
var blogPostMetadata = {
5+
title: { kind: entity.kinds.STRING, indexed: true },
6+
tags: { kind: entity.kinds.STRING, multi: true, indexed: true },
7+
publishedAt: { kind: entity.kinds.DATETIME },
8+
author: { kind: entity.kinds.KEY, indexed: true },
9+
isDraft: { kind: entity.kinds.BOOL, indexed: true }
10+
}
11+
12+
describe('registerKind', function() {
13+
14+
it('should be able to register valid field metadata', function(done) {
15+
entity.registerKind('namespace', 'kind', blogPostMetadata);
16+
done();
17+
});
18+
19+
it('should set the namespace to be "default" if zero value or null is provided', function(done) {
20+
entity.registerKind(null, 'kind', blogPostMetadata);
21+
var meta = entity.getKind('default', 'kind');
22+
assert.strictEqual(meta, blogPostMetadata);
23+
done();
24+
});
25+
26+
it('should throw an exception if an invalid kind is provided', function(done) {
27+
assert.throws(function() {
28+
entity.registerKind(null, '000', blogPostMetadata);
29+
}, /Kinds should match/);
30+
done();
31+
});
32+
});

0 commit comments

Comments
 (0)