diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e6ece73b8..4c0e004af5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,6 +241,8 @@ jobs: pull-requests: write env: GITHUB_TOKEN: ${{secrets.GITHUBTOKEN}} + GA_API_SECRET: ${{secrets.GA_API_SECRET}} + GA_MEASUREMENT_ID: ${{secrets.GA_MEASUREMENT_ID}} APP_VERSION: ${{ needs.draft_release.outputs.create_release_name }} steps: diff --git a/npm/package-lock.json b/npm/package-lock.json index 7835e97807..ac8923d780 100644 --- a/npm/package-lock.json +++ b/npm/package-lock.json @@ -903,9 +903,9 @@ } }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/src/core/generator/tests/snapshots/json_to_config_spec__null.json.snap b/src/core/generator/tests/snapshots/json_to_config_spec__null.json.snap index eb01d1a972..1a01bf6c9c 100644 --- a/src/core/generator/tests/snapshots/json_to_config_spec__null.json.snap +++ b/src/core/generator/tests/snapshots/json_to_config_spec__null.json.snap @@ -7,5 +7,5 @@ schema @server @upstream { } type Query { - usersAge(age: Int): Empty @http(baseURL: "https://example.com", path: "/users", query: [{key: "age", value: "{{.args.age}}"}]) + usersAge(age: Int): JSON @http(baseURL: "https://example.com", path: "/users", query: [{key: "age", value: "{{.args.age}}"}]) } diff --git a/src/core/helpers/gql_type.rs b/src/core/helpers/gql_type.rs index 46bc24b32f..8d4da11518 100644 --- a/src/core/helpers/gql_type.rs +++ b/src/core/helpers/gql_type.rs @@ -25,7 +25,11 @@ pub fn is_valid_field_name(property_name: &str) -> bool { pub fn to_gql_type(value: &Value) -> String { match value { - Value::Null => "Empty", + Value::Null => { + // treat null values as JSON scalars as we don't know the exact shape of the + // output. + "JSON" + } Value::Bool(_) => "Boolean", Value::Number(_) => "Int", Value::String(_) => "String", @@ -81,7 +85,7 @@ mod test { assert_eq!(to_gql_type(&json!(false)), "Boolean"); assert_eq!(to_gql_type(&json!([1, 2, 3])), "List"); assert_eq!(to_gql_type(&json!({"name":"test", "age": 12})), "Object"); - assert_eq!(to_gql_type(&Value::Null), "Empty"); + assert_eq!(to_gql_type(&Value::Null), "JSON"); assert_eq!(to_gql_type(&json!([])), "List"); assert_eq!(to_gql_type(&json!({})), "Object"); diff --git a/src/core/ir/discriminator.rs b/src/core/ir/discriminator.rs index ee8f08057c..127cc59414 100644 --- a/src/core/ir/discriminator.rs +++ b/src/core/ir/discriminator.rs @@ -23,7 +23,6 @@ const TYPENAME_FIELD: &str = "__typename"; impl<'json, T> TypedValue<'json> for T where T: JsonLike<'json>, - T::JsonObject<'json>: JsonObjectLike<'json, Value = T>, { type Error = anyhow::Error; diff --git a/src/core/jit/common/jp.rs b/src/core/jit/common/jp.rs index 521ecdfc8c..815d3a5311 100644 --- a/src/core/jit/common/jp.rs +++ b/src/core/jit/common/jp.rs @@ -83,14 +83,7 @@ impl<'a, Value: JsonLike<'a> + Deserialize<'a> + Clone + 'a> TestData { } } -impl< - 'a, - Value: Deserialize<'a> - + Clone - + 'a - + JsonLike<'a, JsonObject<'a>: JsonObjectLike<'a, Value = Value>>, - > JP -{ +impl<'a, Value: Deserialize<'a> + Clone + 'a + JsonLike<'a>> JP { const CONFIG: &'static str = include_str!("../fixtures/jsonplaceholder-mutation.graphql"); fn plan(query: &str, variables: &Variables) -> OperationPlan { diff --git a/src/core/jit/exec.rs b/src/core/jit/exec.rs index ee9a890bb2..f8d0da9331 100644 --- a/src/core/jit/exec.rs +++ b/src/core/jit/exec.rs @@ -25,8 +25,7 @@ pub struct Executor { impl Executor where - Output: - for<'b> JsonLike<'b, JsonObject<'b>: JsonObjectLike<'b, Value = Output>> + Debug + Clone, + Output: for<'b> JsonLike<'b> + Debug + Clone, Input: Clone + Debug, Exec: IRExecutor, { diff --git a/src/core/jit/synth/synth.rs b/src/core/jit/synth/synth.rs index 446fc8f00a..b5a9d4c7ad 100644 --- a/src/core/jit/synth/synth.rs +++ b/src/core/jit/synth/synth.rs @@ -26,7 +26,6 @@ impl Synth { impl<'a, Value> Synth where Value: JsonLike<'a> + Clone + std::fmt::Debug, - Value::JsonObject<'a>: JsonObjectLike<'a, Value = Value>, { #[inline(always)] fn include(&self, field: &Field) -> bool { diff --git a/src/core/json/borrow.rs b/src/core/json/borrow.rs index 59fd376d7c..1a38196ca8 100644 --- a/src/core/json/borrow.rs +++ b/src/core/json/borrow.rs @@ -12,7 +12,7 @@ impl<'ctx> JsonObjectLike<'ctx> for ObjectAsVec<'ctx> { ObjectAsVec::default() } - fn get_key(&'ctx self, key: &str) -> Option<&Value> { + fn get_key(&self, key: &str) -> Option<&Self::Value> { self.get(key) } @@ -22,13 +22,13 @@ impl<'ctx> JsonObjectLike<'ctx> for ObjectAsVec<'ctx> { } impl<'ctx> JsonLike<'ctx> for Value<'ctx> { - type JsonObject<'obj> = ObjectAsVec<'obj>; + type JsonObject = ObjectAsVec<'ctx>; fn null() -> Self { Value::Null } - fn object(obj: Self::JsonObject<'ctx>) -> Self { + fn object(obj: Self::JsonObject) -> Self { Value::Object(obj) } @@ -54,18 +54,18 @@ impl<'ctx> JsonLike<'ctx> for Value<'ctx> { } } - fn as_object(&self) -> Option<&Self::JsonObject<'_>> { + fn as_object(&self) -> Option<&Self::JsonObject> { self.as_object() } - fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject<'ctx>> { + fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject> { match self { Value::Object(obj) => Some(obj), _ => None, } } - fn into_object(self) -> Option> { + fn into_object(self) -> Option { match self { Value::Object(obj) => Some(obj), _ => None, diff --git a/src/core/json/graphql.rs b/src/core/json/graphql.rs index a41609a80a..aa049a8ed8 100644 --- a/src/core/json/graphql.rs +++ b/src/core/json/graphql.rs @@ -14,7 +14,7 @@ impl<'obj, Value: JsonLike<'obj> + Clone> JsonObjectLike<'obj> for IndexMap Option<&Self::Value> { + fn get_key(&self, key: &str) -> Option<&Self::Value> { self.get(key) } @@ -24,7 +24,7 @@ impl<'obj, Value: JsonLike<'obj> + Clone> JsonObjectLike<'obj> for IndexMap JsonLike<'json> for ConstValue { - type JsonObject<'obj> = IndexMap; + type JsonObject = IndexMap; fn as_array(&self) -> Option<&Vec> { match self { @@ -110,28 +110,28 @@ impl<'json> JsonLike<'json> for ConstValue { Default::default() } - fn as_object(&self) -> Option<&Self::JsonObject<'_>> { + fn as_object(&self) -> Option<&Self::JsonObject> { match self { ConstValue::Object(map) => Some(map), _ => None, } } - fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject<'_>> { + fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject> { match self { ConstValue::Object(map) => Some(map), _ => None, } } - fn into_object(self) -> Option> { + fn into_object(self) -> Option { match self { ConstValue::Object(map) => Some(map), _ => None, } } - fn object(obj: Self::JsonObject<'json>) -> Self { + fn object(obj: Self::JsonObject) -> Self { ConstValue::Object(obj) } diff --git a/src/core/json/json_like.rs b/src/core/json/json_like.rs index 2b10d39eb0..6452036e4a 100644 --- a/src/core/json/json_like.rs +++ b/src/core/json/json_like.rs @@ -6,35 +6,20 @@ impl JsonLikeOwned for T where T: for<'json> JsonLike<'json> {} /// A trait for objects that can be used as JSON values pub trait JsonLike<'json>: Sized { - type JsonObject<'obj>: JsonObjectLike< - 'obj, - // generally we want to specify `Self` instead of generic here - // and `Self` is used anyway through JsonObjectLike for - // current implementations. - // But `Self` means the very specific type with some specific lifetime - // which doesn't work in case we want to return self type but with different - // lifetime. Currently, it affects only `as_object` fn because `serde_json_borrow` - // returns smaller lifetime for Value in its `as_object` fn that either forces to - // use `&'json self` in the fn (that leads to error "variable does not live long enough") - // or generic like this. - // TODO: perhaps it could be fixed on `serde_json_borrow` side if we return `Value<'ctx>` - // instead of `Value<'_>` in its functions like `as_object`. In that case we can specify - // `Self` here and simplify usages of this trait - Value: JsonLike<'obj>, - >; + type JsonObject: JsonObjectLike<'json, Value = Self>; // Constructors fn null() -> Self; - fn object(obj: Self::JsonObject<'json>) -> Self; + fn object(obj: Self::JsonObject) -> Self; fn array(arr: Vec) -> Self; fn string(s: Cow<'json, str>) -> Self; // Operators fn as_array(&self) -> Option<&Vec>; fn into_array(self) -> Option>; - fn as_object(&self) -> Option<&Self::JsonObject<'_>>; - fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject<'json>>; - fn into_object(self) -> Option>; + fn as_object(&self) -> Option<&Self::JsonObject>; + fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject>; + fn into_object(self) -> Option; fn as_str(&self) -> Option<&str>; fn as_i64(&self) -> Option; fn as_u64(&self) -> Option; @@ -50,7 +35,7 @@ pub trait JsonLike<'json>: Sized { pub trait JsonObjectLike<'obj>: Sized { type Value; fn new() -> Self; - fn get_key(&'obj self, key: &str) -> Option<&Self::Value>; + fn get_key(&self, key: &str) -> Option<&Self::Value>; fn insert_key(&mut self, key: &'obj str, value: Self::Value); } diff --git a/src/core/json/serde.rs b/src/core/json/serde.rs index 8ee36499c8..4f6fad6609 100644 --- a/src/core/json/serde.rs +++ b/src/core/json/serde.rs @@ -10,7 +10,7 @@ impl<'obj> JsonObjectLike<'obj> for serde_json::Map { serde_json::Map::new() } - fn get_key(&'obj self, key: &str) -> Option<&serde_json::Value> { + fn get_key(&self, key: &str) -> Option<&serde_json::Value> { self.get(key) } @@ -20,7 +20,7 @@ impl<'obj> JsonObjectLike<'obj> for serde_json::Map { } impl<'json> JsonLike<'json> for serde_json::Value { - type JsonObject<'obj> = serde_json::Map; + type JsonObject = serde_json::Map; fn as_array(&self) -> Option<&Vec> { self.as_array() @@ -89,15 +89,15 @@ impl<'json> JsonLike<'json> for serde_json::Value { Self::Null } - fn as_object(&self) -> Option<&Self::JsonObject<'_>> { + fn as_object(&self) -> Option<&Self::JsonObject> { self.as_object() } - fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject<'_>> { + fn as_object_mut(&mut self) -> Option<&mut Self::JsonObject> { self.as_object_mut() } - fn into_object(self) -> Option> { + fn into_object(self) -> Option { if let Self::Object(obj) = self { Some(obj) } else { @@ -105,7 +105,7 @@ impl<'json> JsonLike<'json> for serde_json::Value { } } - fn object(obj: Self::JsonObject<'json>) -> Self { + fn object(obj: Self::JsonObject) -> Self { serde_json::Value::Object(obj) } diff --git a/src/core/scalar.rs b/src/core/scalar.rs index 1cffeffb39..44e7a4b35a 100644 --- a/src/core/scalar.rs +++ b/src/core/scalar.rs @@ -75,14 +75,14 @@ pub enum Scalar { Bytes, } -fn eval_str<'a, Value: JsonLike<'a> + 'a, F: Fn(&str) -> bool>(val: &'a Value, fxn: F) -> bool { +fn eval_str<'a, Value: JsonLike<'a>, F: Fn(&str) -> bool>(val: &'a Value, fxn: F) -> bool { val.as_str().map_or(false, fxn) } fn eval_signed< 'a, Num, - Value: JsonLike<'a> + 'a, + Value: JsonLike<'a>, F: Fn(i64) -> Result, >( val: &'a Value, @@ -94,7 +94,7 @@ fn eval_signed< fn eval_unsigned< 'a, Num, - Value: JsonLike<'a> + 'a, + Value: JsonLike<'a>, F: Fn(u64) -> Result, >( val: &'a Value, @@ -114,7 +114,7 @@ impl Scalar { } } - pub fn validate<'a, Value: JsonLike<'a> + 'a>(&self, value: &'a Value) -> bool { + pub fn validate<'a, Value: JsonLike<'a>>(&self, value: &'a Value) -> bool { match self { Scalar::JSON => true, Scalar::Empty => true, diff --git a/tailcall-cloudflare/package-lock.json b/tailcall-cloudflare/package-lock.json index c3e1278a7b..bee89f9106 100644 --- a/tailcall-cloudflare/package-lock.json +++ b/tailcall-cloudflare/package-lock.json @@ -139,9 +139,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20240821.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240821.1.tgz", - "integrity": "sha512-icAkbnAqgVl6ef9lgLTom8na+kj2RBw2ViPAQ586hbdj0xZcnrjK7P46Eu08OU9D/lNDgN2sKU/sxhe2iK/gIg==", + "version": "4.20240903.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240903.0.tgz", + "integrity": "sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==", "dev": true }, "node_modules/@cspotcode/source-map-support": { @@ -1454,9 +1454,9 @@ } }, "node_modules/miniflare": { - "version": "3.20240821.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.0.tgz", - "integrity": "sha512-4BhLGpssQxM/O6TZmJ10GkT3wBJK6emFkZ3V87/HyvQmVt8zMxEBvyw5uv6kdtp+7F54Nw6IKFJjPUL8rFVQrQ==", + "version": "3.20240821.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.1.tgz", + "integrity": "sha512-81qdiryDG7VXzZuoa0EwhkaIYYrn7+StRIrd/2i7SPqPUNICUBjbhFFKqTnvE1+fqIPPB6l8ShKFaFvmnZOASg==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "0.8.1", @@ -2203,9 +2203,9 @@ } }, "node_modules/wrangler": { - "version": "3.73.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.73.0.tgz", - "integrity": "sha512-VrdDR2OpvsCQp+r5Of3rDP1W64cNN/LHLVx1roULOlPS8PZiv7rUYgkwhdCQ61+HICAaeSxWYIzkL5+B9+8W3g==", + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.74.0.tgz", + "integrity": "sha512-wmtb+tQrgb61yN+Wa2JM98G1Gt4tKFRYPw6xwuyzUcA74L+Dum1A13w22/manl9Gq1jA3dPn+7UzT5sYEVHRog==", "dev": true, "dependencies": { "@cloudflare/kv-asset-handler": "0.3.4", @@ -2216,7 +2216,7 @@ "chokidar": "^3.5.3", "date-fns": "^3.6.0", "esbuild": "0.17.19", - "miniflare": "3.20240821.0", + "miniflare": "3.20240821.1", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", "resolve": "^1.22.8", @@ -2757,9 +2757,9 @@ "dev": true }, "@cloudflare/workers-types": { - "version": "4.20240821.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240821.1.tgz", - "integrity": "sha512-icAkbnAqgVl6ef9lgLTom8na+kj2RBw2ViPAQ586hbdj0xZcnrjK7P46Eu08OU9D/lNDgN2sKU/sxhe2iK/gIg==", + "version": "4.20240903.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20240903.0.tgz", + "integrity": "sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==", "dev": true }, "@cspotcode/source-map-support": { @@ -3588,9 +3588,9 @@ "dev": true }, "miniflare": { - "version": "3.20240821.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.0.tgz", - "integrity": "sha512-4BhLGpssQxM/O6TZmJ10GkT3wBJK6emFkZ3V87/HyvQmVt8zMxEBvyw5uv6kdtp+7F54Nw6IKFJjPUL8rFVQrQ==", + "version": "3.20240821.1", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240821.1.tgz", + "integrity": "sha512-81qdiryDG7VXzZuoa0EwhkaIYYrn7+StRIrd/2i7SPqPUNICUBjbhFFKqTnvE1+fqIPPB6l8ShKFaFvmnZOASg==", "dev": true, "requires": { "@cspotcode/source-map-support": "0.8.1", @@ -4085,9 +4085,9 @@ } }, "wrangler": { - "version": "3.73.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.73.0.tgz", - "integrity": "sha512-VrdDR2OpvsCQp+r5Of3rDP1W64cNN/LHLVx1roULOlPS8PZiv7rUYgkwhdCQ61+HICAaeSxWYIzkL5+B9+8W3g==", + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.74.0.tgz", + "integrity": "sha512-wmtb+tQrgb61yN+Wa2JM98G1Gt4tKFRYPw6xwuyzUcA74L+Dum1A13w22/manl9Gq1jA3dPn+7UzT5sYEVHRog==", "dev": true, "requires": { "@cloudflare/kv-asset-handler": "0.3.4", @@ -4099,7 +4099,7 @@ "date-fns": "^3.6.0", "esbuild": "0.17.19", "fsevents": "~2.3.2", - "miniflare": "3.20240821.0", + "miniflare": "3.20240821.1", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", "resolve": "^1.22.8", diff --git a/tailcall-tracker/src/tracker.rs b/tailcall-tracker/src/tracker.rs index 40de9a5aa7..d30ad0180f 100644 --- a/tailcall-tracker/src/tracker.rs +++ b/tailcall-tracker/src/tracker.rs @@ -4,8 +4,16 @@ use super::Result; use crate::check_tracking::check_tracking; use crate::event::Event; -const API_SECRET: &str = "GVaEzXFeRkCI9YBIylbEjQ"; -const MEASUREMENT_ID: &str = "G-JEP3QDWT0G"; +const API_SECRET: &str = match option_env!("GA_API_SECRET") { + Some(val) => val, + None => "dev", +}; + +const MEASUREMENT_ID: &str = match option_env!("GA_MEASUREMENT_ID") { + Some(val) => val, + None => "dev", +}; + const BASE_URL: &str = "https://www.google-analytics.com"; ///