You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.5 KiB
JavaScript
74 lines
2.5 KiB
JavaScript
"use strict";
|
|
|
|
const Promise = require("bluebird");
|
|
const syncpipe = require("syncpipe");
|
|
const util = require("util");
|
|
|
|
const ID = Symbol("dlayer-source object ID");
|
|
|
|
// TODO: Make more readable
|
|
|
|
module.exports = {
|
|
withSources: function withSources(schemaObject) {
|
|
let { $sources, ... rest } = schemaObject;
|
|
|
|
let generatedProperties = syncpipe($sources ?? {}, [
|
|
(_) => Object.entries(_),
|
|
(_) => _.flatMap(([ source, properties ]) => {
|
|
return Object.entries(properties).map(([ property, selector ]) => {
|
|
// This is to support property name shorthand used in place of a selector function
|
|
let effectiveSelector = (typeof selector === "string")
|
|
? (result) => {
|
|
// FIXME: Consider whether to add this check or not; currently, it would break stuff in CVM
|
|
// if (selector in result) {
|
|
return result[selector];
|
|
// } else {
|
|
// throw new Error(`Result object does not have a '${selector}' property`);
|
|
// }
|
|
}
|
|
: selector;
|
|
|
|
let getter = function (_args, context) {
|
|
return Promise.try(() => {
|
|
if (properties[ID] != null) {
|
|
let dataSource = context.sources[source];
|
|
|
|
if (dataSource != null) {
|
|
// console.log(`Calling source '${source}' with ID ${util.inspect(properties[ID])}`);
|
|
return dataSource.load(properties[ID]);
|
|
} else {
|
|
throw new Error(`Attempted to read from source '${source}', but no such source is registered`);
|
|
}
|
|
} else {
|
|
// FIXME: Better error message
|
|
throw new Error(`Must specify a dlayer-source ID`);
|
|
}
|
|
}).then((result) => {
|
|
// console.log(`Result [${source}|${util.inspect(properties[ID])}] ${util.inspect(result)}`);
|
|
// TODO: How to deal with null results? Allow them or not? Make it an option?
|
|
if (result != null) {
|
|
return effectiveSelector(result);
|
|
} else {
|
|
throw new Error(`Null-ish result returned for ID '${properties[ID]}' from source '${source}'; this is not allowed, and there is probably a bug in your code. Please file a ticket if you have a good usecase for null-ish results!`);
|
|
}
|
|
});
|
|
};
|
|
|
|
return [ property, getter ];
|
|
});
|
|
}),
|
|
(_) => Object.fromEntries(_)
|
|
]);
|
|
|
|
// NOTE: We always specify the generated properties first, so that properties can be overridden by explicit known values to bypass the source lookup, if needed by the implementation
|
|
return {
|
|
... generatedProperties,
|
|
... rest
|
|
};
|
|
},
|
|
ID: ID
|
|
};
|
|
|
|
|
|
|