n8n-nodes-dataverse
Version:
n8n community node for communicating to dataverse
313 lines • 14.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.dataverseAuth = void 0;
const axios_1 = __importDefault(require("axios"));
class dataverseAuth {
constructor() {
this.accessToken = null;
this.tokenExpiry = 0;
this.scope = null;
this.credentials = null;
this.axiosInstance = null;
this.name = 'dataverseAuth';
this.displayName = 'Dataverse Auth';
this.properties = [
{
displayName: 'Authentication Method',
name: 'authenticationMethod',
type: 'options',
options: [
{
name: 'Client Credentials',
value: 'clientCredentials',
}
],
default: 'clientCredentials',
},
{
displayName: 'Tenant ID',
name: 'tenantId',
type: 'string',
default: '',
description: 'The Azure Active Directory tenant ID',
},
{
displayName: 'Client ID',
name: 'clientId',
type: 'string',
default: '',
description: 'The application (client) ID registered in Azure AD',
},
{
displayName: 'Client Secret',
name: 'clientSecret',
type: 'string',
typeOptions: { password: true },
default: '',
description: 'The client secret generated for the application in Azure AD',
},
{
displayName: 'Scope',
name: 'scope',
type: 'string',
default: 'https://<your-org-name>.crm4.dynamics.com',
description: 'The URL of your Dataverse environment (e.g., https://<your-org-name>.crm4.dynamics.com)',
},
];
}
static getCachedTables() {
return dataverseAuth.cachedTables;
}
static setCachedTables(tables) {
dataverseAuth.cachedTables = tables;
}
static getCachedEntityColumns(entityName) {
return dataverseAuth.cachedEntityColumns[entityName];
}
static setCachedEntityColumns(entityName, options) {
dataverseAuth.cachedEntityColumns[entityName] = options;
}
updateAxiosInstance() {
if (!this.scope || !this.accessToken)
return;
if (!this.axiosInstance) {
this.axiosInstance = axios_1.default.create({
baseURL: this.scope,
headers: {
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
'OData-MaxPageSize': '5000',
},
});
}
else {
this.axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${this.accessToken}`;
}
}
async authenticate(credentials, requestOptions) {
this.credentials = credentials;
const { tenantId, clientId, clientSecret, scope } = credentials;
this.scope = scope;
if (this.accessToken && Date.now() < this.tokenExpiry) {
this.updateAxiosInstance();
requestOptions.headers = {
...requestOptions.headers,
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
'OData-MaxPageSize': '5000',
};
return requestOptions;
}
const tokenResponse = await this.getToken(String(tenantId), String(clientId), String(clientSecret), String(scope));
this.accessToken = tokenResponse.access_token;
const expiresIn = tokenResponse.expires_in ? parseInt(tokenResponse.expires_in, 10) : 3600;
this.tokenExpiry = Date.now() + expiresIn * 1000;
this.updateAxiosInstance();
requestOptions.headers = {
...requestOptions.headers,
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
'OData-MaxPageSize': '5000',
};
return requestOptions;
}
async getToken(tenantId, clientId, clientSecret, resourceURL) {
try {
const url = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
const data = new URLSearchParams();
data.append('grant_type', 'client_credentials');
data.append('client_id', clientId);
data.append('client_secret', clientSecret);
data.append('scope', `${resourceURL}/.default`);
const response = await axios_1.default.post(url, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
return response.data;
}
catch (error) {
throw new Error(`Error fetching token: ${error}`);
}
}
async ensureAuthenticated() {
if (!this.accessToken || Date.now() >= this.tokenExpiry) {
if (!this.credentials) {
throw new Error('Credentials are not available.');
}
const { tenantId, clientId, clientSecret, scope } = this.credentials;
const tokenResponse = await this.getToken(String(tenantId), String(clientId), String(clientSecret), String(scope));
this.accessToken = tokenResponse.access_token;
const expiresIn = tokenResponse.expires_in ? parseInt(tokenResponse.expires_in, 10) : 3600;
this.tokenExpiry = Date.now() + expiresIn * 1000;
this.updateAxiosInstance();
}
}
async CreateData(entityName, payload, columnsToUpdate) {
var _a, _b, _c;
await this.ensureAuthenticated();
if (!this.axiosInstance)
throw new Error('Axios instance not available');
debugger;
let body = {};
if (payload && Object.keys(payload).length > 0) {
body = { ...payload };
}
if (columnsToUpdate &&
columnsToUpdate.columnValues &&
Array.isArray(columnsToUpdate.columnValues)) {
for (const columnUpdate of columnsToUpdate.columnValues) {
if (columnUpdate.columnName) {
body[columnUpdate.columnName] = columnUpdate.columnValue;
}
}
}
const databody = JSON.stringify(body);
const modifiedEntityLogicalName = this.modifyEntityLogicalName(entityName);
const fullApiUrl = `/api/data/v9.2/${modifiedEntityLogicalName}`;
const headers = {
"OData-MaxVersion": "4.0",
"Content-Type": "application/json; charset=utf-8",
"Accept": "application/json",
"Prefer": "odata.include-annotations=*",
};
console.log(`Url : ${fullApiUrl} , Body : ${databody}`);
try {
const response = await this.axiosInstance.post(fullApiUrl, databody, { headers });
return response.data;
}
catch (error) {
throw new Error(`Dataverse API error: ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status} - ${(_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText}. Details: ${JSON.stringify((_c = error.response) === null || _c === void 0 ? void 0 : _c.data)}`);
}
}
async UpdateData(entityName, recordId, updateData, columnsToUpdate) {
var _a, _b, _c;
await this.ensureAuthenticated();
if (!this.axiosInstance)
throw new Error('Axios instance not available');
let body = {};
if (updateData && Object.keys(updateData).length > 0) {
body = { ...updateData };
}
if (columnsToUpdate &&
columnsToUpdate.columnValues &&
Array.isArray(columnsToUpdate.columnValues)) {
for (const columnUpdate of columnsToUpdate.columnValues) {
if (columnUpdate.columnName) {
body[columnUpdate.columnName] = columnUpdate.columnValue;
}
}
}
const databody = JSON.stringify(body);
const modifiedEntityLogicalName = this.modifyEntityLogicalName(entityName);
const fullApiUrl = `/api/data/v9.2/${modifiedEntityLogicalName}(${recordId})`;
const headers = {
"OData-MaxVersion": "4.0",
"Content-Type": "application/json; charset=utf-8",
"Accept": "application/json",
"Prefer": "odata.include-annotations=*",
};
try {
const response = await this.axiosInstance.patch(fullApiUrl, databody, { headers });
return response.data;
}
catch (error) {
throw new Error(`Dataverse API error: ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status} - ${(_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText}. Details: ${JSON.stringify((_c = error.response) === null || _c === void 0 ? void 0 : _c.data)}`);
}
}
async ListEntityColumns(entityName) {
var _a, _b, _c;
await this.ensureAuthenticated();
if (!this.axiosInstance)
throw new Error('Axios instance not available');
const apiUrl = `/api/data/v9.2/EntityDefinitions(LogicalName='${entityName}')/Attributes?$select=LogicalName,DisplayName`;
try {
const response = await this.axiosInstance.get(apiUrl);
const columns = response.data.value.map((attribute) => {
var _a, _b;
return ({
logicalName: attribute.LogicalName,
displayName: ((_b = (_a = attribute.DisplayName) === null || _a === void 0 ? void 0 : _a.UserLocalizedLabel) === null || _b === void 0 ? void 0 : _b.Label) || attribute.LogicalName,
});
});
return { columns };
}
catch (error) {
throw new Error(`Dataverse API error: ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status} - ${(_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText}. Details: ${JSON.stringify((_c = error.response) === null || _c === void 0 ? void 0 : _c.data)}`);
}
}
async ListTables() {
var _a, _b, _c;
await this.ensureAuthenticated();
if (!this.axiosInstance)
throw new Error('Axios instance not available');
const apiUrl = `/api/data/v9.2/EntityDefinitions?$select=LogicalName,DisplayName`;
try {
const response = await this.axiosInstance.get(apiUrl);
const entities = response.data.value.map((entity) => {
var _a, _b;
return ({
logicalName: entity.LogicalName,
displayName: ((_b = (_a = entity.DisplayName) === null || _a === void 0 ? void 0 : _a.UserLocalizedLabel) === null || _b === void 0 ? void 0 : _b.Label) || entity.LogicalName,
});
});
return { tables: entities };
}
catch (error) {
throw new Error(`Dataverse API error: ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status} - ${(_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText}. Details: ${JSON.stringify((_c = error.response) === null || _c === void 0 ? void 0 : _c.data)}`);
}
}
extractEntityNameFromFetchXml(fetchXml) {
const match = fetchXml.match(/<entity name=['"]([^'"]+)['"]/);
return match ? match[1] : null;
}
modifyEntityLogicalName(entityLogicalName) {
if (entityLogicalName.endsWith('y')) {
return entityLogicalName.slice(0, -1) + 'ies';
}
else if (entityLogicalName.endsWith('s')) {
return entityLogicalName + 'es';
}
else {
return entityLogicalName + 's';
}
}
async GetData(type, entityName, query) {
var _a, _b, _c;
await this.ensureAuthenticated();
if (!this.axiosInstance)
throw new Error('Axios instance not available');
let fullApiUrl = '';
if (type === "FETCHXML") {
const entityLogicalName = this.extractEntityNameFromFetchXml(query);
if (!entityLogicalName) {
throw new Error("Failed to extract entity name from FetchXML.");
}
const modifiedEntityLogicalName = this.modifyEntityLogicalName(entityLogicalName);
fullApiUrl = `/api/data/v9.2/${modifiedEntityLogicalName}?fetchXml=${encodeURIComponent(query)}`;
}
else if (type === "ODATA") {
fullApiUrl = `/api/data/v9.2/${query}`;
}
else if (type === "column") {
const modifiedEntityLogicalName = this.modifyEntityLogicalName(entityName);
fullApiUrl = `/api/data/v9.2/${modifiedEntityLogicalName}?$select=${query}`;
}
try {
const response = await this.axiosInstance.get(fullApiUrl, {
headers: { Prefer: 'odata.include-annotations="*"' },
});
return response.data;
}
catch (error) {
throw new Error(`Dataverse API error: ${(_a = error.response) === null || _a === void 0 ? void 0 : _a.status} - ${(_b = error.response) === null || _b === void 0 ? void 0 : _b.statusText}. Details: ${JSON.stringify((_c = error.response) === null || _c === void 0 ? void 0 : _c.data)}`);
}
}
}
exports.dataverseAuth = dataverseAuth;
dataverseAuth.cachedTables = null;
dataverseAuth.cachedEntityColumns = {};
//# sourceMappingURL=dataverseAuth.credentials.js.map