contract schema

This commit is contained in:
Florian Dold 2016-02-17 17:51:25 +01:00
parent 874d083ec3
commit 059de061ab
5 changed files with 48 additions and 11 deletions

View File

@ -77,6 +77,15 @@ export namespace Checkable {
} }
function checkOptional(target, prop, path): any {
console.assert(prop.propertyKey);
prop.elementChecker(target,
prop.elementProp,
path.concat([prop.propertyKey]));
return target;
}
function checkValue(target, prop, path): any { function checkValue(target, prop, path): any {
let type = prop.type; let type = prop.type;
if (!type) { if (!type) {
@ -84,7 +93,8 @@ export namespace Checkable {
} }
let v = target; let v = target;
if (!v || typeof v !== "object") { if (!v || typeof v !== "object") {
throw new SchemaError(`expected object for ${path}, got ${typeof v} instead`); throw new SchemaError(
`expected object for ${path.join(".")}, got ${typeof v} instead`);
} }
let props = type.prototype[chkSym].props; let props = type.prototype[chkSym].props;
let remainingPropNames = new Set(Object.getOwnPropertyNames(v)); let remainingPropNames = new Set(Object.getOwnPropertyNames(v));
@ -119,7 +129,7 @@ export namespace Checkable {
propertyKey: "(root)", propertyKey: "(root)",
type: target, type: target,
checker: checkValue checker: checkValue
}, []); }, ["(root)"]);
}; };
return target; return target;
} }
@ -164,6 +174,29 @@ export namespace Checkable {
} }
export function Optional(type) {
let stub = {};
type(stub, "(optional-element)");
let elementProp = mkChk(stub).props[0];
let elementChecker = elementProp.checker;
if (!elementChecker) {
throw Error("assertion failed");
}
function deco(target: Object, propertyKey: string | symbol): void {
let chk = mkChk(target);
chk.props.push({
elementChecker,
elementProp,
propertyKey: propertyKey,
checker: checkOptional,
optional: true,
});
}
return deco;
}
export function Number(target: Object, propertyKey: string | symbol): void { export function Number(target: Object, propertyKey: string | symbol): void {
let chk = mkChk(target); let chk = mkChk(target);
chk.props.push({propertyKey: propertyKey, checker: checkNumber}); chk.props.push({propertyKey: propertyKey, checker: checkNumber});

View File

@ -162,6 +162,9 @@ export class Contract {
@Checkable.String @Checkable.String
fulfillment_url: string; fulfillment_url: string;
@Checkable.Optional(Checkable.String)
repurchase_correlation_id: string;
static checked: (obj: any) => Contract; static checked: (obj: any) => Contract;
} }
@ -761,6 +764,7 @@ export class Wallet {
* Withdraw one coins of the given denomination from the given reserve. * Withdraw one coins of the given denomination from the given reserve.
*/ */
private withdraw(denom: Denomination, reserve: Reserve): Promise<void> { private withdraw(denom: Denomination, reserve: Reserve): Promise<void> {
console.log("creating pre coin at", new Date());
let preCoin = createPreCoin(denom, reserve); let preCoin = createPreCoin(denom, reserve);
return Query(this.db) return Query(this.db)
.put("precoins", preCoin) .put("precoins", preCoin)

View File

@ -61,7 +61,7 @@ System.register(["./wallet", "./db", "./http", "./checkable"], function(exports_
catch (e) { catch (e) {
if (e instanceof checkable_1.Checkable.SchemaError) { if (e instanceof checkable_1.Checkable.SchemaError) {
console.error("schema error:", e.message); console.error("schema error:", e.message);
return Promise.resolve({ error: "invalid contract", hint: e.message }); return Promise.resolve({ error: "invalid contract", hint: e.message, detail: detail });
} }
else { else {
throw e; throw e;
@ -80,12 +80,12 @@ System.register(["./wallet", "./db", "./http", "./checkable"], function(exports_
); );
var _a; var _a;
} }
function dispatch(handlers, db, req, sendResponse) { function dispatch(handlers, req, sendResponse) {
if (req.type in handlers) { if (req.type in handlers) {
Promise Promise
.resolve() .resolve()
.then(function () { .then(function () {
var p = handlers[req.type](db, req.detail); var p = handlers[req.type](req.detail);
return p.then(function (r) { return p.then(function (r) {
sendResponse(r); sendResponse(r);
}); });
@ -125,7 +125,7 @@ System.register(["./wallet", "./db", "./http", "./checkable"], function(exports_
var wallet = new wallet_1.Wallet(db, http, badge); var wallet = new wallet_1.Wallet(db, http, badge);
var handlers = makeHandlers(db, wallet); var handlers = makeHandlers(db, wallet);
chrome.runtime.onMessage.addListener(function (req, sender, sendResponse) { chrome.runtime.onMessage.addListener(function (req, sender, sendResponse) {
return dispatch(handlers, db, req, sendResponse); return dispatch(handlers, req, sendResponse);
}); });
}) })
.catch(function (e) { .catch(function (e) {

View File

@ -77,7 +77,7 @@ function makeHandlers(db: IDBDatabase,
} catch (e) { } catch (e) {
if (e instanceof Checkable.SchemaError) { if (e instanceof Checkable.SchemaError) {
console.error("schema error:", e.message); console.error("schema error:", e.message);
return Promise.resolve({error: "invalid contract", hint: e.message}); return Promise.resolve({error: "invalid contract", hint: e.message, detail: detail});
} else { } else {
throw e; throw e;
} }
@ -107,12 +107,12 @@ class ChromeBadge implements Badge {
} }
function dispatch(handlers, db, req, sendResponse) { function dispatch(handlers, req, sendResponse) {
if (req.type in handlers) { if (req.type in handlers) {
Promise Promise
.resolve() .resolve()
.then(() => { .then(() => {
const p = handlers[req.type](db, req.detail); const p = handlers[req.type](req.detail);
return p.then((r) => { return p.then((r) => {
sendResponse(r); sendResponse(r);
@ -155,7 +155,7 @@ export function wxMain() {
let wallet = new Wallet(db, http, badge); let wallet = new Wallet(db, http, badge);
let handlers = makeHandlers(db, wallet); let handlers = makeHandlers(db, wallet);
chrome.runtime.onMessage.addListener((req, sender, sendResponse) => { chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
return dispatch(handlers, db, req, sendResponse) return dispatch(handlers, req, sendResponse)
}); });
}) })
.catch((e) => { .catch((e) => {

View File

@ -21,7 +21,7 @@
</aside> </aside>
<section id="main"> <section id="main">
<article id="contract"></article> <article id="contract" class="fade"></article>
</section> </section>
</body> </body>