using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using MoralisUnity.Platform.Abstractions; using MoralisUnity.Platform.Objects; using MoralisUnity.Platform.Utilities; namespace MoralisUnity.Platform.Services.ClientServices { public class MoralisService : CustomServiceHub, IServiceHubComposer where TUser : MoralisUser { /// /// Contains, in order, the official ISO date and time format strings, and two modified versions that account for the possibility that the server-side string processing mechanism removed trailing zeroes. /// internal static string[] DateFormatStrings { get; } = { "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'", "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ff'Z'", "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'f'Z'", }; /// /// Gets whether or not the assembly using the Moralis SDK was compiled by IL2CPP. /// public static bool IL2CPPCompiled { get; set; } = AppDomain.CurrentDomain?.FriendlyName?.Equals("IL2CPP Root Domain") == true; /// /// The configured default instance of to use. /// public static MoralisService Instance { get; private set; } internal static string Version => typeof(MoralisService)?.Assembly?.GetCustomAttribute()?.InformationalVersion ?? typeof(MoralisService)?.Assembly?.GetName()?.Version?.ToString(); /// /// Services that provide essential functionality. /// public override IServiceHub Services { get; internal set; } /// /// Creates a new and authenticates it as belonging to your application. This class is a hub for interacting with the SDK. The recommended way to use this class on client applications is to instantiate it, then call on it in your application entry point. This allows you to access . /// /// The Application ID provided in the Moralis dashboard. /// The server URL provided in the Moralis dashboard. /// The .NET Key provided in the Moralis dashboard. /// A service hub to override internal services and thereby make the Moralis SDK operate in a custom manner. /// A set of implementation instances to tweak the behaviour of the SDK. public MoralisService(string applicationID, string serverURL, string key, IJsonSerializer jsonSerializer, IServiceHub serviceHub = default, params IServiceHubMutator[] configurators) : this(new ServerConnectionData { ApplicationID = applicationID, ServerURI = serverURL, Key = key }, jsonSerializer, serviceHub, configurators) { } /// /// Creates a new and authenticates it as belonging to your application. This class is a hub for interacting with the SDK. The recommended way to use this class on client applications is to instantiate it, then call on it in your application entry point. This allows you to access . /// /// The configuration to initialize Moralis with. /// A service hub to override internal services and thereby make the Moralis SDK operate in a custom manner. /// A set of implementation instances to tweak the behaviour of the SDK. public MoralisService(IServerConnectionData configuration, IJsonSerializer jsonSerializer, IServiceHub serviceHub = default, params IServiceHubMutator[] configurators) { Services = serviceHub is { } ? new OrchestrationServiceHub { Custom = serviceHub, Default = new ServiceHub { ServerConnectionData = GenerateServerConnectionData(), JsonSerializer = jsonSerializer } } : new ServiceHub { ServerConnectionData = GenerateServerConnectionData(), JsonSerializer = jsonSerializer } as IServiceHub; IServerConnectionData GenerateServerConnectionData() => configuration switch { null => throw new ArgumentNullException(nameof(configuration)), ServerConnectionData { Test: true, ServerURI: { } } data => data, ServerConnectionData { Test: true } data => new ServerConnectionData { ApplicationID = data.ApplicationID, Headers = data.Headers, MasterKey = data.MasterKey, Test = data.Test, Key = data.Key, ServerURI = "https://api.Moralis.com/1/" }, { ServerURI: "https://api.Moralis.com/1/" } => throw new InvalidOperationException("Since the official Moralis server has shut down, you must specify a URI that points to a hosted instance."), { ApplicationID: { }, ServerURI: { }, Key: { } } data => data, _ => throw new InvalidOperationException("The IServerConnectionData implementation instance provided to the MoralisClient constructor must be populated with the information needed to connect to a Moralis server instance.") }; // If a WS/WSS URI is not supplied create it from the server URL. if (String.IsNullOrWhiteSpace(configuration.LiveQueryServerURI)) { configuration.LiveQueryServerURI = Conversion.WebUriToWsURi(configuration.ServerURI); } if (configurators is { Length: int length } && length > 0) { Services = serviceHub switch { IMutableServiceHub { } mutableServiceHub => BuildHub((Hub: mutableServiceHub, mutableServiceHub.ServerConnectionData = serviceHub.ServerConnectionData != null ? serviceHub.ServerConnectionData : Services.ServerConnectionData).Hub, Services, configurators), { } => BuildHub(default, Services, configurators) }; } Cloud = new MoralisCloud((IServiceHub)this.Services); //Services.ClassController.AddIntrinsic(); } /// /// Initializes a instance using the set on the 's implementation instance. /// //public MoralisClient() => Services = (Instance ?? throw new InvalidOperationException("A MoralisClient instance with an initializer service must first be publicized in order for the default constructor to be used.")).Services.Cloner.BuildHub(Instance.Services, this); /// /// Sets this instance as the template to create new instances from. /// ///// Declares that the current instance should be the publicly-accesible . public void Publicize() { lock (Mutex) { Instance = this; } } public MoralisCloud Cloud { get; private set; } static object Mutex { get; } = new object { }; internal static string BuildQueryString(IDictionary parameters) => String.Join("&", (from pair in parameters let valueString = pair.Value as string select $"{Uri.EscapeDataString(pair.Key)}={Uri.EscapeDataString(String.IsNullOrEmpty(valueString) ? JsonUtilities.Encode(pair.Value) : valueString)}").ToArray()); internal static IDictionary DecodeQueryString(string queryString) { Dictionary query = new Dictionary { }; foreach (string pair in queryString.Split('&')) { string[] parts = pair.Split(new char[] { '=' }, 2); query[parts[0]] = parts.Length == 2 ? Uri.UnescapeDataString(parts[1].Replace("+", " ")) : null; } return query; } //internal static IDictionary DeserializeJsonString(string jsonData) => JsonUtilities.Parse(jsonData) as IDictionary; //internal static string SerializeJsonString(IDictionary jsonData) => JsonUtilities.Encode(jsonData); public IServiceHub BuildHub(IMutableServiceHub target = default, IServiceHub extension = default, params IServiceHubMutator[] configurators) { OrchestrationServiceHub orchestrationServiceHub = new OrchestrationServiceHub { Custom = target != null ? target : new MutableServiceHub { }, Default = extension != null ? extension : new ServiceHub { } }; foreach (IServiceHubMutator mutator in configurators.Where(configurator => configurator.Valid)) { mutator.Mutate(ref target, orchestrationServiceHub); orchestrationServiceHub.Custom = target; } return orchestrationServiceHub; } } }