@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.
Files changed (3) hide show
  1. package/dist/index.cjs +113 -10
  2. package/dist/index.js +113 -10
  3. 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
- "creative": {
16437
- "description": "This field is required for create. The ID or creative spec of the ad creative to be used by this ad. You can read more about creatives here. You may supply the ID within an object as follows:",
16438
- "type": "AdCreative"
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=${fields.join(",")}&limit=${this.fieldsSchema[nodeName].limit}`;
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 {string} logContext - Context for logging
18965
+ * @param {Array} fields - Fields that were requested
18865
18966
  * @return {Array} All fetched data
18866
18967
  * @private
18867
18968
  */
18868
- _fetchPaginatedData(initialUrl, nodeName, logContext = "") {
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
- record = this.castRecordFields(nodeName, record);
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
- "creative": {
16442
- "description": "This field is required for create. The ID or creative spec of the ad creative to be used by this ad. You can read more about creatives here. You may supply the ID within an object as follows:",
16443
- "type": "AdCreative"
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=${fields.join(",")}&limit=${this.fieldsSchema[nodeName].limit}`;
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 {string} logContext - Context for logging
18970
+ * @param {Array} fields - Fields that were requested
18870
18971
  * @return {Array} All fetched data
18871
18972
  * @private
18872
18973
  */
18873
- _fetchPaginatedData(initialUrl, nodeName, logContext = "") {
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
- record = this.castRecordFields(nodeName, record);
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owox/connectors",
3
- "version": "0.12.0-next-20251104090753",
3
+ "version": "0.12.0-next-20251104123907",
4
4
  "description": "Connectors and storages for different data sources",
5
5
  "license": "MIT",
6
6
  "publishConfig": {