@twilio-labs/serverless-api
Version:
API-wrapper for the Twilio Serverless API
159 lines (158 loc) • 6.26 kB
JavaScript
/** @module @twilio-labs/serverless-api/dist/api */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.downloadFunctionVersion = exports.listFunctionVersions = exports.isFunctionSid = exports.uploadFunction = exports.getOrCreateFunctionResources = exports.listFunctionResources = exports.createFunctionResource = void 0;
const debug_1 = __importDefault(require("debug"));
const form_data_1 = __importDefault(require("form-data"));
const content_type_1 = require("../utils/content-type");
const error_1 = require("../utils/error");
const api_client_1 = require("./utils/api-client");
const pagination_1 = require("./utils/pagination");
const log = (0, debug_1.default)('twilio-serverless-api:functions');
/**
* Creates a new Function instance by calling the API
*
* @param {string} name the friendly name of the function to create
* @param {string} serviceSid the service the function should belong to
* @param {TwilioServerlessApiClient} client API client
* @returns {Promise<FunctionApiResource>}
*/
async function createFunctionResource(name, serviceSid, client) {
try {
const resp = await client.request('post', `Services/${serviceSid}/Functions`, {
form: {
FriendlyName: name,
},
});
return resp.body;
}
catch (err) {
log('%O', new error_1.ClientApiError(err));
throw new Error(`Failed to create "${name}" function`);
}
}
exports.createFunctionResource = createFunctionResource;
/**
* Lists all functions associated to a service
*
* @export
* @param {string} serviceSid the service to look up
* @param {TwilioServerlessApiClient} client API client
* @returns
*/
async function listFunctionResources(serviceSid, client) {
try {
return (0, pagination_1.getPaginatedResource)(client, `Services/${serviceSid}/Functions`);
}
catch (err) {
log('%O', new error_1.ClientApiError(err));
throw err;
}
}
exports.listFunctionResources = listFunctionResources;
/**
* Given a list of functions it will create the ones that don't exist and retrieves the others
*
* @export
* @param {FileInfo[]} functions list of functions to get or create
* @param {string} serviceSid service the functions belong to
* @param {TwilioServerlessApiClient} client API client
* @returns {Promise<FunctionResource[]>}
*/
async function getOrCreateFunctionResources(functions, serviceSid, client) {
const output = [];
const existingFunctions = await listFunctionResources(serviceSid, client);
const functionsToCreate = [];
functions.forEach((fn) => {
const existingFn = existingFunctions.find((f) => fn.name === f.friendly_name);
if (!existingFn) {
functionsToCreate.push({ ...fn });
}
else {
output.push({
...fn,
sid: existingFn.sid,
});
}
});
const createdFunctions = await Promise.all(functionsToCreate.map(async (fn) => {
const newFunction = await createFunctionResource(fn.name, serviceSid, client);
return {
...fn,
sid: newFunction.sid,
};
}));
return [...output, ...createdFunctions];
}
exports.getOrCreateFunctionResources = getOrCreateFunctionResources;
/**
* Creates a new Version to be used for uploading a new function
*
* @param {FunctionResource} fn the function the version should be created for
* @param {string} serviceSid the service related to the function
* @param {TwilioServerlessApiClient} client API client
* @returns {Promise<VersionResource>}
*/
async function createFunctionVersion(fn, serviceSid, client, clientConfig) {
try {
const contentType = (await (0, content_type_1.getContentType)(fn.content, fn.filePath || 'application/json')) ||
'application/javascript';
log('Uploading asset via form data with content-type "%s"', contentType);
const contentOpts = {
filename: fn.name,
contentType: contentType,
};
const form = new form_data_1.default();
form.append('Path', fn.path);
form.append('Visibility', fn.access);
form.append('Content', fn.content, contentOpts);
const resp = await client.request('post', `Services/${serviceSid}/Functions/${fn.sid}/Versions`, {
responseType: 'text',
prefixUrl: (0, api_client_1.getApiUrl)(clientConfig, 'serverless-upload'),
body: form,
});
return JSON.parse(resp.body);
}
catch (err) {
log('%O', new error_1.ClientApiError(err));
throw new Error(`Failed to upload Function ${fn.name}`);
}
}
/**
* Uploads a given function by creating a new version, reading the content if necessary and uploading the content
*
* @export
* @param {FunctionResource} fn function to be uploaded
* @param {string} serviceSid service that the function is connected to
* @param {TwilioServerlessApiClient} client API client
* @returns {Promise<Sid>}
*/
async function uploadFunction(fn, serviceSid, client, clientConfig) {
const version = await createFunctionVersion(fn, serviceSid, client, clientConfig);
return version.sid;
}
exports.uploadFunction = uploadFunction;
/**
* Checks if a string is an function SID by checking its prefix and length
*
* @export
* @param {string} str the string to check
* @returns
*/
function isFunctionSid(str) {
return str.startsWith('ZH') && str.length === 34;
}
exports.isFunctionSid = isFunctionSid;
async function listFunctionVersions(serviceSid, functionSid, client) {
const resp = await client.request('get', `Services/${serviceSid}/Functions/${functionSid}/Versions`);
return resp.body;
}
exports.listFunctionVersions = listFunctionVersions;
async function downloadFunctionVersion(serviceSid, functionSid, functionVersionSid, client) {
const resp = await client.request('get', `Services/${serviceSid}/Functions/${functionSid}/Versions/${functionVersionSid}/Content`);
return resp.body;
}
exports.downloadFunctionVersion = downloadFunctionVersion;
;