textiot
Version:
A framework for building web and native (IoT) Dapps on the IPFS network
103 lines (102 loc) • 4.56 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const toposort_1 = __importDefault(require("toposort"));
class SchemaMiller {
static sortLinksByDependency(links) {
// Create an array of [ name, dependency ] for sorting
const linkAndDepends = Object.entries(links).map(([name, link]) => {
const pair = [name, link.use];
return pair;
});
// Sort the array into an execution order
const sorted = [...toposort_1.default(linkAndDepends)].reverse();
// Refill the items in the sorted array
return (sorted
// File is the original form so we don't need a method
.filter((name) => {
return name !== ':file';
})
// TODO: `Name` should eventually be converted to lowercase
.map((name) => ({ name, link: links[name] })));
}
static normalizeOptions(info) {
const opts = info.opts || {};
// Check for top level opts
opts.plaintext = (info.plaintext || false).toString();
opts.pin = (info.pin || false).toString();
return opts;
}
static resolveDependency(method, payloadsByName) {
let use;
// Convert 'use' to hash of payload
if (method.use && method.use !== ':file') {
// TODO: This is a hack, should use multihash JS lib in future
use = (method.use.length === 46 && method.use.startsWith('Qm')) ?
method.use :
payloadsByName.files[method.use].hash;
}
const resolvedMethod = Object.assign({}, method);
resolvedMethod.use = use || '';
return resolvedMethod;
}
static mill(payload, node, remoteMill) {
return __awaiter(this, void 0, void 0, function* () {
const dir = { files: {} };
// Traverse the schema and collect generated files
if (node.mill) {
const normal = SchemaMiller.normalizeOptions(node);
const resolved = SchemaMiller.resolveDependency(normal, dir);
let form;
if (resolved.use) {
form = undefined;
}
else if (typeof payload === 'function') {
form = payload();
}
else {
form = payload;
}
const file = yield remoteMill(node.mill, resolved, form, {});
dir.files[':single'] = file;
}
else if (node.links) {
// Determine order
const steps = SchemaMiller.sortLinksByDependency(node.links);
// Send each link
// eslint-disable-next-line no-restricted-syntax
for (const step of steps) {
let form;
const normal = SchemaMiller.normalizeOptions(step.link || {});
const resolved = SchemaMiller.resolveDependency(normal, dir);
if (resolved.use) {
// It's an existing 'file', hash will pass as payload, so don't send file again
form = undefined;
}
else if (typeof payload === 'function') {
form = payload();
}
else {
form = payload;
}
// Must be synchronous for dependencies
const file = yield remoteMill(step.link.mill, resolved, form, {});
dir.files[step.name] = file;
}
}
return dir;
});
}
}
exports.default = SchemaMiller;
;