|
|
|
import {primitive, PropSchema} from 'serializr';
|
|
|
|
|
|
|
|
function invariant(cond: boolean, message?: string) {
|
|
|
|
if (!cond) {
|
|
|
|
throw new Error('[serializr] ' + (message || 'Illegal ServerState'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function isPropSchema(thing: any) {
|
|
|
|
return thing && thing.serializer && thing.deserializer;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isAliasedPropSchema(propSchema: any) {
|
|
|
|
return typeof propSchema === 'object' && !!propSchema.jsonname;
|
|
|
|
}
|
|
|
|
|
|
|
|
function parallel(
|
|
|
|
ar: any[], processor: (item: any, done: any) => void, cb: any) {
|
|
|
|
if (ar.length === 0) {
|
|
|
|
return void cb(null, []);
|
|
|
|
}
|
|
|
|
let left = ar.length;
|
|
|
|
const resultArray: any[] = [];
|
|
|
|
let failed = false;
|
|
|
|
const processorCb = (idx: number, err: any, result: any) => {
|
|
|
|
if (err) {
|
|
|
|
if (!failed) {
|
|
|
|
failed = true;
|
|
|
|
cb(err);
|
|
|
|
}
|
|
|
|
} else if (!failed) {
|
|
|
|
resultArray[idx] = result;
|
|
|
|
if (--left === 0) {
|
|
|
|
cb(null, resultArray);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
ar.forEach((value, idx) => processor(value, processorCb.bind(null, idx)));
|
|
|
|
}
|
|
|
|
|
|
|
|
export default function list(propSchema: PropSchema): PropSchema {
|
|
|
|
propSchema = propSchema || primitive();
|
|
|
|
invariant(isPropSchema(propSchema), 'expected prop schema as first argument');
|
|
|
|
invariant(
|
|
|
|
!isAliasedPropSchema(propSchema),
|
|
|
|
'provided prop is aliased, please put aliases first');
|
|
|
|
return {
|
|
|
|
serializer(ar) {
|
|
|
|
invariant(
|
|
|
|
ar && typeof ar.length === 'number' && typeof ar.map === 'function',
|
|
|
|
'expected array (like) object');
|
|
|
|
return ar.map(propSchema.serializer);
|
|
|
|
},
|
|
|
|
deserializer(jsonArray, done, context) {
|
|
|
|
if (jsonArray === null) {
|
|
|
|
// sometimes go will return null in place of empty array
|
|
|
|
return void done(null, []);
|
|
|
|
}
|
|
|
|
if (!Array.isArray(jsonArray)) {
|
|
|
|
return void done('[serializr] expected JSON array', null);
|
|
|
|
}
|
|
|
|
parallel(
|
|
|
|
jsonArray,
|
|
|
|
(item: any, itemDone: (err: any, targetPropertyValue: any) => void) =>
|
|
|
|
propSchema.deserializer(item, itemDone, context, undefined),
|
|
|
|
done);
|
|
|
|
},
|
|
|
|
beforeDeserialize: () => {},
|
|
|
|
afterDeserialize: () => {},
|
|
|
|
};
|
|
|
|
}
|