'use strict';
import extend from 'extend';
import Base from './base';
import fetch from './deps/fetch';
import join from './deps/utils/join';
import Blob from './blob';
import BatchBlob from './upload/blob';
import BatchUpload from './upload/batch';
import FormData from './deps/form-data';
/**
* The `Operation` class allows to execute an operation on a Nuxeo Platform instance.
*
* **Cannot directly be instantiated**
*
* @example
* var Nuxeo = require('nuxeo')
* var nuxeo = new Nuxeo({
* baseUrl: 'http://localhost:8080/nuxeo',
* auth: {
* username: 'Administrator',
* password: 'Administrator',
* }
* });
* nuxeo.operation('Document.GetChild')
* .input('/default-domain')
* .params({
* name: 'workspaces',
* })
* .execute().then((res) => {
// res.uid !== null
* // res.title === 'Workspaces'
* }).catch(error => throw new Error(error));
*/
class Operation extends Base {
/**
* Creates an Operation.
* @param {string} opts - The configuration options.
* @param {string} opts.id - The ID of the operation.
* @param {string} opts.url - The automation URL.
*/
constructor(opts = {}) {
const options = extend(true, {}, opts);
super(options);
this._nuxeo = options.nuxeo;
this._id = options.id;
this._url = options.url;
this._automationParams = {
params: {},
context: {},
input: undefined,
};
}
/**
* Adds an operation param.
* @param {string} name - The param name.
* @param {string} value - The param value.
* @returns {Operation} The operation itself.
*/
param(name, value) {
this._automationParams.params[name] = value;
return this;
}
/**
* Adds operation params. The given params are merged with the existing ones if any.
* @param {object} params - The params to be merge with the existing ones.
* @returns {Operation} The operation itself.
*/
params(params) {
this._automationParams.params = extend(true, {}, this._automationParams.params, params);
return this;
}
/**
* Sets this operation context.
* @param {object} context - The operation context.
* @returns {Operation} The operation itself.
*/
context(context) {
this._automationParams.context = context;
return this;
}
/**
* Sets this operation input.
* @param {string|Array|Blob|BatchBlob|BatchUpload} input - The operation input.
* @returns {Operation} The operation itself.
*/
input(input) {
this._automationParams.input = input;
return this;
}
/**
* Executes this operation.
* @param {object} opts - Options overriding the ones from the Operation object.
* @returns {Promise} A Promise object resolved with the result of the Operation.
*/
execute(opts = {}) {
const schemas = opts.schemas || this._schemas;
let headers = extend(true, {}, this._headers);
if (schemas.length > 0) {
headers['X-NXDocumentProperties'] = schemas.join(',');
}
const repositoryName = opts.repositoryName || this._repositoryName;
if (repositoryName !== undefined) {
headers['X-NXRepository'] = repositoryName;
}
headers['Content-Type'] = this._computeContentTypeHeader(this._automationParams.input);
headers = extend(true, headers, opts.headers);
let finalOptions = {
headers,
method: 'POST',
url: this._computeRequestURL(),
body: this._computeRequestBody(),
timeout: this._timeout,
transactionTimeout: this._transactionTimeout,
httpTimeout: this._httpTimeout,
auth: this._auth,
};
finalOptions = extend(true, finalOptions, opts);
return fetch(finalOptions);
}
_computeContentTypeHeader(input) {
let contentType = 'application/json+nxrequest';
if (this._isMultipartInput(input)) {
contentType = 'multipart/form-data';
} else if (this._isBatchInput(input)) {
contentType = 'application/json';
}
return contentType;
}
_computeRequestURL() {
const input = this._automationParams.input;
if (input instanceof BatchBlob) {
return join(this._nuxeo._restURL, 'upload', input['upload-batch'], input['upload-fileId'], 'execute', this._id);
} else if (input instanceof BatchUpload) {
return join(this._nuxeo._restURL, 'upload', input._batchId, 'execute', this._id);
}
return join(this._url, this._id);
}
_computeRequestBody() {
const input = this._automationParams.input;
if (this._isBatchInput(input)) {
// no input needed
const body = extend(true, {}, this._automationParams);
body.input = undefined;
return body;
}
if (input instanceof Array) {
if (input.length > 0) {
const first = input[0];
if (typeof first === 'string') {
// assume ref list
this._automationParams.input = `docs:${input.join(',')}`;
return this._automationParams;
} else if (first instanceof Blob) {
// blob list => multipart
const automationParams = {
params: this._automationParams.params,
context: this._automationParams.context,
};
const form = new FormData();
form.append('params', JSON.stringify(automationParams));
let inputIndex = 0;
for (const blob of input) {
form.append(`input#${inputIndex++}`, blob.content, blob.name);
}
return form;
}
}
} else if (this._automationParams.input instanceof Blob) {
const automationParams = {
params: this._automationParams.params,
context: this._automationParams.context,
};
const form = new FormData();
form.append('params', JSON.stringify(automationParams));
form.append('input', input.content, input.name);
return form;
}
return this._automationParams;
}
_isMultipartInput(input) {
if (input instanceof Array) {
if (input.length > 0) {
const first = input[0];
if (first instanceof Blob) {
return true;
}
}
} else if (input instanceof Blob) {
return true;
}
return false;
}
_isBatchInput(input) {
return input instanceof BatchUpload || input instanceof BatchBlob;
}
}
export default Operation;