blt/scripts/rebuild-cloud-sdk.js

135 lines
4.4 KiB
JavaScript

module.exports = {
friendlyName: 'Rebuild Cloud SDK',
description: 'Regenerate the configuration for the "Cloud SDK" -- the JavaScript module used for AJAX and WebSockets.',
fn: async function(){
var path = require('path');
var endpointsByMethodName = {};
var extraEndpointsOnlyForTestsByMethodName = {};
for (let address in sails.config.routes) {
let target = sails.config.routes[address];
// If the route target is an array, then only consider
// the very last sub-target in the array.
if (_.isArray(target)) {
target = _.last(target);
}//fi
// Skip redirects
// (Note that, by doing this, we also skip traditional shorthand
// -- that's ok though.)
if (_.isString(target)) {
continue;
}
// Skip routes whose target doesn't contain `action` for any
// other miscellaneous reason.
if (!target.action) {
continue;
}
// Just about everything else gets a Cloud SDK method.
// We determine its name using the bare action name.
var bareActionName = _.last(target.action.split(/\//));
var methodName = _.camelCase(bareActionName);
var expandedAddress = sails.getRouteFor(target);
// Skip routes that just serve views.
// (but still generate them for use in tests, for convenience)
if (target.view || (bareActionName.match(/^view-/))) {
extraEndpointsOnlyForTestsByMethodName[methodName] = {
verb: (expandedAddress.method||'get').toUpperCase(),
url: expandedAddress.url
};
continue;
}//•
endpointsByMethodName[methodName] = {
verb: (expandedAddress.method||'get').toUpperCase(),
url: expandedAddress.url,
};
// If this is an actions2 action, then determine appropriate serial usage.
// (deduced the same way as helpers)
// > If there is no such action for some reason, then don't compile a
// > method for this one.
var requestable = sails.getActions()[target.action];
if (!requestable) {
sails.log.warn('Skipping unrecognized action: `'+target.action+'`');
continue;
}
var def = requestable.toJSON && requestable.toJSON();
if (def && def.fn) {
if (def.args !== undefined) {
endpointsByMethodName[methodName].args = def.args;
} else {
endpointsByMethodName[methodName].args = _.reduce(def.inputs, (args, inputDef, inputCodeName)=>{
args.push(inputCodeName);
return args;
}, []);
}
}
// And we determine whether it needs to communicate over WebSockets
// by checking for an additional property in the route target.
if (target.isSocket || target.hasSocketFeatures) {
endpointsByMethodName[methodName].protocol = 'io.socket';
}
}//∞
// Smash and rewrite the `cloud.setup.js` file in the assets folder to
// reflect the latest set of available cloud actions exposed by this Sails
// app (as determined by its routes above)
await sails.helpers.fs.write.with({
destination: path.resolve(sails.config.appPath, 'assets/js/cloud.setup.js'),
force: true,
string: ``+
`/**
* cloud.setup.js
*
* Configuration for this Sails app's generated browser SDK ("Cloud").
*
* Above all, the purpose of this file is to provide endpoint definitions,
* each of which corresponds with one particular route+action on the server.
*
* > This file was automatically generated.
* > (To regenerate, run \`sails run rebuild-cloud-sdk\`)
*/
Cloud.setup({
/* eslint-disable */
methods: ${JSON.stringify(endpointsByMethodName)}
/* eslint-enable */
});`+
`\n`
});
// Also, if a `test/` folder exists, set up a barebones bounce of this data
// as a JSON file inside of it, for testing purposes:
var hasTestFolder = await sails.helpers.fs.exists(path.resolve(sails.config.appPath, 'test/'));
if (hasTestFolder) {
await sails.helpers.fs.write.with({
destination: path.resolve(sails.config.appPath, 'test/private/CLOUD_SDK_METHODS.json'),
string: JSON.stringify(_.extend(endpointsByMethodName, extraEndpointsOnlyForTestsByMethodName)),
force: true
});
}
sails.log.info('--');
sails.log.info('Successfully rebuilt Cloud SDK for use in the browser.');
sails.log.info('(and CLOUD_SDK_METHODS.json for use in automated tests)');
}
};