@owox/connectors 0.12.0-next-20251104090753 → 0.12.0-next-20251104123907
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +113 -10
- package/dist/index.js +113 -10
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -16433,9 +16433,30 @@ const FacebookMarketing = (function() {
|
|
|
16433
16433
|
"description": "Time when the ad was created.",
|
|
16434
16434
|
"type": "datetime"
|
|
16435
16435
|
},
|
|
16436
|
-
"
|
|
16437
|
-
"description": "
|
|
16438
|
-
"type": "
|
|
16436
|
+
"creative_id": {
|
|
16437
|
+
"description": "Unique ID for the ad creative",
|
|
16438
|
+
"type": "string",
|
|
16439
|
+
"apiName": "creative.id"
|
|
16440
|
+
},
|
|
16441
|
+
"creative_effective_object_story_id": {
|
|
16442
|
+
"description": "The ID of a page post to use in an ad, regardless of whether its an organic or unpublished page post",
|
|
16443
|
+
"type": "string",
|
|
16444
|
+
"apiName": "creative.effective_object_story_id"
|
|
16445
|
+
},
|
|
16446
|
+
"creative_name": {
|
|
16447
|
+
"description": "Name of the ad creative as seen in the ad accounts library",
|
|
16448
|
+
"type": "string",
|
|
16449
|
+
"apiName": "creative.name"
|
|
16450
|
+
},
|
|
16451
|
+
"creative_object_story_spec": {
|
|
16452
|
+
"description": "Object story spec containing page_id and other details",
|
|
16453
|
+
"type": "string",
|
|
16454
|
+
"apiName": "creative.object_story_spec"
|
|
16455
|
+
},
|
|
16456
|
+
"creative_url_tags": {
|
|
16457
|
+
"description": "A set of query string parameters which will replace or be appended to urls clicked from page post ads",
|
|
16458
|
+
"type": "string",
|
|
16459
|
+
"apiName": "creative.url_tags"
|
|
16439
16460
|
},
|
|
16440
16461
|
"creative_asset_groups_spec": {
|
|
16441
16462
|
"description": "This field is used to create ads using the Flexible ad format. You can read more about that here",
|
|
@@ -18725,14 +18746,14 @@ const FacebookMarketing = (function() {
|
|
|
18725
18746
|
case "ad-account/insights-by-link-url-asset":
|
|
18726
18747
|
return this._fetchInsightsData({ nodeName, accountId, fields, timeRange, url });
|
|
18727
18748
|
case "ad-group":
|
|
18728
|
-
url += `act_${accountId}/ads?fields=${
|
|
18749
|
+
url += `act_${accountId}/ads?fields=${this._buildFieldsString({ nodeName, fields })}&limit=${this.fieldsSchema[nodeName].limit}`;
|
|
18729
18750
|
break;
|
|
18730
18751
|
default:
|
|
18731
18752
|
throw new Error(`End point for ${nodeName} is not implemented yet. Feel free add idea here: https://github.com/OWOX/owox-data-marts/discussions/categories/ideas`);
|
|
18732
18753
|
}
|
|
18733
18754
|
console.log(`Facebook API URL:`, url);
|
|
18734
18755
|
url += `&access_token=${this.config.AccessToken.value}`;
|
|
18735
|
-
return this._fetchPaginatedData(url, nodeName);
|
|
18756
|
+
return this._fetchPaginatedData(url, nodeName, fields);
|
|
18736
18757
|
}
|
|
18737
18758
|
//---- castRecordFields -------------------------------------------------
|
|
18738
18759
|
/**
|
|
@@ -18805,7 +18826,7 @@ const FacebookMarketing = (function() {
|
|
|
18805
18826
|
nodeName,
|
|
18806
18827
|
url
|
|
18807
18828
|
});
|
|
18808
|
-
const allData = this._fetchPaginatedData(requestUrl, nodeName);
|
|
18829
|
+
const allData = this._fetchPaginatedData(requestUrl, nodeName, fields);
|
|
18809
18830
|
if (this.config.ProcessShortLinks.value && allData.length > 0 && allData.some((record) => record.link_url_asset)) {
|
|
18810
18831
|
return processShortLinks(allData, {
|
|
18811
18832
|
shortLinkField: "link_url_asset",
|
|
@@ -18855,17 +18876,97 @@ const FacebookMarketing = (function() {
|
|
|
18855
18876
|
insightsUrl += `&access_token=${this.config.AccessToken.value}`;
|
|
18856
18877
|
return insightsUrl;
|
|
18857
18878
|
}
|
|
18879
|
+
//---- _buildFieldsString ------------------------------------------------
|
|
18880
|
+
/**
|
|
18881
|
+
* Build fields string for Facebook API request
|
|
18882
|
+
* Filters out fields that don't exist in schema
|
|
18883
|
+
* Handles nested fields using Facebook's syntax: parent{field1,field2}
|
|
18884
|
+
*
|
|
18885
|
+
* @param {Object} params - Parameters object
|
|
18886
|
+
* @param {string} params.nodeName - Node name
|
|
18887
|
+
* @param {Array} params.fields - Fields to fetch
|
|
18888
|
+
* @return {string} Fields string for API request
|
|
18889
|
+
* @private
|
|
18890
|
+
*/
|
|
18891
|
+
_buildFieldsString({ nodeName, fields }) {
|
|
18892
|
+
const nestedFields = {};
|
|
18893
|
+
const regularFields = [];
|
|
18894
|
+
const skippedFields = [];
|
|
18895
|
+
for (const field of fields) {
|
|
18896
|
+
const fieldConfig = this.fieldsSchema[nodeName].fields[field];
|
|
18897
|
+
if (!fieldConfig) {
|
|
18898
|
+
skippedFields.push(field);
|
|
18899
|
+
continue;
|
|
18900
|
+
}
|
|
18901
|
+
if (fieldConfig.apiName && fieldConfig.apiName.includes(".")) {
|
|
18902
|
+
const [parent, ...childParts] = fieldConfig.apiName.split(".");
|
|
18903
|
+
const child = childParts.join(".");
|
|
18904
|
+
if (!nestedFields[parent]) {
|
|
18905
|
+
nestedFields[parent] = [];
|
|
18906
|
+
}
|
|
18907
|
+
nestedFields[parent].push(child);
|
|
18908
|
+
} else {
|
|
18909
|
+
regularFields.push(field);
|
|
18910
|
+
}
|
|
18911
|
+
}
|
|
18912
|
+
if (skippedFields.length > 0) {
|
|
18913
|
+
console.log(`Skipped fields not found in ${nodeName} schema:`, skippedFields.join(", "));
|
|
18914
|
+
}
|
|
18915
|
+
const finalFields = [...regularFields];
|
|
18916
|
+
for (const [parent, children] of Object.entries(nestedFields)) {
|
|
18917
|
+
finalFields.push(`${parent}{${children.join(",")}}`);
|
|
18918
|
+
}
|
|
18919
|
+
return finalFields.join(",");
|
|
18920
|
+
}
|
|
18921
|
+
//---- _mapResultToColumns -----------------------------------------------
|
|
18922
|
+
/**
|
|
18923
|
+
* Map API result to requested column names
|
|
18924
|
+
* Only includes fields that exist in schema and were requested
|
|
18925
|
+
* Handles nested fields using apiName mapping
|
|
18926
|
+
*
|
|
18927
|
+
* @param {Object} result - API response result
|
|
18928
|
+
* @param {string} nodeName - Node name for schema lookup
|
|
18929
|
+
* @param {Array<string>} requestedFields - Fields that were requested
|
|
18930
|
+
* @return {Object} Mapped result with only requested columns
|
|
18931
|
+
* @private
|
|
18932
|
+
*/
|
|
18933
|
+
_mapResultToColumns(result, nodeName, requestedFields) {
|
|
18934
|
+
const mapped = {};
|
|
18935
|
+
for (const fieldName of requestedFields) {
|
|
18936
|
+
const fieldConfig = this.fieldsSchema[nodeName].fields[fieldName];
|
|
18937
|
+
if (!fieldConfig) {
|
|
18938
|
+
continue;
|
|
18939
|
+
}
|
|
18940
|
+
if (fieldConfig.apiName) {
|
|
18941
|
+
mapped[fieldName] = this._getNestedValue(result, fieldConfig.apiName);
|
|
18942
|
+
} else {
|
|
18943
|
+
mapped[fieldName] = result[fieldName];
|
|
18944
|
+
}
|
|
18945
|
+
}
|
|
18946
|
+
return mapped;
|
|
18947
|
+
}
|
|
18948
|
+
//---- _getNestedValue ---------------------------------------------------
|
|
18949
|
+
/**
|
|
18950
|
+
* Get nested value from object using dot-notation path
|
|
18951
|
+
* @param {Object} obj - Object to search in
|
|
18952
|
+
* @param {string} path - Dot-notation path (e.g. 'creative.id')
|
|
18953
|
+
* @return {*} Value at path or undefined
|
|
18954
|
+
* @private
|
|
18955
|
+
*/
|
|
18956
|
+
_getNestedValue(obj, path) {
|
|
18957
|
+
return path.split(".").reduce((current, key) => current == null ? void 0 : current[key], obj);
|
|
18958
|
+
}
|
|
18858
18959
|
//---- _fetchPaginatedData -----------------------------------------------
|
|
18859
18960
|
/**
|
|
18860
18961
|
* Fetch paginated data from Facebook API
|
|
18861
18962
|
*
|
|
18862
18963
|
* @param {string} initialUrl - Initial URL to fetch
|
|
18863
18964
|
* @param {string} nodeName - Node name for field casting
|
|
18864
|
-
* @param {
|
|
18965
|
+
* @param {Array} fields - Fields that were requested
|
|
18865
18966
|
* @return {Array} All fetched data
|
|
18866
18967
|
* @private
|
|
18867
18968
|
*/
|
|
18868
|
-
_fetchPaginatedData(initialUrl, nodeName,
|
|
18969
|
+
_fetchPaginatedData(initialUrl, nodeName, fields) {
|
|
18869
18970
|
var allData = [];
|
|
18870
18971
|
var nextPageURL = initialUrl;
|
|
18871
18972
|
while (nextPageURL) {
|
|
@@ -18873,8 +18974,10 @@ const FacebookMarketing = (function() {
|
|
|
18873
18974
|
var jsonData = JSON.parse(response.getContentText());
|
|
18874
18975
|
if ("data" in jsonData) {
|
|
18875
18976
|
nextPageURL = jsonData.paging ? jsonData.paging.next : null;
|
|
18876
|
-
jsonData.data.forEach((record) => {
|
|
18877
|
-
|
|
18977
|
+
jsonData.data.forEach((record, index) => {
|
|
18978
|
+
let mappedRecord = this._mapResultToColumns(record, nodeName, fields);
|
|
18979
|
+
mappedRecord = this.castRecordFields(nodeName, mappedRecord);
|
|
18980
|
+
jsonData.data[index] = mappedRecord;
|
|
18878
18981
|
});
|
|
18879
18982
|
allData = allData.concat(jsonData.data);
|
|
18880
18983
|
} else {
|
package/dist/index.js
CHANGED
|
@@ -16438,9 +16438,30 @@ API Response: ${JSON.stringify(statusResult, null, 2)}`);
|
|
|
16438
16438
|
"description": "Time when the ad was created.",
|
|
16439
16439
|
"type": "datetime"
|
|
16440
16440
|
},
|
|
16441
|
-
"
|
|
16442
|
-
"description": "
|
|
16443
|
-
"type": "
|
|
16441
|
+
"creative_id": {
|
|
16442
|
+
"description": "Unique ID for the ad creative",
|
|
16443
|
+
"type": "string",
|
|
16444
|
+
"apiName": "creative.id"
|
|
16445
|
+
},
|
|
16446
|
+
"creative_effective_object_story_id": {
|
|
16447
|
+
"description": "The ID of a page post to use in an ad, regardless of whether its an organic or unpublished page post",
|
|
16448
|
+
"type": "string",
|
|
16449
|
+
"apiName": "creative.effective_object_story_id"
|
|
16450
|
+
},
|
|
16451
|
+
"creative_name": {
|
|
16452
|
+
"description": "Name of the ad creative as seen in the ad accounts library",
|
|
16453
|
+
"type": "string",
|
|
16454
|
+
"apiName": "creative.name"
|
|
16455
|
+
},
|
|
16456
|
+
"creative_object_story_spec": {
|
|
16457
|
+
"description": "Object story spec containing page_id and other details",
|
|
16458
|
+
"type": "string",
|
|
16459
|
+
"apiName": "creative.object_story_spec"
|
|
16460
|
+
},
|
|
16461
|
+
"creative_url_tags": {
|
|
16462
|
+
"description": "A set of query string parameters which will replace or be appended to urls clicked from page post ads",
|
|
16463
|
+
"type": "string",
|
|
16464
|
+
"apiName": "creative.url_tags"
|
|
16444
16465
|
},
|
|
16445
16466
|
"creative_asset_groups_spec": {
|
|
16446
16467
|
"description": "This field is used to create ads using the Flexible ad format. You can read more about that here",
|
|
@@ -18730,14 +18751,14 @@ API Response: ${JSON.stringify(statusResult, null, 2)}`);
|
|
|
18730
18751
|
case "ad-account/insights-by-link-url-asset":
|
|
18731
18752
|
return this._fetchInsightsData({ nodeName, accountId, fields, timeRange, url });
|
|
18732
18753
|
case "ad-group":
|
|
18733
|
-
url += `act_${accountId}/ads?fields=${
|
|
18754
|
+
url += `act_${accountId}/ads?fields=${this._buildFieldsString({ nodeName, fields })}&limit=${this.fieldsSchema[nodeName].limit}`;
|
|
18734
18755
|
break;
|
|
18735
18756
|
default:
|
|
18736
18757
|
throw new Error(`End point for ${nodeName} is not implemented yet. Feel free add idea here: https://github.com/OWOX/owox-data-marts/discussions/categories/ideas`);
|
|
18737
18758
|
}
|
|
18738
18759
|
console.log(`Facebook API URL:`, url);
|
|
18739
18760
|
url += `&access_token=${this.config.AccessToken.value}`;
|
|
18740
|
-
return this._fetchPaginatedData(url, nodeName);
|
|
18761
|
+
return this._fetchPaginatedData(url, nodeName, fields);
|
|
18741
18762
|
}
|
|
18742
18763
|
//---- castRecordFields -------------------------------------------------
|
|
18743
18764
|
/**
|
|
@@ -18810,7 +18831,7 @@ API Response: ${JSON.stringify(statusResult, null, 2)}`);
|
|
|
18810
18831
|
nodeName,
|
|
18811
18832
|
url
|
|
18812
18833
|
});
|
|
18813
|
-
const allData = this._fetchPaginatedData(requestUrl, nodeName);
|
|
18834
|
+
const allData = this._fetchPaginatedData(requestUrl, nodeName, fields);
|
|
18814
18835
|
if (this.config.ProcessShortLinks.value && allData.length > 0 && allData.some((record) => record.link_url_asset)) {
|
|
18815
18836
|
return processShortLinks(allData, {
|
|
18816
18837
|
shortLinkField: "link_url_asset",
|
|
@@ -18860,17 +18881,97 @@ API Response: ${JSON.stringify(statusResult, null, 2)}`);
|
|
|
18860
18881
|
insightsUrl += `&access_token=${this.config.AccessToken.value}`;
|
|
18861
18882
|
return insightsUrl;
|
|
18862
18883
|
}
|
|
18884
|
+
//---- _buildFieldsString ------------------------------------------------
|
|
18885
|
+
/**
|
|
18886
|
+
* Build fields string for Facebook API request
|
|
18887
|
+
* Filters out fields that don't exist in schema
|
|
18888
|
+
* Handles nested fields using Facebook's syntax: parent{field1,field2}
|
|
18889
|
+
*
|
|
18890
|
+
* @param {Object} params - Parameters object
|
|
18891
|
+
* @param {string} params.nodeName - Node name
|
|
18892
|
+
* @param {Array} params.fields - Fields to fetch
|
|
18893
|
+
* @return {string} Fields string for API request
|
|
18894
|
+
* @private
|
|
18895
|
+
*/
|
|
18896
|
+
_buildFieldsString({ nodeName, fields }) {
|
|
18897
|
+
const nestedFields = {};
|
|
18898
|
+
const regularFields = [];
|
|
18899
|
+
const skippedFields = [];
|
|
18900
|
+
for (const field of fields) {
|
|
18901
|
+
const fieldConfig = this.fieldsSchema[nodeName].fields[field];
|
|
18902
|
+
if (!fieldConfig) {
|
|
18903
|
+
skippedFields.push(field);
|
|
18904
|
+
continue;
|
|
18905
|
+
}
|
|
18906
|
+
if (fieldConfig.apiName && fieldConfig.apiName.includes(".")) {
|
|
18907
|
+
const [parent, ...childParts] = fieldConfig.apiName.split(".");
|
|
18908
|
+
const child = childParts.join(".");
|
|
18909
|
+
if (!nestedFields[parent]) {
|
|
18910
|
+
nestedFields[parent] = [];
|
|
18911
|
+
}
|
|
18912
|
+
nestedFields[parent].push(child);
|
|
18913
|
+
} else {
|
|
18914
|
+
regularFields.push(field);
|
|
18915
|
+
}
|
|
18916
|
+
}
|
|
18917
|
+
if (skippedFields.length > 0) {
|
|
18918
|
+
console.log(`Skipped fields not found in ${nodeName} schema:`, skippedFields.join(", "));
|
|
18919
|
+
}
|
|
18920
|
+
const finalFields = [...regularFields];
|
|
18921
|
+
for (const [parent, children] of Object.entries(nestedFields)) {
|
|
18922
|
+
finalFields.push(`${parent}{${children.join(",")}}`);
|
|
18923
|
+
}
|
|
18924
|
+
return finalFields.join(",");
|
|
18925
|
+
}
|
|
18926
|
+
//---- _mapResultToColumns -----------------------------------------------
|
|
18927
|
+
/**
|
|
18928
|
+
* Map API result to requested column names
|
|
18929
|
+
* Only includes fields that exist in schema and were requested
|
|
18930
|
+
* Handles nested fields using apiName mapping
|
|
18931
|
+
*
|
|
18932
|
+
* @param {Object} result - API response result
|
|
18933
|
+
* @param {string} nodeName - Node name for schema lookup
|
|
18934
|
+
* @param {Array<string>} requestedFields - Fields that were requested
|
|
18935
|
+
* @return {Object} Mapped result with only requested columns
|
|
18936
|
+
* @private
|
|
18937
|
+
*/
|
|
18938
|
+
_mapResultToColumns(result, nodeName, requestedFields) {
|
|
18939
|
+
const mapped = {};
|
|
18940
|
+
for (const fieldName of requestedFields) {
|
|
18941
|
+
const fieldConfig = this.fieldsSchema[nodeName].fields[fieldName];
|
|
18942
|
+
if (!fieldConfig) {
|
|
18943
|
+
continue;
|
|
18944
|
+
}
|
|
18945
|
+
if (fieldConfig.apiName) {
|
|
18946
|
+
mapped[fieldName] = this._getNestedValue(result, fieldConfig.apiName);
|
|
18947
|
+
} else {
|
|
18948
|
+
mapped[fieldName] = result[fieldName];
|
|
18949
|
+
}
|
|
18950
|
+
}
|
|
18951
|
+
return mapped;
|
|
18952
|
+
}
|
|
18953
|
+
//---- _getNestedValue ---------------------------------------------------
|
|
18954
|
+
/**
|
|
18955
|
+
* Get nested value from object using dot-notation path
|
|
18956
|
+
* @param {Object} obj - Object to search in
|
|
18957
|
+
* @param {string} path - Dot-notation path (e.g. 'creative.id')
|
|
18958
|
+
* @return {*} Value at path or undefined
|
|
18959
|
+
* @private
|
|
18960
|
+
*/
|
|
18961
|
+
_getNestedValue(obj, path) {
|
|
18962
|
+
return path.split(".").reduce((current, key) => current == null ? void 0 : current[key], obj);
|
|
18963
|
+
}
|
|
18863
18964
|
//---- _fetchPaginatedData -----------------------------------------------
|
|
18864
18965
|
/**
|
|
18865
18966
|
* Fetch paginated data from Facebook API
|
|
18866
18967
|
*
|
|
18867
18968
|
* @param {string} initialUrl - Initial URL to fetch
|
|
18868
18969
|
* @param {string} nodeName - Node name for field casting
|
|
18869
|
-
* @param {
|
|
18970
|
+
* @param {Array} fields - Fields that were requested
|
|
18870
18971
|
* @return {Array} All fetched data
|
|
18871
18972
|
* @private
|
|
18872
18973
|
*/
|
|
18873
|
-
_fetchPaginatedData(initialUrl, nodeName,
|
|
18974
|
+
_fetchPaginatedData(initialUrl, nodeName, fields) {
|
|
18874
18975
|
var allData = [];
|
|
18875
18976
|
var nextPageURL = initialUrl;
|
|
18876
18977
|
while (nextPageURL) {
|
|
@@ -18878,8 +18979,10 @@ API Response: ${JSON.stringify(statusResult, null, 2)}`);
|
|
|
18878
18979
|
var jsonData = JSON.parse(response.getContentText());
|
|
18879
18980
|
if ("data" in jsonData) {
|
|
18880
18981
|
nextPageURL = jsonData.paging ? jsonData.paging.next : null;
|
|
18881
|
-
jsonData.data.forEach((record) => {
|
|
18882
|
-
|
|
18982
|
+
jsonData.data.forEach((record, index) => {
|
|
18983
|
+
let mappedRecord = this._mapResultToColumns(record, nodeName, fields);
|
|
18984
|
+
mappedRecord = this.castRecordFields(nodeName, mappedRecord);
|
|
18985
|
+
jsonData.data[index] = mappedRecord;
|
|
18883
18986
|
});
|
|
18884
18987
|
allData = allData.concat(jsonData.data);
|
|
18885
18988
|
} else {
|