diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1421d39..116e8fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: cache gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.gradle/caches diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b42b515..b92c582 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: cache gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.gradle/caches diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 6ccd79a..844fe05 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -13,7 +13,7 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - name: cache gradle dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.gradle/caches diff --git a/destination-filters-kotlin/src/main/java/com/segment/analytics/plugins/DestinationFilters.kt b/destination-filters-kotlin/src/main/java/com/segment/analytics/plugins/DestinationFilters.kt index 33f9dfb..f8027f2 100644 --- a/destination-filters-kotlin/src/main/java/com/segment/analytics/plugins/DestinationFilters.kt +++ b/destination-filters-kotlin/src/main/java/com/segment/analytics/plugins/DestinationFilters.kt @@ -1,19 +1,24 @@ package com.segment.analytics.plugins import com.segment.analytics.kotlin.core.Analytics +import com.segment.analytics.kotlin.core.BaseEvent import com.segment.analytics.kotlin.core.Settings +import com.segment.analytics.kotlin.core.platform.DestinationPlugin import com.segment.analytics.kotlin.core.platform.Plugin +import com.segment.analytics.kotlin.core.utilities.EncodeDefaultsJson import com.segment.analytics.kotlin.core.utilities.safeJsonArray -import com.segment.analytics.liveplugins.kotlin.LivePlugins -import com.segment.analytics.liveplugins.kotlin.LivePluginsDependent +import com.segment.analytics.kotlin.core.utilities.toBaseEvent import com.segment.analytics.substrata.kotlin.JSObject import com.segment.analytics.substrata.kotlin.JSScope import com.segment.analytics.substrata.kotlin.JsonElementConverter +import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonPrimitive +import java.lang.ref.WeakReference -class DestinationFilters : Plugin, LivePluginsDependent { +class DestinationFilters : Plugin { companion object { public const val version = "1.0.2" @@ -23,46 +28,36 @@ class DestinationFilters : Plugin, LivePluginsDependent { var dest_filters=function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=5)}([function(e,r,t){e.exports=function(e,r,t,n,o){for(r=r.split?r.split("."):r,n=0;n1?(s.pop(),c=o(t,s.join("."))):c=e,"object"==typeof c){if(i.copy){var f=o(t,i.copy);void 0!==f&&u(e,n,f)}else if(i.move){var l=o(t,i.move);void 0!==l&&u(e,n,l),a.unset(e,i.move)}else i.hasOwnProperty("set")&&u(e,n,i.set);if(i.to_string){var p=o(e,n);if("string"==typeof p||"object"==typeof p&&null!==p)continue;u(e,n,void 0!==p?JSON.stringify(p):"undefined")}}}}function l(e,r){return!(r.sample.percent<=0)&&(r.sample.percent>=1||(r.sample.path?function(e,r){var t=o(e,r.sample.path),u=n(JSON.stringify(t)),a=-64,s=[];p(u.slice(0,8),s);for(var c=0,f=0;f<64&&1!==s[f];f++)c++;if(0!==c){var l=[];p(u.slice(9,16),l),a-=c,s.splice(0,c),l.splice(64-c),s=s.concat(l)}return s[63]=0===s[63]?1:0,i(parseInt(s.join(""),2),a)=1;o/=2)n-o>=0?(n-=o,r.push(1)):r.push(0)}r.default=function(e,r){for(var t=e,n=0,o=r;n>2]|=s.charCodeAt(c)<<8*c--;for(o=s=0;o>4]+n[s]+~~a[o|15&[s,5*s+1,3*s+5,7*s][c]])<<(c=[7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21][4*c+s++%4])|i>>>-c),r,t])r=0|c[1],t=c[2];for(s=4;s;)u[--s]+=c[s]}for(e="";s<32;)e+=(u[s>>3]>>4*(1^s++)&15).toString(16);return e}},function(e,r,t){"use strict";var n=t(10),o=t(11),i=t(12),u=t(17),a=t(20),s=t(3),c=t(4);e.exports=function(e,r){var t,f,l,p;return 0===e||e!=e||e===n||e===o?e:(e=(f=i(e))[0],r+=f[1],(r+=u(e))<-1074?a(0,e):r>1023?e<0?o:n:(r<=-1023?(r+=52,p=2220446049250313e-31):p=1,t=(l=s(e))[0],t&=2148532223,p*c(t|=r+1023<<20,l[1])))}},function(e,r,t){"use strict";e.exports=Number.POSITIVE_INFINITY},function(e,r,t){"use strict";e.exports=Number.NEGATIVE_INFINITY},function(e,r,t){"use strict";var n=t(13).VALUE,o=t(15),i=t(16);e.exports=function(e){return e!=e||o(e)?[e,0]:0!==e&&i(e)>>20)-1023}},function(e,r,t){"use strict";var n;n=!0===t(1)?1:0,e.exports=n},function(e,r,t){"use strict";var n={uint16:Uint16Array,uint8:Uint8Array};e.exports=n},function(e,r,t){"use strict";var n=t(3),o=t(2),i=t(4);e.exports=function(e,r){var t,u;return t=(e=n(e))[0],t&=2147483647,u=o(r),i(t|=u&=2147483648,e[1])}},function(e,r,t){"use strict";var n,o;t(1)?(n=1,o=0):(n=0,o=1),e.exports={HIGH:n,LOW:o}},function(e,r,t){"use strict";var n,o;!0===t(1)?(n=1,o=0):(n=0,o=1),e.exports={HIGH:n,LOW:o}},function(e,r){e.exports=function(e,r,t){r.split&&(r=r.split("."));for(var n,o,i=0,u=r.length,a=e;i":case">=":return function(e,r,t,n){u(e)&&(e=o(e,n));u(r)&&(r=o(r,n));if("number"!=typeof e||"number"!=typeof r)return!1;switch(t){case"<=":return e<=r;case">=":return e>=r;case"<":return e":return e>r;default:throw new Error("Invalid operator in compareNumbers: "+t)}}(i(e[1],r),i(e[2],r),t,r);case"contains":return function(e,r){if("string"!=typeof e||"string"!=typeof r)return!1;return-1!==e.indexOf(r)}(i(e[1],r),i(e[2],r));case"match":return function(e,r){if("string"!=typeof e||"string"!=typeof r)return!1;return function(e,r){var t,n;e:for(;e.length>0;){var o,i;if(t=a(e),o=t.star,i=t.chunk,e=t.pattern,o&&""===i)return!0;var u=s(i,r),c=u.t,f=u.ok,l=u.err;if(l)return!1;if(!f||!(0===c.length||e.length>0)){if(o)for(var p=0;p0)continue;r=c;continue e}if(l)return!1}return!1}r=c}return 0===r.length}(r,e)}(i(e[1],r),i(e[2],r));case"lowercase":var c=i(e[1],r);return"string"!=typeof c?null:c.toLowerCase();case"typeof":return typeof i(e[1],r);case"length":return function(e){if(null===e)return 0;if(!Array.isArray(e)&&"string"!=typeof e)return NaN;return e.length}(i(e[1],r));default:throw new Error("FQL IR could not evaluate for token: "+t)}}function i(e,r){return Array.isArray(e)?e:"object"==typeof e?e.value:n(r,e)}function u(e){return!!Array.isArray(e)&&(("lowercase"===e[0]||"length"===e[0]||"typeof"===e[0])&&2===e.length||("contains"===e[0]||"match"===e[0])&&3===e.length)}function a(e){for(var r={star:!1,chunk:"",pattern:""};e.length>0&&"*"===e[0];)e=e.slice(1),r.star=!0;var t,n=!1;e:for(t=0;t0;){if(0===r.length)return o;switch(e[0]){case"[":var i=r[0];r=r.slice(1);var u=!0;(e=e.slice(1)).length>0&&"^"===e[0]&&(u=!1,e=e.slice(1));for(var a=!1,s=0;;){if(e.length>0&&"]"===e[0]&&s>0){e=e.slice(1);break}var f,l="";if(f=(t=c(e)).char,e=t.newChunk,t.err)return o;if(l=f,"-"===e[0]&&(l=(n=c(e.slice(1))).char,e=n.newChunk,n.err))return o;f<=i&&i<=l&&(a=!0),s++}if(a!==u)return o;break;case"?":r=r.slice(1),e=e.slice(1);break;case"\\":if(0===(e=e.slice(1)).length)return o.err=!0,o;default:if(e[0]!==r[0])return o;r=r.slice(1),e=e.slice(1)}}return o.t=r,o.ok=!0,o.err=!1,o}function c(e){var r={char:"",newChunk:"",err:!1};return 0===e.length||"-"===e[0]||"]"===e[0]||"\\"===e[0]&&0===(e=e.slice(1)).length?(r.err=!0,r):(r.char=e[0],r.newChunk=e.slice(1),0===r.newChunk.length&&(r.err=!0),r)}r.default=function(e,r){if(!r)throw new Error("No matcher supplied!");switch(r.type){case"all":return!0;case"fql":return function(e,r){if(!e)return!1;try{e=JSON.parse(e)}catch(r){throw new Error('Failed to JSON.parse FQL intermediate representation "'+e+'": '+r)}var t=o(e,r);if("boolean"!=typeof t)return!1;return t}(r.ir,e);default:throw new Error("Matcher of type "+r.type+" unsupported.")}}},function(e,r,t){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n=function(){function e(e){this.rules=[],this.rules=e||[]}return e.prototype.getRulesByDestinationName=function(e){for(var r=[],t=0,n=this.rules;t() settings.middlewareSettings["routingRules"]?.safeJsonArray?.let { rules -> for (it in rules) { @@ -70,14 +65,8 @@ class DestinationFilters : Plugin, LivePluginsDependent { val destination: String = rule["destinationName"]?.jsonPrimitive?.contentOrNull ?: "" if (destination.isNotBlank()) { - val added = engine.await(global = true) { - return@await call( - function = "createDestinationFilter", - destination, - JsonElementConverter.write(rule, context) - ) - } - if (added is JSObject) { + val added = createFilter(destination, rule) + if (added) { setOfActiveDestinations.add(destination) } } @@ -87,13 +76,51 @@ class DestinationFilters : Plugin, LivePluginsDependent { analytics.add(MetricsPlugin(setOfActiveDestinations)) } - override fun prepare(engine: JSScope) { - this.engine.sync(global = true) { - evaluate(tsubScript) - evaluate(destinationFilterEdgeFunctionTypes) + private fun removeExistingFilters() { + for (dest in analytics.findAll(DestinationPlugin::class)) { + for (filter in dest.findAll(DestinationFilter::class)) { + dest.remove(filter) + } } } - override fun readyToStart() { + private fun createFilter(destination: String, rule: JsonObject): Boolean { + analytics.find(destination)?.let { dest -> + val filter = DestinationFilter(WeakReference(engine), rule) + dest.add(filter) + return true + } + return false + } +} + +internal class DestinationFilter( + val engineRef: WeakReference, + val rule: JsonObject +): Plugin { + override lateinit var analytics: Analytics + override val type: Plugin.Type = Plugin.Type.Enrichment + + override fun execute(event: BaseEvent): BaseEvent? { + var result: BaseEvent? = event + + engineRef.get()?.let { engine -> + val payload = EncodeDefaultsJson.encodeToJsonElement(event) + result = engine.await { + val modified = call( + "evaluateRules", + JsonElementConverter.write(rule, context), + JsonElementConverter.write(payload, context) + ) + + return@await if (modified is JSObject) { + JsonElementConverter.read(modified).jsonObject.toBaseEvent() + } else { + null + } + } + } + + return result } } \ No newline at end of file