public override bool TryCreate(FunctionFolderInfo functionFolderInfo, out FunctionDescriptor functionDescriptor) { functionDescriptor = null; // name might point to a single file, or a module string extension = Path.GetExtension(functionFolderInfo.Source).ToLower(); if (!(extension == ".js" || string.IsNullOrEmpty(extension))) { return false; } // parse the bindings JObject bindings = (JObject)functionFolderInfo.Configuration["bindings"]; JArray inputs = (JArray)bindings["input"]; Collection<Binding> inputBindings = Binding.GetBindings(inputs, FileAccess.Read); JArray outputs = (JArray)bindings["output"]; Collection<Binding> outputBindings = Binding.GetBindings(outputs, FileAccess.Write); JObject trigger = (JObject)inputs.FirstOrDefault(p => ((string)p["type"]).ToLowerInvariant().EndsWith("trigger")); string triggerType = (string)trigger["type"]; string triggerParameterName = (string)trigger["name"]; if (string.IsNullOrEmpty(triggerParameterName)) { // default the name to simply 'input' trigger["name"] = triggerParameterName = "input"; } NodeFunctionInvoker invoker = new NodeFunctionInvoker(triggerParameterName, functionFolderInfo.Source, inputBindings, outputBindings); ParameterDescriptor triggerParameter = null; switch (triggerType) { case "queueTrigger": triggerParameter = ParseQueueTrigger(trigger); break; case "blobTrigger": triggerParameter = ParseBlobTrigger(trigger); break; case "serviceBusTrigger": triggerParameter = ParseServiceBusTrigger(trigger); break; case "timerTrigger": triggerParameter = ParseTimerTrigger(trigger, typeof(TimerInfo)); break; case "webHookTrigger": triggerParameter = ParseWebHookTrigger(trigger); break; } Collection<ParameterDescriptor> parameters = new Collection<ParameterDescriptor>(); parameters.Add(triggerParameter); // Add a TraceWriter for logging parameters.Add(new ParameterDescriptor("log", typeof(TraceWriter))); // Add an IBinder to support the binding programming model parameters.Add(new ParameterDescriptor("binder", typeof(IBinder))); functionDescriptor = new FunctionDescriptor(functionFolderInfo.Name, invoker, parameters); return true; }
public abstract bool TryCreate(FunctionFolderInfo functionFolderInfo, out FunctionDescriptor functionDescriptor);
internal static Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable<FunctionDescriptorProvider> descriptionProviders) { string scriptRootPath = config.RootPath; List<FunctionFolderInfo> functionFolderInfos = new List<FunctionFolderInfo>(); foreach (var scriptDir in Directory.EnumerateDirectories(scriptRootPath)) { FunctionFolderInfo functionInfo = new FunctionFolderInfo(); // read the function config string functionConfigPath = Path.Combine(scriptDir, "function.json"); if (!File.Exists(functionConfigPath)) { // not a function directory continue; } string json = File.ReadAllText(functionConfigPath); functionInfo.Configuration = JObject.Parse(json); // unless the name is explicitly set in the config, // default it to the function folder name string name = (string)functionInfo.Configuration["name"]; if (string.IsNullOrEmpty(name)) { functionInfo.Name = Path.GetFileNameWithoutExtension(scriptDir); } // determine the primary script string[] functionFiles = Directory.EnumerateFiles(scriptDir).Where(p => Path.GetFileName(p).ToLowerInvariant() != "function.json").ToArray(); if (functionFiles.Length == 0) { continue; } else if (functionFiles.Length == 1) { // if there is only a single file, that file is primary functionInfo.Source = functionFiles[0]; } else { // if there is a "run" file, that file is primary string functionPrimary = null; functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileNameWithoutExtension(p).ToLowerInvariant() == "run"); if (string.IsNullOrEmpty(functionPrimary)) { // for Node, any index.js file is primary functionPrimary = functionFiles.FirstOrDefault(p => Path.GetFileName(p).ToLowerInvariant() == "index.js"); if (string.IsNullOrEmpty(functionPrimary)) { // finally, if there is an explicit primary file indicated // in config, use it JToken token = functionInfo.Configuration["source"]; if (token != null) { string sourceFileName = (string)token; functionPrimary = Path.Combine(scriptDir, sourceFileName); } } } if (string.IsNullOrEmpty(functionPrimary)) { // TODO: should this be an error? continue; } functionInfo.Source = functionPrimary; } functionFolderInfos.Add(functionInfo); } var functions = ReadFunctions(functionFolderInfos, descriptionProviders); return functions; }
private static MethodInfo GenerateMethod(JObject trigger) { FunctionFolderInfo functionFolderInfo = new FunctionFolderInfo(); functionFolderInfo.Name = "Test"; functionFolderInfo.Source = Path.Combine(Environment.CurrentDirectory, @"scripts\Common\test.js"); JArray inputs = new JArray(trigger); functionFolderInfo.Configuration = new JObject(); functionFolderInfo.Configuration["bindings"] = new JObject(); functionFolderInfo.Configuration["bindings"]["input"] = inputs; List<FunctionFolderInfo> functionFolderInfos = new List<FunctionFolderInfo>(); functionFolderInfos.Add(functionFolderInfo); FunctionDescriptorProvider[] descriptorProviders = new FunctionDescriptorProvider[] { new NodeFunctionDescriptorProvider(Environment.CurrentDirectory) }; var functionDescriptors = ScriptHost.ReadFunctions(functionFolderInfos, descriptorProviders); Type t = FunctionGenerator.Generate("TestScriptHost", "Host.Functions", functionDescriptors); MethodInfo method = t.GetMethods(BindingFlags.Public | BindingFlags.Static).First(); return method; }