├── .gitattributes ├── .gitignore ├── Abstracts ├── CustomEventAbstract.cs └── TypescriptModelClassAbstract.cs ├── App.config ├── DirectoryManager.cs ├── Extensions └── ImportsExtensions.cs ├── FuryTech.OdataTypescriptServiceGenerator.csproj ├── FuryTech.OdataTypescriptServiceGenerator.sln ├── Interfaces ├── IHasImports.cs ├── IHasUri.cs └── INamespaced.cs ├── License.md ├── Loader.cs ├── Logger.cs ├── MetadataReader.cs ├── Models ├── AngularModule.cs ├── ComplexType.cs ├── CustomAction.cs ├── CustomFunction.cs ├── EntitySet.cs ├── EntityType.cs ├── EnumMember.cs ├── EnumType.cs ├── NavigationProperty.cs └── Property.cs ├── NorthwindExample ├── AngularOdataServiceBase.ts ├── AureliaOdataServiceBase.ts ├── DpsApi.ts ├── NorthwindModel │ ├── Alphabetical_list_of_product.ts │ ├── Category.ts │ ├── Category_Sales_for_1997.ts │ ├── Current_Product_List.ts │ ├── Customer.ts │ ├── CustomerDemographic.ts │ ├── Customer_and_Suppliers_by_City.ts │ ├── Employee.ts │ ├── Invoice.ts │ ├── Order.ts │ ├── Order_Detail.ts │ ├── Order_Details_Extended.ts │ ├── Order_Subtotal.ts │ ├── Orders_Qry.ts │ ├── Product.ts │ ├── Product_Sales_for_1997.ts │ ├── Products_Above_Average_Price.ts │ ├── Products_by_Category.ts │ ├── Region.ts │ ├── Sales_Totals_by_Amount.ts │ ├── Sales_by_Category.ts │ ├── Shipper.ts │ ├── Summary_of_Sales_by_Quarter.ts │ ├── Summary_of_Sales_by_Year.ts │ ├── Supplier.ts │ └── Territory.ts ├── ODataContext.ts ├── ODataError.ts ├── ODataGetOperation.ts ├── ODataOperation.ts ├── ODataQuery.ts ├── ODataQueryResult.ts ├── ODataServiceAbstract.ts └── ODataWebExperimental │ └── Northwind │ └── Model │ ├── Alphabetical_list_of_productsODataService.ts │ ├── CategoriesODataService.ts │ ├── Category_Sales_for_1997ODataService.ts │ ├── Current_Product_ListsODataService.ts │ ├── CustomerDemographicsODataService.ts │ ├── Customer_and_Suppliers_by_CitiesODataService.ts │ ├── CustomersODataService.ts │ ├── EmployeesODataService.ts │ ├── InvoicesODataService.ts │ ├── Order_DetailsODataService.ts │ ├── Order_Details_ExtendedsODataService.ts │ ├── Order_SubtotalsODataService.ts │ ├── OrdersODataService.ts │ ├── Orders_QriesODataService.ts │ ├── Product_Sales_for_1997ODataService.ts │ ├── ProductsODataService.ts │ ├── Products_Above_Average_PricesODataService.ts │ ├── Products_by_CategoriesODataService.ts │ ├── RegionsODataService.ts │ ├── Sales_Totals_by_AmountsODataService.ts │ ├── Sales_by_CategoriesODataService.ts │ ├── ShippersODataService.ts │ ├── Summary_of_Sales_by_QuartersODataService.ts │ ├── Summary_of_Sales_by_YearsODataService.ts │ ├── SuppliersODataService.ts │ └── TerritoriesODataService.ts ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── StaticContent ├── AngularOdataServiceBase.ts ├── AureliaOdataServiceBase.ts ├── NativeOdataServiceBase.ts ├── ODataError.ts ├── ODataFilterBuilder.ts ├── ODataGetOperation.ts ├── ODataOperation.ts ├── ODataQuery.ts ├── ODataQueryResult.ts └── ODataServiceAbstract.ts ├── TemplateRenderer.cs └── Templates ├── .vscode └── symbols.json ├── AngularEntitySetService.tst ├── AngularModuleTemplate.tst ├── AureliaEntitySetService.tst ├── AureliaModuleTemplate.tst ├── ContextTemplate.tst ├── CustomActionTemplate.tst ├── CustomFunctionTemplate.tst ├── EntityTypeTemplate.tst ├── EnumMemberTemplate.tst ├── EnumTypeTemplate.tst ├── FieldTemplate.tst ├── ImportTemplate.tst ├── NativeEntitySetService.tst ├── NativeModuleTemplate.tst └── PropertyTemplate.tst /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | 263 | # Visual Studio Code symbols 264 | .vscode -------------------------------------------------------------------------------- /Abstracts/CustomEventAbstract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Xml.Linq; 6 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 7 | 8 | namespace FuryTech.OdataTypescriptServiceGenerator.Abstracts 9 | { 10 | public abstract class CustomEventAbstract : IHasImports 11 | { 12 | public CustomEventAbstract(XElement xElement) 13 | { 14 | Name = xElement.Attribute("Name")?.Value; 15 | BindingParameter = xElement.Descendants()? 16 | .SingleOrDefault(a => a.Name.LocalName == "Parameter" && a.Attribute("Name")?.Value == "bindingParameter")? 17 | .Attribute("Type")?.Value; 18 | 19 | ReturnType = xElement.Descendants().SingleOrDefault(a => a.Name.LocalName == "ReturnType")?.Attribute("Type")?.Value; 20 | 21 | if (!string.IsNullOrWhiteSpace(ReturnType) && ReturnType.StartsWith("Collection(")) 22 | { 23 | ReturnsCollection = true; 24 | ReturnType = ReturnType.TrimStart("Collection(".ToCharArray()).TrimEnd(')'); 25 | } 26 | 27 | if (!string.IsNullOrWhiteSpace(BindingParameter) && BindingParameter.StartsWith("Collection(")) 28 | { 29 | IsCollectionAction = true; 30 | BindingParameter = BindingParameter.TrimStart("Collection(".ToCharArray()).TrimEnd(')'); 31 | } 32 | 33 | NameSpace = 34 | xElement.Ancestors().First(a => a.Attribute("Namespace") != null)?.Attribute("Namespace")?.Value; 35 | } 36 | public string Name { get; } 37 | public string NameSpace { get; } 38 | 39 | public string ReturnType { get; } 40 | public string BindingParameter { get; } 41 | 42 | public bool IsCollectionAction { get; } 43 | public bool ReturnsCollection { get; } 44 | 45 | private Uri _uri; 46 | public Uri Uri => _uri ?? (_uri = new Uri("r://" + NameSpace.Replace(".", Path.DirectorySeparatorChar.ToString()) + Path.DirectorySeparatorChar + Name, UriKind.Absolute)); 47 | 48 | public IEnumerable Imports 49 | { 50 | get 51 | { 52 | var uriList = new List(); 53 | if (!string.IsNullOrWhiteSpace(ReturnType)) 54 | { 55 | uriList.Add(new Uri("r://" + ReturnType.Replace(".", Path.DirectorySeparatorChar.ToString()))); 56 | } 57 | if (!string.IsNullOrWhiteSpace(BindingParameter)) 58 | { 59 | uriList.Add(new Uri("r://" + BindingParameter.Replace(".", Path.DirectorySeparatorChar.ToString()))); 60 | } 61 | return uriList; 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Abstracts/TypescriptModelClassAbstract.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Xml.Linq; 5 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 6 | using FuryTech.OdataTypescriptServiceGenerator.Models; 7 | 8 | namespace FuryTech.OdataTypescriptServiceGenerator.Abstracts 9 | { 10 | public abstract class TypescriptModelClassAbstract : IHasImports 11 | { 12 | public TypescriptModelClassAbstract(XElement sourceElement) 13 | { 14 | Name = sourceElement.Attribute("Name")?.Value; 15 | KeyName = 16 | sourceElement.Descendants() 17 | .Where(a => a.Name.LocalName == "Key") 18 | .Descendants() 19 | .FirstOrDefault()? //ToDo: Composite keys 20 | .Attribute("Name")? 21 | .Value; 22 | NameSpace = sourceElement.Parent?.Attribute("Namespace")?.Value; 23 | 24 | Properties = sourceElement.Descendants().Where(a => a.Name.LocalName == "Property") 25 | .Select(propElement => new Property() 26 | { 27 | Name = propElement.Attribute("Name")?.Value, 28 | IsRequired = propElement.Attribute("Nullable")?.Value == "true", 29 | Type = propElement.Attribute("Type")?.Value 30 | }).ToList(); 31 | 32 | NavigationProperties = sourceElement.Descendants().Where(a => a.Name.LocalName == "NavigationProperty") 33 | .Select(prop => new NavigationProperty() 34 | { 35 | FullName = prop.Attribute("Name")?.Value, 36 | IsCollection = prop.Attribute("Type")?.Value.StartsWith("Collection(") ?? false, 37 | Type = prop.Attribute("Type")?.Value.TrimStart("Collection(".ToCharArray()).TrimEnd(')'), 38 | ReferentialConstraint = prop.Descendants().SingleOrDefault(a => a.Name.LocalName == "ReferentialConstraint")?.Attribute("Property")?.Value, 39 | ReferencedProperty = prop.Descendants().SingleOrDefault(a => a.Name.LocalName == "ReferentialConstraint")?.Attribute("ReferencedProperty")?.Value 40 | }).ToList(); 41 | } 42 | 43 | public string NameSpace { get; private set; } 44 | public string Name { get; private set; } 45 | public string KeyName { get; set; } 46 | public List Properties { get; private set; } 47 | public List NavigationProperties { get; set; } 48 | 49 | public IEnumerable Imports 50 | { 51 | get 52 | { 53 | var namespaces = NavigationProperties.Select(a => a.Type).Where(a => a != NameSpace + "." + Name).ToList(); 54 | /*For Not-EDM types (e.g. enums with namespaces, complex types*/ 55 | namespaces.AddRange(Properties.Where(a => !a.Type.StartsWith("Edm.")).Select(a => a.Type)); 56 | 57 | var uris = namespaces.Distinct().Select(a => new Uri("r://" + a.Replace(".", "/"), UriKind.Absolute)); 58 | return uris; 59 | } 60 | } 61 | 62 | private Uri _uri; 63 | public Uri Uri => _uri ?? (_uri = new Uri("r://" + NameSpace.Replace(".", "/") + "/" + Name, UriKind.Absolute)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /DirectoryManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 6 | 7 | namespace FuryTech.OdataTypescriptServiceGenerator 8 | { 9 | public class DirectoryManager 10 | { 11 | private readonly string _outFolder; 12 | private readonly DirectoryInfo _di; 13 | 14 | public void PrepareOutput(bool purgeOutput) 15 | { 16 | Logger.Log($"Preparing output path '{_outFolder}'..."); 17 | if (!Directory.Exists(_outFolder)) 18 | { 19 | Logger.Log("Folder doesn't exists, creating..."); 20 | Directory.CreateDirectory(_outFolder); 21 | } 22 | else 23 | { 24 | var files = _di.GetFiles(); 25 | var dirs = _di.GetDirectories(); 26 | if (files.Any() || dirs.Any()) 27 | { 28 | if (purgeOutput) 29 | { 30 | Logger.Log("Purging output directory..."); 31 | 32 | foreach (var directoryInfo in dirs) 33 | { 34 | Logger.Log($"Removing directory '{directoryInfo.Name}'"); 35 | directoryInfo.Delete(true); 36 | } 37 | 38 | foreach (var fileInfo in files) 39 | { 40 | Logger.Log($"Removing file '{fileInfo.Name}'"); 41 | fileInfo.Delete(); 42 | } 43 | } 44 | else 45 | { 46 | throw new InvalidOperationException("The output folder is not empty and output purging is disabled. Please enable purging or delete your output folder manually."); 47 | } 48 | } 49 | } 50 | } 51 | 52 | public void PrepareNamespaceFolders(IEnumerable namespaces) 53 | { 54 | var nsList = namespaces.ToList().OrderBy(a => a.NameSpace); 55 | foreach (var ns in nsList) 56 | { 57 | var path = ns.NameSpace.Replace('.', Path.DirectorySeparatorChar); 58 | if (!Directory.Exists( Path.Combine(_di.FullName, path))) 59 | { 60 | Logger.Log($"Creating subdirectory '{path}'"); 61 | _di.CreateSubdirectory(path); 62 | } 63 | } 64 | } 65 | 66 | public DirectoryManager(string outFolder) 67 | { 68 | _outFolder = outFolder; 69 | _di = new DirectoryInfo(_outFolder); 70 | } 71 | 72 | public void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs) 73 | { 74 | // Get the subdirectories for the specified directory. 75 | DirectoryInfo dir = new DirectoryInfo(sourceDirName); 76 | 77 | if (!dir.Exists) 78 | { 79 | throw new DirectoryNotFoundException( 80 | "Source directory does not exist or could not be found: " 81 | + sourceDirName); 82 | } 83 | 84 | DirectoryInfo[] dirs = dir.GetDirectories(); 85 | // If the destination directory doesn't exist, create it. 86 | if (!Directory.Exists(destDirName)) 87 | { 88 | Directory.CreateDirectory(destDirName); 89 | } 90 | 91 | // Get the files in the directory and copy them to the new location. 92 | FileInfo[] files = dir.GetFiles(); 93 | foreach (FileInfo file in files) 94 | { 95 | string temppath = Path.Combine(destDirName, file.Name); 96 | file.CopyTo(temppath, false); 97 | } 98 | 99 | // If copying subdirectories, copy them and their contents to new location. 100 | if (copySubDirs) 101 | { 102 | foreach (DirectoryInfo subdir in dirs) 103 | { 104 | string temppath = Path.Combine(destDirName, subdir.Name); 105 | DirectoryCopy(subdir.FullName, temppath, copySubDirs); 106 | } 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Extensions/ImportsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 5 | 6 | namespace FuryTech.OdataTypescriptServiceGenerator.Extensions 7 | { 8 | 9 | public class ImportRecord 10 | { 11 | public string ElementTypeName { get; set; } 12 | public Uri RelativeNamespace { get; set; } 13 | } 14 | 15 | public static class ImportsExtensions 16 | { 17 | public static IEnumerable GetImportRecords(this IHasImports element) 18 | { 19 | var records = element.Imports.Where(a=>a != element.Uri).Select(a => new ImportRecord 20 | { 21 | RelativeNamespace = element.Uri.MakeRelativeUri(a), 22 | ElementTypeName = a.Segments.Last() 23 | }); 24 | return records; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FuryTech.OdataTypescriptServiceGenerator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2C2EC957-F5BD-4D39-8F85-DAAEAB812132} 8 | Exe 9 | FuryTech.OdataTypescriptServiceGenerator 10 | FuryTech.OdataTypescriptServiceGenerator 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | PreserveNewest 71 | 72 | 73 | PreserveNewest 74 | 75 | 76 | PreserveNewest 77 | 78 | 79 | 80 | 81 | 82 | PreserveNewest 83 | 84 | 85 | PreserveNewest 86 | 87 | 88 | PreserveNewest 89 | 90 | 91 | PreserveNewest 92 | 93 | 94 | PreserveNewest 95 | 96 | 97 | PreserveNewest 98 | 99 | 100 | PreserveNewest 101 | 102 | 103 | 104 | 105 | PreserveNewest 106 | 107 | 108 | PreserveNewest 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | PreserveNewest 117 | 118 | 119 | PreserveNewest 120 | 121 | 122 | PreserveNewest 123 | 124 | 125 | PreserveNewest 126 | 127 | 128 | PreserveNewest 129 | 130 | 131 | PreserveNewest 132 | 133 | 134 | PreserveNewest 135 | 136 | 137 | PreserveNewest 138 | 139 | 140 | PreserveNewest 141 | 142 | 143 | PreserveNewest 144 | 145 | 146 | PreserveNewest 147 | 148 | 149 | 150 | 151 | PreserveNewest 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /FuryTech.OdataTypescriptServiceGenerator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26009.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuryTech.OdataTypescriptServiceGenerator", "FuryTech.OdataTypescriptServiceGenerator.csproj", "{2C2EC957-F5BD-4D39-8F85-DAAEAB812132}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2C2EC957-F5BD-4D39-8F85-DAAEAB812132}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {2C2EC957-F5BD-4D39-8F85-DAAEAB812132}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {2C2EC957-F5BD-4D39-8F85-DAAEAB812132}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {2C2EC957-F5BD-4D39-8F85-DAAEAB812132}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Interfaces/IHasImports.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FuryTech.OdataTypescriptServiceGenerator.Interfaces 5 | { 6 | public interface IHasImports : IHasUri 7 | { 8 | IEnumerable Imports { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Interfaces/IHasUri.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FuryTech.OdataTypescriptServiceGenerator.Interfaces 4 | { 5 | public interface IHasUri : IRenderableElement 6 | { 7 | Uri Uri { get; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Interfaces/INamespaced.cs: -------------------------------------------------------------------------------- 1 | namespace FuryTech.OdataTypescriptServiceGenerator.Interfaces 2 | { 3 | public interface IRenderableElement 4 | { 5 | string Name { get; } 6 | string NameSpace { get; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Gallay Lajos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Loader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Xml.Linq; 4 | 5 | namespace FuryTech.OdataTypescriptServiceGenerator 6 | { 7 | public class Loader 8 | { 9 | public static XDocument Load(string source) 10 | { 11 | Logger.Log("Loading Metadata..."); 12 | XDocument xml; 13 | 14 | try 15 | { 16 | xml = XDocument.Load(source); 17 | return xml; 18 | } 19 | catch (WebException wex) 20 | { 21 | if (wex.Message == "The remote server returned an error: (401) Unauthorized.") 22 | { 23 | Logger.Warning("Authorization error, trying NTLM..."); 24 | var req = WebRequest.Create(source); 25 | req.Credentials = CredentialCache.DefaultCredentials; 26 | var stream = req.GetResponse().GetResponseStream(); 27 | if (stream != null) 28 | { 29 | xml = XDocument.Load(stream); 30 | return xml; 31 | } 32 | } 33 | Logger.Error("Failed to read metadata."); 34 | throw; 35 | } 36 | catch (Exception) 37 | { 38 | Logger.Error("Error reading metadata."); 39 | throw; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FuryTech.OdataTypescriptServiceGenerator 4 | { 5 | public class Logger 6 | { 7 | public static void Log(string logEntry) 8 | { 9 | Console.ForegroundColor = ConsoleColor.White; 10 | Console.WriteLine($"{DateTime.Now} - {logEntry}"); 11 | } 12 | 13 | public static void Error(string logEntry) 14 | { 15 | Console.ForegroundColor = ConsoleColor.Red; 16 | Console.WriteLine($"{DateTime.Now} - {logEntry}"); 17 | } 18 | 19 | public static void Warning(string logEntry) 20 | { 21 | Console.ForegroundColor = ConsoleColor.Yellow; 22 | Console.WriteLine($"{DateTime.Now} - {logEntry}"); 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MetadataReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using FuryTech.OdataTypescriptServiceGenerator.Models; 5 | 6 | namespace FuryTech.OdataTypescriptServiceGenerator 7 | { 8 | public class MetadataReader 9 | { 10 | public List EntityTypes { get; private set; } 11 | public List ComplexTypes { get; private set; } 12 | 13 | public List EnumTypes { get; private set; } 14 | public List EntitySets { get; private set; } 15 | public List CustomActions { get; private set; } 16 | public List CustomFunctions { get; private set; } 17 | 18 | 19 | private void ReadEntityTypes(XDocument xdoc) 20 | { 21 | Logger.Log("Parsing entity types..."); 22 | var typeList = new List(); 23 | var elements = xdoc.Descendants().Where(a => a.Name.LocalName == "EntityType"); 24 | 25 | foreach (var xElement in elements) 26 | { 27 | var enT = new EntityType(xElement); 28 | typeList.Add(enT); 29 | Logger.Log($"Entity Type '{enT.NameSpace}.{enT.Name}' parsed"); 30 | } 31 | EntityTypes = typeList; 32 | } 33 | 34 | private void ReadComplexTypes(XDocument xdoc) 35 | { 36 | Logger.Log("Parsing entity types..."); 37 | var typeList = new List(); 38 | var elements = xdoc.Descendants().Where(a => a.Name.LocalName == "ComplexType"); 39 | 40 | foreach (var xElement in elements) 41 | { 42 | var enT = new ComplexType(xElement); 43 | typeList.Add(enT); 44 | Logger.Log($"Entity Type '{enT.NameSpace}.{enT.Name}' parsed"); 45 | } 46 | ComplexTypes = typeList; 47 | } 48 | 49 | private void ReadEnums(XDocument xdoc) 50 | { 51 | Logger.Log("Parsing enums..."); 52 | var enumList = new List(); 53 | var elements = xdoc.Descendants().Where(a => a.Name.LocalName == "EnumType"); 54 | 55 | foreach (var xElement in elements) 56 | { 57 | var enT = new EnumType(xElement); 58 | enumList.Add(enT); 59 | Logger.Log($"Enum Type '{enT.NameSpace}.{enT.Name}' parsed"); 60 | } 61 | EnumTypes = enumList; 62 | 63 | } 64 | 65 | private void ReadEntitySets(XDocument xdoc, List actions, List functions) 66 | { 67 | Logger.Log("Parsing entity sets..."); 68 | var entitySetList = new List(); 69 | var elements = xdoc.Descendants().Where(a => a.Name.LocalName == "EntitySet"); 70 | 71 | foreach (var xElement in elements) 72 | { 73 | var tContainer = new EntitySet(xElement, actions, functions); 74 | entitySetList.Add(tContainer); 75 | Logger.Log($"Entity set '{tContainer.Name}' parsed"); 76 | } 77 | 78 | EntitySets = entitySetList; 79 | } 80 | 81 | private void ReadCustomActions(XDocument xDoc) 82 | { 83 | Logger.Log("Parsing custom actions..."); 84 | List customActionList = new List(); 85 | var elements = xDoc.Descendants().Where(a => a.Name.LocalName == "Action"); 86 | foreach (var xElement in elements) 87 | { 88 | var tCustomAction = new CustomAction(xElement); 89 | customActionList.Add(tCustomAction); 90 | Logger.Log($"Custom Action '{tCustomAction.Name}' parsed"); 91 | } 92 | CustomActions = customActionList; 93 | } 94 | 95 | private void ReadCustomFunctions(XDocument xDoc) 96 | { 97 | Logger.Log("Parsing custom functions..."); 98 | List customFunctionList = new List(); 99 | var elements = xDoc.Descendants().Where(a => a.Name.LocalName == "Function"); 100 | foreach (var xElement in elements) 101 | { 102 | var tCustomAction = new CustomFunction(xElement); 103 | customFunctionList.Add(tCustomAction); 104 | Logger.Log($"Custom Action '{tCustomAction.Name}' parsed"); 105 | } 106 | CustomFunctions = customFunctionList; 107 | } 108 | 109 | 110 | public MetadataReader(XDocument xdoc) 111 | { 112 | ReadEntityTypes(xdoc); 113 | ReadComplexTypes(xdoc); 114 | ReadEnums(xdoc); 115 | 116 | ReadCustomActions(xdoc); 117 | ReadCustomFunctions(xdoc); 118 | 119 | ReadEntitySets(xdoc, CustomActions, CustomFunctions); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /Models/AngularModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 5 | 6 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 7 | { 8 | public class AngularModule : IHasImports 9 | { 10 | public AngularModule(string endpointName, IEnumerable entitySets) 11 | { 12 | EntitySets = entitySets; 13 | Name = endpointName; 14 | NameSpace = string.Empty; 15 | } 16 | 17 | public string Name { get; } 18 | public string NameSpace { get; } 19 | 20 | private Uri _uri; 21 | public readonly IEnumerable EntitySets; 22 | 23 | public Uri Uri => _uri ?? (_uri = new Uri("r://" + Name, UriKind.Absolute)); 24 | 25 | public IEnumerable Imports 26 | { 27 | get 28 | { 29 | return EntitySets.Select(a => a.Uri); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Models/ComplexType.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using FuryTech.OdataTypescriptServiceGenerator.Abstracts; 3 | 4 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 5 | { 6 | public class ComplexType : TypescriptModelClassAbstract 7 | { 8 | public ComplexType(XElement sourceElement) : base(sourceElement) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Models/CustomAction.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using FuryTech.OdataTypescriptServiceGenerator.Abstracts; 3 | 4 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 5 | { 6 | public class CustomAction : CustomEventAbstract 7 | { 8 | public CustomAction(XElement xElement) : base(xElement) 9 | { 10 | 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Models/CustomFunction.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using FuryTech.OdataTypescriptServiceGenerator.Abstracts; 3 | 4 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 5 | { 6 | public class CustomFunction : CustomEventAbstract 7 | { 8 | public CustomFunction(XElement xElement) : base(xElement) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Models/EntitySet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Xml.Linq; 6 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 7 | 8 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 9 | { 10 | public class EntitySet : IHasImports 11 | { 12 | public EntitySet(XElement xElement, IEnumerable customActions, IEnumerable functions) 13 | { 14 | EntitySetName = xElement.Attribute("Name")?.Value; 15 | Name = char.ToUpper(EntitySetName[0]) + EntitySetName.Substring(1) + "ODataService"; 16 | EntityType = xElement.Attribute("EntityType")?.Value; 17 | NameSpace = 18 | xElement.Ancestors().FirstOrDefault(a => a.Attribute("Namespace") != null)?.Attribute("Namespace").Value; 19 | CustomActions = customActions.Where(a=>a.BindingParameter == EntityType); 20 | CustomFunctions = functions.Where(a => a.BindingParameter == EntityType); 21 | } 22 | 23 | public string Name { get; private set; } 24 | public string NameSpace { get; private set; } 25 | public string EntityType { get; private set; } 26 | public string EntitySetName { get; private set; } 27 | 28 | private Uri _uri; 29 | public Uri Uri => _uri ?? (_uri = new Uri("r://" + NameSpace.Replace(".", Path.DirectorySeparatorChar.ToString()) + Path.DirectorySeparatorChar + Name, UriKind.Absolute)); 30 | 31 | public IEnumerable Imports 32 | { 33 | get 34 | { 35 | var list = new List 36 | { 37 | new Uri("r://" + EntityType.Replace(".", Path.DirectorySeparatorChar.ToString()), UriKind.Absolute), 38 | new Uri("r://ODataContext", UriKind.Absolute) 39 | }; 40 | list.AddRange(CustomActions.SelectMany(a=>a.Imports)); 41 | list.AddRange(CustomFunctions.SelectMany(a => a.Imports)); 42 | return list.Distinct(); 43 | } 44 | } 45 | 46 | public IEnumerable CustomActions { get; set; } 47 | public IEnumerable CustomFunctions { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Models/EntityType.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using FuryTech.OdataTypescriptServiceGenerator.Abstracts; 3 | 4 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 5 | { 6 | public class EntityType : TypescriptModelClassAbstract{ 7 | public EntityType(XElement sourceElement) : base(sourceElement) 8 | { 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Models/EnumMember.cs: -------------------------------------------------------------------------------- 1 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 2 | { 3 | public class EnumMember 4 | { 5 | public string Name { get; set; } 6 | public string Value { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Models/EnumType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Xml.Linq; 4 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 5 | 6 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 7 | { 8 | public class EnumType : IRenderableElement 9 | { 10 | 11 | public string Name { get; private set; } 12 | 13 | public string NameSpace { get; private set; } 14 | public IEnumerable Members { get; private set; } 15 | 16 | public EnumType(XElement sourceElement) 17 | { 18 | Name = sourceElement.Attribute("Name")?.Value; 19 | NameSpace = sourceElement.Parent?.Attribute("Namespace")?.Value; 20 | Members = sourceElement.Descendants().Where(a => a.Name.LocalName == "Member") 21 | .Select(propElement => new EnumMember() 22 | { 23 | Name = propElement.Attribute("Name")?.Value, 24 | Value = propElement.Attribute("Value")?.Value 25 | }).ToList(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Models/NavigationProperty.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 4 | { 5 | public class NavigationProperty 6 | { 7 | public string Name => FullName.Split('.').Last(); 8 | public string FullName { get; set; } 9 | public string ReferentialConstraint { get; set; } 10 | public string ReferencedProperty { get; set; } 11 | public string Type { get; set; } 12 | public bool IsCollection { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Models/Property.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace FuryTech.OdataTypescriptServiceGenerator.Models 4 | { 5 | public class Property 6 | { 7 | public string Name { get; set; } 8 | public string Type { get; set; } 9 | 10 | public string TypescriptType 11 | { 12 | get 13 | { 14 | switch (Type) 15 | { 16 | case "Edm.String": 17 | case "Edm.Duration": 18 | case "Edm.Guid": 19 | case "Edm.Binary": 20 | return "string"; 21 | case "Edm.Int16": 22 | case "Edm.Int32": 23 | case "Edm.Int64": 24 | case "Edm.Double": 25 | case "Edm.Decimal": 26 | case "Edm.Byte": 27 | return "number"; 28 | case "Edm.Boolean": 29 | return "boolean"; 30 | case "Edm.DateTimeOffset": 31 | return "Date"; 32 | default: 33 | { 34 | return Type.Contains(".") ? Type.Split('.').Last(a => !string.IsNullOrWhiteSpace(a)) : "any"; 35 | } 36 | } 37 | } 38 | } 39 | 40 | public bool IsRequired { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /NorthwindExample/AngularOdataServiceBase.ts: -------------------------------------------------------------------------------- 1 | import { RequestOptionsArgs } from '@angular/http/src/interfaces'; 2 | import * as https from 'https'; 3 | import { Injectable } from '@angular/core'; 4 | import { Http, RequestOptions, Response } from '@angular/http'; 5 | import 'rxjs/add/operator/toPromise'; 6 | 7 | import { ODataGetOperation } from './ODataGetOperation'; 8 | import { ODataServiceAbstract } from './ODataServiceAbstract'; 9 | import { ODataQuery } from './ODataQuery'; 10 | import { ODataQueryResult } from './ODataQueryResult'; 11 | import { ODataContext } from './ODataContext'; 12 | import { ODataError } from './ODataError'; 13 | 14 | // created by FuryTech.ODataTypeScriptGenerator 15 | 16 | export abstract class AngularODataServiceBase extends ODataServiceAbstract { 17 | 18 | private requestOptions: RequestOptionsArgs = { 19 | withCredentials: true 20 | }; 21 | 22 | protected abstract entitySetUrlSegment: string; 23 | 24 | protected get entitySetUrl(): string { 25 | return ODataContext.ODataRootPath + this.entitySetUrlSegment; 26 | } 27 | 28 | protected abstract http: Http; 29 | constructor() { 30 | super(); 31 | } 32 | 33 | public Get(id: any): ODataGetOperation { 34 | let idSegment = this.getEntityUriSegment(id); 35 | return new ODataGetOperation(idSegment, async (queryString: string) => { 36 | return this.http.get(this.entitySetUrl + idSegment + queryString, { 37 | withCredentials: true, 38 | }).map(a => { 39 | return a.json() as T; 40 | }).toPromise(); 41 | }); 42 | }; 43 | 44 | private extractResponse(res: Response) { 45 | if (res.status < 200 || res.status >= 300) { 46 | throw new ODataError(res.status, res.json()); 47 | } 48 | let body: any = res.json(); 49 | let entity: T = body; 50 | return entity || null; 51 | } 52 | 53 | public async Post(entity: T): Promise { 54 | return this.http.post(this.entitySetUrl, entity, this.requestOptions) 55 | .map(this.extractResponse) 56 | .toPromise(); 57 | } 58 | 59 | public async Patch(id: any, entity: T): Promise { 60 | return this.http 61 | .patch(this.entitySetUrl + this.getEntityUriSegment(id), entity, this.requestOptions) 62 | .toPromise(); 63 | } 64 | 65 | public async Put(id: any, entity: T): Promise { 66 | return this.http 67 | .put(this.entitySetUrl + this.getEntityUriSegment(id), entity, this.requestOptions) 68 | .map(this.extractResponse) 69 | .toPromise(); 70 | } 71 | 72 | public async Delete(id: any): Promise { 73 | return this.http 74 | .delete(this.entitySetUrl + this.getEntityUriSegment(id), this.requestOptions) 75 | .toPromise(); 76 | } 77 | 78 | protected async ExecCustomAction(actionName: string, entity: T, ...args: any[]): Promise { 79 | return this.http 80 | .post(this.entitySetUrl + this.getEntityUriSegment(entity) + `/${actionName}`, null, this.requestOptions) 81 | .map(a => {return a.json(); } ) 82 | .toPromise(); 83 | } 84 | 85 | protected async ExecCustomCollectionAction(actionName: string, ...args: any[]): Promise { 86 | return this.http 87 | .post(this.entitySetUrl + actionName, null, this.requestOptions) 88 | .map(a => {return a.json(); } ) 89 | .toPromise(); 90 | } 91 | 92 | protected async ExecCustomFunction(fucntionName: string, entity: T, ...args: any[]): Promise { 93 | return this.http 94 | .get(this.entitySetUrl + this.getEntityUriSegment(entity) + `/${fucntionName}`, this.requestOptions) 95 | .map(a => {return a.json(); } ) 96 | .toPromise(); 97 | } 98 | 99 | protected async ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise { 100 | return this.http 101 | .get(this.entitySetUrl + fucntionName, this.requestOptions) 102 | .map(a => {return a.json(); } ) 103 | .toPromise(); 104 | 105 | } 106 | 107 | 108 | Query(): ODataQuery { 109 | 110 | let http = this.http; 111 | let entitySetUrl = this.entitySetUrl; 112 | 113 | let evaluateQuery = (queryString: string): Promise> => { 114 | let url = this.entitySetUrl + queryString; 115 | let subscription = http.get(url, { 116 | withCredentials: true 117 | }).map(a => { 118 | return a.json() as ODataQueryResult; 119 | }); 120 | 121 | return subscription.toPromise(); 122 | }; 123 | 124 | return new ODataQuery(evaluateQuery); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /NorthwindExample/AureliaOdataServiceBase.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpResponseMessage } from 'aurelia-http-client'; 2 | 3 | import { ODataServiceAbstract } from './ODataServiceAbstract'; 4 | import { ODataContext } from './ODataContext'; 5 | import { ODataGetOperation } from './ODataGetOperation'; 6 | import { ODataError } from './ODataError'; 7 | import { ODataQuery } from './ODataQuery'; 8 | import { ODataQueryResult } from './ODataQueryResult'; 9 | 10 | export abstract class AureliaOdataServiceBase extends ODataServiceAbstract{ 11 | 12 | private http: HttpClient; 13 | 14 | protected get entitySetUrl(): string { 15 | return ODataContext.ODataRootPath + this.entitySetUrlSegment; 16 | } 17 | 18 | protected getUriForEntity(id: any): string { 19 | return this.entitySetUrl + this.getEntityUriSegment(id) 20 | } 21 | 22 | constructor(protected entitySetUrlSegment: string) { 23 | super(); 24 | this.http = new HttpClient().configure(c => { 25 | c.withBaseUrl(this.entitySetUrl), 26 | c.withCredentials(true) 27 | }); 28 | } 29 | 30 | public Get(id: any): ODataGetOperation { 31 | let entityUri = this.getUriForEntity(id); 32 | return new ODataGetOperation(entityUri, async (queryString: string) => { 33 | var result = await this.http.get(entityUri + queryString); 34 | return result.content; 35 | }); 36 | }; 37 | 38 | private extractResponse(res: HttpResponseMessage) { 39 | if (res.statusCode < 200 || res.statusCode >= 300) { 40 | throw new ODataError(res.statusCode, res.content); 41 | } 42 | let entity: T = res.content; 43 | return entity || null; 44 | } 45 | 46 | public async Post(entity: T): Promise { 47 | var result = await this.http.post(this.entitySetUrl, entity); 48 | return result.content; 49 | } 50 | 51 | public async Patch(id: any, entity: T): Promise { 52 | var result = await this.http.patch(this.getUriForEntity(id), entity); 53 | return result.content; 54 | } 55 | 56 | public async Put(id: any, entity: T): Promise { 57 | var result = await this.http.put(this.getUriForEntity(id), entity); 58 | return result.content; 59 | } 60 | 61 | public async Delete(id: any): Promise { 62 | var result = await this.http.delete(this.getUriForEntity(id)); 63 | return result.content; 64 | } 65 | 66 | protected async ExecCustomAction(actionName: string, entityId: any, ...args: any[]): Promise { 67 | var result = await this.http.post(this.getUriForEntity(entityId) + `/${actionName}`, null); 68 | return result.content; 69 | } 70 | 71 | protected async ExecCustomCollectionAction(actionName: string, ...args: any[]): Promise { 72 | var result = await this.http.post(actionName, null); 73 | return result.content; 74 | } 75 | 76 | protected async ExecCustomFunction(fucntionName: string, entityId: any, ...args: any[]): Promise { 77 | let result = await this.http.get(this.getUriForEntity(entityId) + `/${fucntionName}`); 78 | return result.content; 79 | } 80 | 81 | protected async ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise { 82 | let result = await this.http.get(fucntionName); 83 | return result.content; 84 | } 85 | 86 | 87 | Query(): ODataQuery { 88 | 89 | let http = this.http; 90 | let entitySetUrl = this.entitySetUrl; 91 | 92 | let evaluateQuery = async (queryString: string): Promise> => { 93 | let url = this.entitySetUrl + "/" + queryString; 94 | let response = await http.get(url); 95 | return response.content; 96 | }; 97 | 98 | return new ODataQuery(evaluateQuery); 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /NorthwindExample/DpsApi.ts: -------------------------------------------------------------------------------- 1 | import { CategoriesODataService } from './ODataWebExperimental/Northwind/Model/CategoriesODataService'; 2 | import { CustomerDemographicsODataService } from './ODataWebExperimental/Northwind/Model/CustomerDemographicsODataService'; 3 | import { CustomersODataService } from './ODataWebExperimental/Northwind/Model/CustomersODataService'; 4 | import { EmployeesODataService } from './ODataWebExperimental/Northwind/Model/EmployeesODataService'; 5 | import { Order_DetailsODataService } from './ODataWebExperimental/Northwind/Model/Order_DetailsODataService'; 6 | import { OrdersODataService } from './ODataWebExperimental/Northwind/Model/OrdersODataService'; 7 | import { ProductsODataService } from './ODataWebExperimental/Northwind/Model/ProductsODataService'; 8 | import { RegionsODataService } from './ODataWebExperimental/Northwind/Model/RegionsODataService'; 9 | import { ShippersODataService } from './ODataWebExperimental/Northwind/Model/ShippersODataService'; 10 | import { SuppliersODataService } from './ODataWebExperimental/Northwind/Model/SuppliersODataService'; 11 | import { TerritoriesODataService } from './ODataWebExperimental/Northwind/Model/TerritoriesODataService'; 12 | import { Alphabetical_list_of_productsODataService } from './ODataWebExperimental/Northwind/Model/Alphabetical_list_of_productsODataService'; 13 | import { Category_Sales_for_1997ODataService } from './ODataWebExperimental/Northwind/Model/Category_Sales_for_1997ODataService'; 14 | import { Current_Product_ListsODataService } from './ODataWebExperimental/Northwind/Model/Current_Product_ListsODataService'; 15 | import { Customer_and_Suppliers_by_CitiesODataService } from './ODataWebExperimental/Northwind/Model/Customer_and_Suppliers_by_CitiesODataService'; 16 | import { InvoicesODataService } from './ODataWebExperimental/Northwind/Model/InvoicesODataService'; 17 | import { Order_Details_ExtendedsODataService } from './ODataWebExperimental/Northwind/Model/Order_Details_ExtendedsODataService'; 18 | import { Order_SubtotalsODataService } from './ODataWebExperimental/Northwind/Model/Order_SubtotalsODataService'; 19 | import { Orders_QriesODataService } from './ODataWebExperimental/Northwind/Model/Orders_QriesODataService'; 20 | import { Product_Sales_for_1997ODataService } from './ODataWebExperimental/Northwind/Model/Product_Sales_for_1997ODataService'; 21 | import { Products_Above_Average_PricesODataService } from './ODataWebExperimental/Northwind/Model/Products_Above_Average_PricesODataService'; 22 | import { Products_by_CategoriesODataService } from './ODataWebExperimental/Northwind/Model/Products_by_CategoriesODataService'; 23 | import { Sales_by_CategoriesODataService } from './ODataWebExperimental/Northwind/Model/Sales_by_CategoriesODataService'; 24 | import { Sales_Totals_by_AmountsODataService } from './ODataWebExperimental/Northwind/Model/Sales_Totals_by_AmountsODataService'; 25 | import { Summary_of_Sales_by_QuartersODataService } from './ODataWebExperimental/Northwind/Model/Summary_of_Sales_by_QuartersODataService'; 26 | import { Summary_of_Sales_by_YearsODataService } from './ODataWebExperimental/Northwind/Model/Summary_of_Sales_by_YearsODataService'; 27 | 28 | // Aurelia Module for 'DpsApi' 29 | // 30 | export { CategoriesODataService, 31 | CustomerDemographicsODataService, 32 | CustomersODataService, 33 | EmployeesODataService, 34 | Order_DetailsODataService, 35 | OrdersODataService, 36 | ProductsODataService, 37 | RegionsODataService, 38 | ShippersODataService, 39 | SuppliersODataService, 40 | TerritoriesODataService, 41 | Alphabetical_list_of_productsODataService, 42 | Category_Sales_for_1997ODataService, 43 | Current_Product_ListsODataService, 44 | Customer_and_Suppliers_by_CitiesODataService, 45 | InvoicesODataService, 46 | Order_Details_ExtendedsODataService, 47 | Order_SubtotalsODataService, 48 | Orders_QriesODataService, 49 | Product_Sales_for_1997ODataService, 50 | Products_Above_Average_PricesODataService, 51 | Products_by_CategoriesODataService, 52 | Sales_by_CategoriesODataService, 53 | Sales_Totals_by_AmountsODataService, 54 | Summary_of_Sales_by_QuartersODataService, 55 | Summary_of_Sales_by_YearsODataService }; -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Alphabetical_list_of_product.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Alphabetical_list_of_product { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ProductID: number; 9 | public ProductName: string; 10 | public SupplierID: number; 11 | public CategoryID: number; 12 | public QuantityPerUnit: string; 13 | public UnitPrice: number; 14 | public UnitsInStock: number; 15 | public UnitsOnOrder: number; 16 | public ReorderLevel: number; 17 | public Discontinued: boolean; 18 | public CategoryName: string; 19 | 20 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Category.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Product } from './Product'; 3 | 4 | export class Category { 5 | 6 | /* Navigation properties */ 7 | public Products: Product[]; 8 | 9 | /* Properties */ 10 | public CategoryID: number; 11 | public CategoryName: string; 12 | public Description: string; 13 | public Picture: string; 14 | 15 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Category_Sales_for_1997.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Category_Sales_for_1997 { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public CategoryName: string; 9 | public CategorySales: number; 10 | 11 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Current_Product_List.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Current_Product_List { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ProductID: number; 9 | public ProductName: string; 10 | 11 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Customer.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Order } from './Order'; 3 | import { CustomerDemographic } from './CustomerDemographic'; 4 | 5 | export class Customer { 6 | 7 | /* Navigation properties */ 8 | public Orders: Order[]; 9 | public CustomerDemographics: CustomerDemographic[]; 10 | 11 | /* Properties */ 12 | public CustomerID: string; 13 | public CompanyName: string; 14 | public ContactName: string; 15 | public ContactTitle: string; 16 | public Address: string; 17 | public City: string; 18 | public Region: string; 19 | public PostalCode: string; 20 | public Country: string; 21 | public Phone: string; 22 | public Fax: string; 23 | 24 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/CustomerDemographic.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Customer } from './Customer'; 3 | 4 | export class CustomerDemographic { 5 | 6 | /* Navigation properties */ 7 | public Customers: Customer[]; 8 | 9 | /* Properties */ 10 | public CustomerTypeID: string; 11 | public CustomerDesc: string; 12 | 13 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Customer_and_Suppliers_by_City.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Customer_and_Suppliers_by_City { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public City: string; 9 | public CompanyName: string; 10 | public ContactName: string; 11 | public Relationship: string; 12 | 13 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Employee.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Order } from './Order'; 3 | import { Territory } from './Territory'; 4 | 5 | export class Employee { 6 | 7 | /* Navigation properties */ 8 | public Employees1: Employee[]; 9 | public Employee1: Employee; 10 | public Orders: Order[]; 11 | public Territories: Territory[]; 12 | 13 | /* Properties */ 14 | public EmployeeID: number; 15 | public LastName: string; 16 | public FirstName: string; 17 | public Title: string; 18 | public TitleOfCourtesy: string; 19 | public BirthDate: Date; 20 | public HireDate: Date; 21 | public Address: string; 22 | public City: string; 23 | public Region: string; 24 | public PostalCode: string; 25 | public Country: string; 26 | public HomePhone: string; 27 | public Extension: string; 28 | public Photo: string; 29 | public Notes: string; 30 | public ReportsTo: number; 31 | public PhotoPath: string; 32 | 33 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Invoice.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Invoice { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ShipName: string; 9 | public ShipAddress: string; 10 | public ShipCity: string; 11 | public ShipRegion: string; 12 | public ShipPostalCode: string; 13 | public ShipCountry: string; 14 | public CustomerID: string; 15 | public CustomerName: string; 16 | public Address: string; 17 | public City: string; 18 | public Region: string; 19 | public PostalCode: string; 20 | public Country: string; 21 | public Salesperson: string; 22 | public OrderID: number; 23 | public OrderDate: Date; 24 | public RequiredDate: Date; 25 | public ShippedDate: Date; 26 | public ShipperName: string; 27 | public ProductID: number; 28 | public ProductName: string; 29 | public UnitPrice: number; 30 | public Quantity: number; 31 | public Discount: Single; 32 | public ExtendedPrice: number; 33 | public Freight: number; 34 | 35 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Order.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Customer } from './Customer'; 3 | import { Employee } from './Employee'; 4 | import { Order_Detail } from './Order_Detail'; 5 | import { Shipper } from './Shipper'; 6 | 7 | export class Order { 8 | 9 | /* Navigation properties */ 10 | public Customer: Customer; 11 | public Employee: Employee; 12 | public Order_Details: Order_Detail[]; 13 | public Shipper: Shipper; 14 | 15 | /* Properties */ 16 | public OrderID: number; 17 | public CustomerID: string; 18 | public EmployeeID: number; 19 | public OrderDate: Date; 20 | public RequiredDate: Date; 21 | public ShippedDate: Date; 22 | public ShipVia: number; 23 | public Freight: number; 24 | public ShipName: string; 25 | public ShipAddress: string; 26 | public ShipCity: string; 27 | public ShipRegion: string; 28 | public ShipPostalCode: string; 29 | public ShipCountry: string; 30 | 31 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Order_Detail.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Order } from './Order'; 3 | import { Product } from './Product'; 4 | 5 | export class Order_Detail { 6 | 7 | /* Navigation properties */ 8 | public Order: Order; 9 | public Product: Product; 10 | 11 | /* Properties */ 12 | public OrderID: number; 13 | public ProductID: number; 14 | public UnitPrice: number; 15 | public Quantity: number; 16 | public Discount: Single; 17 | 18 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Order_Details_Extended.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Order_Details_Extended { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public OrderID: number; 9 | public ProductID: number; 10 | public ProductName: string; 11 | public UnitPrice: number; 12 | public Quantity: number; 13 | public Discount: Single; 14 | public ExtendedPrice: number; 15 | 16 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Order_Subtotal.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Order_Subtotal { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public OrderID: number; 9 | public Subtotal: number; 10 | 11 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Orders_Qry.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Orders_Qry { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public OrderID: number; 9 | public CustomerID: string; 10 | public EmployeeID: number; 11 | public OrderDate: Date; 12 | public RequiredDate: Date; 13 | public ShippedDate: Date; 14 | public ShipVia: number; 15 | public Freight: number; 16 | public ShipName: string; 17 | public ShipAddress: string; 18 | public ShipCity: string; 19 | public ShipRegion: string; 20 | public ShipPostalCode: string; 21 | public ShipCountry: string; 22 | public CompanyName: string; 23 | public Address: string; 24 | public City: string; 25 | public Region: string; 26 | public PostalCode: string; 27 | public Country: string; 28 | 29 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Product.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Category } from './Category'; 3 | import { Order_Detail } from './Order_Detail'; 4 | import { Supplier } from './Supplier'; 5 | 6 | export class Product { 7 | 8 | /* Navigation properties */ 9 | public Category: Category; 10 | public Order_Details: Order_Detail[]; 11 | public Supplier: Supplier; 12 | 13 | /* Properties */ 14 | public ProductID: number; 15 | public ProductName: string; 16 | public SupplierID: number; 17 | public CategoryID: number; 18 | public QuantityPerUnit: string; 19 | public UnitPrice: number; 20 | public UnitsInStock: number; 21 | public UnitsOnOrder: number; 22 | public ReorderLevel: number; 23 | public Discontinued: boolean; 24 | 25 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Product_Sales_for_1997.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Product_Sales_for_1997 { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public CategoryName: string; 9 | public ProductName: string; 10 | public ProductSales: number; 11 | 12 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Products_Above_Average_Price.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Products_Above_Average_Price { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ProductName: string; 9 | public UnitPrice: number; 10 | 11 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Products_by_Category.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Products_by_Category { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public CategoryName: string; 9 | public ProductName: string; 10 | public QuantityPerUnit: string; 11 | public UnitsInStock: number; 12 | public Discontinued: boolean; 13 | 14 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Region.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Territory } from './Territory'; 3 | 4 | export class Region { 5 | 6 | /* Navigation properties */ 7 | public Territories: Territory[]; 8 | 9 | /* Properties */ 10 | public RegionID: number; 11 | public RegionDescription: string; 12 | 13 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Sales_Totals_by_Amount.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Sales_Totals_by_Amount { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public SaleAmount: number; 9 | public OrderID: number; 10 | public CompanyName: string; 11 | public ShippedDate: Date; 12 | 13 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Sales_by_Category.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Sales_by_Category { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public CategoryID: number; 9 | public CategoryName: string; 10 | public ProductName: string; 11 | public ProductSales: number; 12 | 13 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Shipper.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Order } from './Order'; 3 | 4 | export class Shipper { 5 | 6 | /* Navigation properties */ 7 | public Orders: Order[]; 8 | 9 | /* Properties */ 10 | public ShipperID: number; 11 | public CompanyName: string; 12 | public Phone: string; 13 | 14 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Summary_of_Sales_by_Quarter.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Summary_of_Sales_by_Quarter { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ShippedDate: Date; 9 | public OrderID: number; 10 | public Subtotal: number; 11 | 12 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Summary_of_Sales_by_Year.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export class Summary_of_Sales_by_Year { 4 | 5 | /* Navigation properties */ 6 | 7 | /* Properties */ 8 | public ShippedDate: Date; 9 | public OrderID: number; 10 | public Subtotal: number; 11 | 12 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Supplier.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Product } from './Product'; 3 | 4 | export class Supplier { 5 | 6 | /* Navigation properties */ 7 | public Products: Product[]; 8 | 9 | /* Properties */ 10 | public SupplierID: number; 11 | public CompanyName: string; 12 | public ContactName: string; 13 | public ContactTitle: string; 14 | public Address: string; 15 | public City: string; 16 | public Region: string; 17 | public PostalCode: string; 18 | public Country: string; 19 | public Phone: string; 20 | public Fax: string; 21 | public HomePage: string; 22 | 23 | } -------------------------------------------------------------------------------- /NorthwindExample/NorthwindModel/Territory.ts: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | import { Region } from './Region'; 3 | import { Employee } from './Employee'; 4 | 5 | export class Territory { 6 | 7 | /* Navigation properties */ 8 | public Region: Region; 9 | public Employees: Employee[]; 10 | 11 | /* Properties */ 12 | public TerritoryID: string; 13 | public TerritoryDescription: string; 14 | public RegionID: number; 15 | 16 | } -------------------------------------------------------------------------------- /NorthwindExample/ODataContext.ts: -------------------------------------------------------------------------------- 1 | // 2 | 3 | export class ODataContext { 4 | public static MetadataPath = 'http://services.odata.org/V4/Northwind/Northwind.svc/$metadata'; 5 | public static ODataRootPath = 'http://services.odata.org/V4/Northwind/Northwind.svc/'; 6 | public static CreationDate = '2017-02-03 09:15:19'; 7 | public static ODataVersion = '4.0'; 8 | } 9 | -------------------------------------------------------------------------------- /NorthwindExample/ODataError.ts: -------------------------------------------------------------------------------- 1 | export class ODataError implements Error { 2 | public Status: number; 3 | public Response: any; 4 | 5 | public name: string; 6 | public message: string; 7 | 8 | constructor(status: number, response: any) { 9 | this.name = 'OData Request Error'; 10 | this.message = response; 11 | } 12 | } -------------------------------------------------------------------------------- /NorthwindExample/ODataGetOperation.ts: -------------------------------------------------------------------------------- 1 | import { ODataOperation } from './ODataOperation'; 2 | 3 | export class ODataGetOperation extends ODataOperation { 4 | 5 | private buildQueryUrl(): string { 6 | let url = '?'; 7 | if (this._expand) { url += `$expand=${this._expand}&`; } 8 | if (this._select) { url += `$expand=${this._select}&`; } 9 | return url; 10 | } 11 | 12 | public async Exec(): Promise { 13 | let queryUrl = this.buildQueryUrl(); 14 | return await this.evaluate(queryUrl); 15 | } 16 | 17 | constructor(private idSegment: string, private evaluate: (queryString) => Promise) { 18 | super(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /NorthwindExample/ODataOperation.ts: -------------------------------------------------------------------------------- 1 | export abstract class ODataOperation { 2 | protected _expand: string; 3 | protected _select: string; 4 | 5 | public Expand(...expand: string[]) { 6 | this._expand = this.parseStringOrStringArray(...expand); 7 | return this; 8 | } 9 | 10 | public Select(...select: string[]) { 11 | this._select = this.parseStringOrStringArray(...select); 12 | return this; 13 | } 14 | 15 | protected parseStringOrStringArray(...input: string[]): string { 16 | if (input instanceof Array) { 17 | return input.join(','); 18 | } 19 | 20 | return input as string; 21 | } 22 | 23 | abstract Exec(...args): Promise; 24 | } 25 | -------------------------------------------------------------------------------- /NorthwindExample/ODataQuery.ts: -------------------------------------------------------------------------------- 1 | import { ODataOperation } from './ODataOperation'; 2 | import { ODataQueryResult } from './ODataQueryResult'; 3 | 4 | export class ODataQuery extends ODataOperation { 5 | private _filter: string; 6 | private _top: number; 7 | private _skip: number; 8 | private _orderBy: string; 9 | 10 | private evaluate: (queryString) => Promise>; 11 | 12 | private buildQueryUrl(): string { 13 | let url = '?'; 14 | if (this._filter) { url += `$filter=${this._filter}&`; } 15 | if (this._top) { url += `$top=${this._top}&`; } 16 | if (this._skip) { url += `$skip=${this._skip}&`; } 17 | if (this._orderBy) { url += `$orderby=${this._orderBy}&`; } 18 | if (this._expand) { url += `$expand=${this._expand}&`; } 19 | if (this._select) { url += `$expand=${this._select}&`; } 20 | return url; 21 | } 22 | 23 | constructor(_evaluate: (queryString) => Promise>) { 24 | super(); 25 | this.evaluate = _evaluate; 26 | } 27 | 28 | public Filter(filter: string): ODataQuery { 29 | this._filter = filter; 30 | return this; 31 | }; 32 | 33 | public Top(top: number): ODataQuery { 34 | this._top = top; 35 | return this; 36 | }; 37 | 38 | public Skip(skip: number): ODataQuery { 39 | this._skip = skip; 40 | return this; 41 | } 42 | 43 | public OrderBy(orderBy: string): ODataQuery { 44 | this._orderBy = orderBy; 45 | return this; 46 | } 47 | 48 | public async Exec(): Promise> { 49 | let queryUrl = this.buildQueryUrl(); 50 | return await this.evaluate(queryUrl); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NorthwindExample/ODataQueryResult.ts: -------------------------------------------------------------------------------- 1 | export class ODataQueryResult{ 2 | public '@odata.context': string; 3 | public '@odata.count': number; 4 | 5 | public get Context(): string { 6 | return this['@odata.context']; 7 | } 8 | 9 | public get Count(): number { 10 | return this['@odata.count']; 11 | } 12 | 13 | public value: T[]; 14 | } 15 | -------------------------------------------------------------------------------- /NorthwindExample/ODataServiceAbstract.ts: -------------------------------------------------------------------------------- 1 | import { ODataQuery } from './ODataQuery'; 2 | import { ODataGetOperation } from './ODataGetOperation'; 3 | 4 | export abstract class ODataServiceAbstract { 5 | 6 | protected abstract entitySetUrl: string; 7 | 8 | public async abstract Post(entity: T): Promise; 9 | 10 | public async abstract Patch(id: any, entity: T): Promise; 11 | 12 | public async abstract Put(id: any, entity: T): Promise; 13 | 14 | public async abstract Delete(id: any): Promise; 15 | 16 | protected abstract ExecCustomAction(actionName: string, id: any, ...args: any[]): Promise; 17 | protected abstract ExecCustomCollectionAction(actionName: string, ...args: any[]): Promise; 18 | protected abstract ExecCustomFunction(fucntionName: string, id: any, ...args: any[]): Promise; 19 | protected abstract ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise; 20 | 21 | public abstract Get(id: any): ODataGetOperation; 22 | 23 | public abstract Query(): ODataQuery; 24 | 25 | protected getEntityUriSegment(entityKey: any): string { 26 | entityKey = entityKey.toString(); 27 | if (!/^[0-9]*$/.test(entityKey)) { 28 | return `('${entityKey}')`; 29 | } 30 | 31 | return `(${entityKey})`; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Alphabetical_list_of_productsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Alphabetical_list_of_product } from './../../../NorthwindModel/Alphabetical_list_of_product'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Alphabetical_list_of_productsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Alphabetical_list_of_products'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/CategoriesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Category } from './../../../NorthwindModel/Category'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class CategoriesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Categories'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Category_Sales_for_1997ODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Category_Sales_for_1997 } from './../../../NorthwindModel/Category_Sales_for_1997'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Category_Sales_for_1997ODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Category_Sales_for_1997'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Current_Product_ListsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Current_Product_List } from './../../../NorthwindModel/Current_Product_List'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Current_Product_ListsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Current_Product_Lists'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/CustomerDemographicsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { CustomerDemographic } from './../../../NorthwindModel/CustomerDemographic'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class CustomerDemographicsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('CustomerDemographics'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Customer_and_Suppliers_by_CitiesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Customer_and_Suppliers_by_City } from './../../../NorthwindModel/Customer_and_Suppliers_by_City'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Customer_and_Suppliers_by_CitiesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Customer_and_Suppliers_by_Cities'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/CustomersODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Customer } from './../../../NorthwindModel/Customer'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class CustomersODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Customers'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/EmployeesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Employee } from './../../../NorthwindModel/Employee'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class EmployeesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Employees'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/InvoicesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Invoice } from './../../../NorthwindModel/Invoice'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class InvoicesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Invoices'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Order_DetailsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Order_Detail } from './../../../NorthwindModel/Order_Detail'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Order_DetailsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Order_Details'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Order_Details_ExtendedsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Order_Details_Extended } from './../../../NorthwindModel/Order_Details_Extended'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Order_Details_ExtendedsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Order_Details_Extendeds'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Order_SubtotalsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Order_Subtotal } from './../../../NorthwindModel/Order_Subtotal'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Order_SubtotalsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Order_Subtotals'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/OrdersODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Order } from './../../../NorthwindModel/Order'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class OrdersODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Orders'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Orders_QriesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Orders_Qry } from './../../../NorthwindModel/Orders_Qry'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Orders_QriesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Orders_Qries'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Product_Sales_for_1997ODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Product_Sales_for_1997 } from './../../../NorthwindModel/Product_Sales_for_1997'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Product_Sales_for_1997ODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Product_Sales_for_1997'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/ProductsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Product } from './../../../NorthwindModel/Product'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class ProductsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Products'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Products_Above_Average_PricesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Products_Above_Average_Price } from './../../../NorthwindModel/Products_Above_Average_Price'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Products_Above_Average_PricesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Products_Above_Average_Prices'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Products_by_CategoriesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Products_by_Category } from './../../../NorthwindModel/Products_by_Category'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Products_by_CategoriesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Products_by_Categories'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/RegionsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Region } from './../../../NorthwindModel/Region'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class RegionsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Regions'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Sales_Totals_by_AmountsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Sales_Totals_by_Amount } from './../../../NorthwindModel/Sales_Totals_by_Amount'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Sales_Totals_by_AmountsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Sales_Totals_by_Amounts'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Sales_by_CategoriesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Sales_by_Category } from './../../../NorthwindModel/Sales_by_Category'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Sales_by_CategoriesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Sales_by_Categories'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/ShippersODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Shipper } from './../../../NorthwindModel/Shipper'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class ShippersODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Shippers'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Summary_of_Sales_by_QuartersODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Summary_of_Sales_by_Quarter } from './../../../NorthwindModel/Summary_of_Sales_by_Quarter'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Summary_of_Sales_by_QuartersODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Summary_of_Sales_by_Quarters'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/Summary_of_Sales_by_YearsODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Summary_of_Sales_by_Year } from './../../../NorthwindModel/Summary_of_Sales_by_Year'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class Summary_of_Sales_by_YearsODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Summary_of_Sales_by_Years'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/SuppliersODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Supplier } from './../../../NorthwindModel/Supplier'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class SuppliersODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Suppliers'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /NorthwindExample/ODataWebExperimental/Northwind/Model/TerritoriesODataService.ts: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | import { Territory } from './../../../NorthwindModel/Territory'; 3 | import { ODataContext } from './../../../ODataContext'; 4 | 5 | 6 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 7 | 8 | export class TerritoriesODataService extends AureliaOdataServiceBase { 9 | 10 | constructor() { 11 | super('Territories'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using FuryTech.OdataTypescriptServiceGenerator.Models; 4 | 5 | namespace FuryTech.OdataTypescriptServiceGenerator 6 | { 7 | class Program 8 | { 9 | private static string _metadataPath; 10 | private static string _outputDirectory; 11 | private static bool _purgeOutput; 12 | private static string _endpointName; 13 | 14 | private static void InitConfig() 15 | { 16 | Logger.Log("Reading config..."); 17 | _metadataPath = ConfigurationManager.AppSettings["metadataPath"]; 18 | _outputDirectory = ConfigurationManager.AppSettings["output"]; 19 | _purgeOutput = bool.Parse(ConfigurationManager.AppSettings["purgeOutput"]); 20 | _endpointName = ConfigurationManager.AppSettings["endpointName"]; 21 | } 22 | 23 | static void Main(string[] args) 24 | { 25 | try 26 | { 27 | Logger.Log("Starting..."); 28 | InitConfig(); 29 | 30 | var xml = Loader.Load(_metadataPath); 31 | var metadataReader = new MetadataReader(xml); 32 | 33 | var directoryManager = new DirectoryManager(_outputDirectory); 34 | var templateRenderer = new TemplateRenderer(_outputDirectory); 35 | 36 | directoryManager.PrepareOutput(_purgeOutput); 37 | 38 | Logger.Log("Preparing namespace structure"); 39 | directoryManager.PrepareNamespaceFolders(metadataReader.EnumTypes); 40 | directoryManager.PrepareNamespaceFolders(metadataReader.EntitySets); 41 | directoryManager.PrepareNamespaceFolders(metadataReader.EntityTypes); 42 | directoryManager.PrepareNamespaceFolders(metadataReader.ComplexTypes); 43 | 44 | directoryManager.DirectoryCopy("./StaticContent", _outputDirectory, true); 45 | 46 | templateRenderer.CreateContext(_metadataPath, "4.0"); 47 | 48 | templateRenderer.CreateEntityTypes(metadataReader.EntityTypes); 49 | templateRenderer.CreateComplexTypes(metadataReader.ComplexTypes); 50 | 51 | templateRenderer.CreateEnums(metadataReader.EnumTypes); 52 | 53 | templateRenderer.CreateServicesForEntitySets(metadataReader.EntitySets); 54 | 55 | templateRenderer.CreateAngularModule(new AngularModule(_endpointName, metadataReader.EntitySets)); 56 | 57 | } 58 | catch (Exception ex) 59 | { 60 | Logger.Error($"Error details: {ex}"); 61 | } 62 | 63 | Logger.Log("Service generation finished, exiting..."); 64 | Logger.Log("Press any key to exit"); 65 | Console.ReadKey(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("FuryTech.OdataTypescriptServiceGenerator")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Digic Pictures")] 11 | [assembly: AssemblyProduct("FuryTech.OdataTypescriptServiceGenerator")] 12 | [assembly: AssemblyCopyright("Copyright © Digic Pictures 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("2c2ec957-f5bd-4d39-8f85-daaeab812132")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FuryTech.OdataTypescriptServiceGenerator 2 | 3 | This project is a small command line tool written in .NET, to help scaffolding TypeScript model classes and services from an OData Metadata XML. It has templates bundled for Angular(>2) and Aurelia. 4 | 5 | ## Usage 6 | 7 | 1. Download & Configure 8 | * edit settings in app.config (choose the templates between Aurelia / Angular) 9 | * edit the "metadataPath" setting to point to your endpoint (save your metadata.xml to a file if you have authentication issues) 10 | * set your "endpointName" variable 11 | 2. Build & Run the tool 12 | 3. Grab the generated TypeScript files 13 | * All files from the StaticContent directory will be copied to the output. Please delete the not necessary files (e.g. is you're using Aurelia, delete *AngularOdataServiceBase.ts* to avoid missing import errors during tsc) 14 | 15 | ## What works now 16 | 17 | * EntityTypes to Typescript model classes 18 | * ComplexTypes to Typescript model classes 19 | * Primitive EDM types to Typescript types 20 | * EnumTypes to Typescript Enums 21 | * EntitySets to TypeScript services (for angular2, use *AngularEntitySetService.tst*, for Aurelia, use *AureliaEntitySetService.tst*) 22 | * Strongly typed CustomActions (for entity and for collection) 23 | * Strongly typed CustomFunction (for entity and for collection) 24 | * ODataContext class generation to store some basic endpoint context data 25 | -------------------------------------------------------------------------------- /StaticContent/AngularOdataServiceBase.ts: -------------------------------------------------------------------------------- 1 | import { RequestOptionsArgs } from '@angular/http/src/interfaces'; 2 | import * as https from 'https'; 3 | import { Injectable } from '@angular/core'; 4 | import { Http, RequestOptions, Response } from '@angular/http'; 5 | import 'rxjs/add/operator/toPromise'; 6 | 7 | import { ODataGetOperation } from './ODataGetOperation'; 8 | import { ODataServiceAbstract } from './ODataServiceAbstract'; 9 | import { ODataQuery } from './ODataQuery'; 10 | import { ODataQueryResult } from './ODataQueryResult'; 11 | import { ODataContext } from './ODataContext'; 12 | import { ODataError } from './ODataError'; 13 | 14 | // created by FuryTech.ODataTypeScriptGenerator 15 | 16 | export abstract class AngularODataServiceBase extends ODataServiceAbstract { 17 | 18 | private requestOptions: RequestOptionsArgs = { 19 | withCredentials: true 20 | }; 21 | 22 | protected abstract entitySetUrlSegment: string; 23 | 24 | protected get entitySetUrl(): string { 25 | return ODataContext.ODataRootPath + this.entitySetUrlSegment; 26 | } 27 | 28 | protected abstract http: Http; 29 | constructor() { 30 | super(); 31 | } 32 | 33 | public Get(id: any): ODataGetOperation { 34 | let idSegment = this.getEntityUriSegment(id); 35 | return new ODataGetOperation(idSegment, async (queryString: string) => { 36 | return this.http.get(this.entitySetUrl + idSegment + queryString, { 37 | withCredentials: true, 38 | }).map(a => { 39 | return a.json() as T; 40 | }).toPromise(); 41 | }); 42 | }; 43 | 44 | private extractResponse(res: Response) { 45 | if (res.status < 200 || res.status >= 300) { 46 | throw new ODataError(res.status, res.json()); 47 | } 48 | let body: any = res.json(); 49 | let entity: T = body; 50 | return entity || null; 51 | } 52 | 53 | public async Post(entity: T): Promise { 54 | return this.http.post(this.entitySetUrl, entity, this.requestOptions) 55 | .map(this.extractResponse) 56 | .toPromise(); 57 | } 58 | 59 | public async Patch(id: any, entity: T): Promise { 60 | return this.http 61 | .patch(this.entitySetUrl + this.getEntityUriSegment(id), entity, this.requestOptions) 62 | .toPromise(); 63 | } 64 | 65 | public async Put(id: any, entity: T): Promise { 66 | return this.http 67 | .put(this.entitySetUrl + this.getEntityUriSegment(id), entity, this.requestOptions) 68 | .map(this.extractResponse) 69 | .toPromise(); 70 | } 71 | 72 | public async Delete(id: any): Promise { 73 | return this.http 74 | .delete(this.entitySetUrl + this.getEntityUriSegment(id), this.requestOptions) 75 | .toPromise(); 76 | } 77 | 78 | protected async ExecCustomAction(actionName: string, entity: T, ...args: any[]): Promise { 79 | return this.http 80 | .post(this.entitySetUrl + this.getEntityUriSegment(entity) + `/${actionName}`, null, this.requestOptions) 81 | .map(a => {return a.json(); } ) 82 | .toPromise(); 83 | } 84 | 85 | protected async ExecCustomCollectionAction(actionName: string, ...args: any[]): Promise { 86 | return this.http 87 | .post(this.entitySetUrl + actionName, null, this.requestOptions) 88 | .map(a => {return a.json(); } ) 89 | .toPromise(); 90 | } 91 | 92 | protected async ExecCustomFunction(fucntionName: string, entity: T, ...args: any[]): Promise { 93 | return this.http 94 | .get(this.entitySetUrl + this.getEntityUriSegment(entity) + `/${fucntionName}`, this.requestOptions) 95 | .map(a => {return a.json(); } ) 96 | .toPromise(); 97 | } 98 | 99 | protected async ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise { 100 | return this.http 101 | .get(this.entitySetUrl + fucntionName, this.requestOptions) 102 | .map(a => {return a.json(); } ) 103 | .toPromise(); 104 | 105 | } 106 | 107 | 108 | Query(): ODataQuery { 109 | 110 | let http = this.http; 111 | let entitySetUrl = this.entitySetUrl; 112 | 113 | let evaluateQuery = (queryString: string): Promise> => { 114 | let url = this.entitySetUrl + queryString; 115 | let subscription = http.get(url, { 116 | withCredentials: true 117 | }).map(a => { 118 | return a.json() as ODataQueryResult; 119 | }); 120 | 121 | return subscription.toPromise(); 122 | }; 123 | 124 | return new ODataQuery(evaluateQuery); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /StaticContent/AureliaOdataServiceBase.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpResponseMessage } from 'aurelia-http-client'; 2 | 3 | import { ODataServiceAbstract } from './ODataServiceAbstract'; 4 | import { ODataContext } from './ODataContext'; 5 | import { ODataGetOperation } from './ODataGetOperation'; 6 | import { ODataError } from './ODataError'; 7 | import { ODataQuery } from './ODataQuery'; 8 | import { ODataQueryResult } from './ODataQueryResult'; 9 | 10 | export abstract class AureliaOdataServiceBase extends ODataServiceAbstract{ 11 | 12 | private http: HttpClient; 13 | 14 | protected get entitySetUrl(): string { 15 | return ODataContext.ODataRootPath + this.entitySetUrlSegment; 16 | } 17 | 18 | protected getUriForEntity(id: any): string { 19 | return this.entitySetUrl + this.getEntityUriSegment(id) 20 | } 21 | 22 | constructor(protected entitySetUrlSegment: string) { 23 | super(); 24 | this.http = new HttpClient().configure(c => { 25 | c.withBaseUrl(this.entitySetUrl), 26 | c.withCredentials(true) 27 | }); 28 | } 29 | 30 | /** 31 | * Creates an OData Get Operation object. 32 | * @param id The entity's unique identifier 33 | */ 34 | public Get(id: any): ODataGetOperation { 35 | let entityUri = this.getUriForEntity(id); 36 | return new ODataGetOperation(entityUri, async (queryString: string) => { 37 | var result = await this.http.get(entityUri + queryString); 38 | return result.content; 39 | }); 40 | }; 41 | 42 | private extractResponse(res: HttpResponseMessage) { 43 | if (res.statusCode < 200 || res.statusCode >= 300) { 44 | throw new ODataError(res.statusCode, res.content); 45 | } 46 | let entity: T = res.content; 47 | return entity || null; 48 | } 49 | 50 | /** 51 | * Executes an OData Post Operation 52 | * @param entity the entity to be posted 53 | * @returns an awaitable promise with the created content 54 | */ 55 | public async Post(entity: T): Promise { 56 | var result = await this.http.post(this.entitySetUrl, entity); 57 | return result.content; 58 | } 59 | 60 | /** 61 | * Executes an OData Patch Operation 62 | * @param id The entitie's unique identifier 63 | * @param entity's delta to be patched 64 | * @returns an awaitable promise 65 | */ 66 | public async Patch(id: any, entity: any): Promise { 67 | var result = await this.http.patch(this.getUriForEntity(id), entity); 68 | return result.content; 69 | } 70 | 71 | /** 72 | * Executes an OData Put Operation 73 | * @param id The entitie's unique identifier 74 | * @param entity the entity to be putted 75 | * @returns an awaitable promise with the putted content 76 | */ 77 | public async Put(id: any, entity: T): Promise { 78 | var result = await this.http.put(this.getUriForEntity(id), entity); 79 | return result.content; 80 | } 81 | 82 | /** 83 | * Executes an OData Delete Operation 84 | * @param id The entity's unique identifier 85 | * @returns an awaitable promise 86 | */ 87 | public async Delete(id: any): Promise { 88 | var result = await this.http.delete(this.getUriForEntity(id)); 89 | return result.content; 90 | } 91 | 92 | 93 | /** 94 | * Executes a custom action on an OData entity 95 | * @param actionName The action's actionName 96 | * @param id The entity's unique identifier 97 | * @param ...args The other optional arguments 98 | * @returns An awaitable promise 99 | */ 100 | protected async ExecCustomAction(actionName: string, entityId: any, postData: any): Promise { 101 | var result = await this.http.post(this.getUriForEntity(entityId) + `/${actionName}`, postData); 102 | return result.content; 103 | } 104 | 105 | /** 106 | * Executes a custom action on an OData entity collection 107 | * @param actionName The action's actionName 108 | * @param ...args The other optional arguments 109 | * @returns An awaitable promise 110 | */ 111 | protected async ExecCustomCollectionAction(actionName: string, postData: any): Promise { 112 | var result = await this.http.post(actionName, postData); 113 | return result.content; 114 | } 115 | 116 | /** 117 | * Executes a custom function on an OData entity 118 | * @param actionName The action's actionName 119 | * @param id The entity's unique identifier 120 | * @param ...args The other optional arguments 121 | * @returns An awaitable promise 122 | */ 123 | protected async ExecCustomFunction(fucntionName: string, entityId: any, ...args: any[]): Promise { 124 | let result = await this.http.get(this.getUriForEntity(entityId) + `/${fucntionName}`); 125 | return result.content; 126 | } 127 | 128 | /** 129 | * Executes a custom function on an OData entity collection 130 | * @param actionName The action's actionName 131 | * @param ...args The other optional arguments 132 | * @returns An awaitable promise 133 | */ 134 | protected async ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise { 135 | let result = await this.http.get(fucntionName); 136 | return result.content; 137 | } 138 | 139 | 140 | /** 141 | * Creates an OData Query object 142 | * @param id The entitie's unique identifier 143 | * @param entity the entity to be posted 144 | * @returns an awaitable promise with the created content 145 | */ 146 | Query(): ODataQuery { 147 | let http = this.http; 148 | let evaluateQuery = async (queryString: string): Promise> => { 149 | let url = this.entitySetUrl + "/" + queryString; 150 | let response = await http.get(url); 151 | return response.content; 152 | }; 153 | 154 | return new ODataQuery(evaluateQuery); 155 | } 156 | 157 | } -------------------------------------------------------------------------------- /StaticContent/NativeOdataServiceBase.ts: -------------------------------------------------------------------------------- 1 | import { ODataContext } from "./ODataContext"; 2 | import { ODataError } from "./ODataError"; 3 | import { ODataGetOperation } from "./ODataGetOperation"; 4 | import { ODataQuery } from "./ODataQuery"; 5 | import { ODataQueryResult } from "./ODataQueryResult"; 6 | import { ODataServiceAbstract } from "./ODataServiceAbstract"; 7 | 8 | export abstract class NativeOdataServiceBase extends ODataServiceAbstract { 9 | 10 | private defaultInit: RequestInit = { 11 | credentials: 'include', 12 | } 13 | protected get entitySetUrl(): string { 14 | return ODataContext.ODataRootPath + this.entitySetUrlSegment; 15 | } 16 | 17 | constructor(protected entitySetUrlSegment: string) { 18 | super(); 19 | } 20 | 21 | /** 22 | * Creates an OData Get Operation object. 23 | * @param id The entity's unique identifier 24 | */ 25 | public Get(id: any): ODataGetOperation { 26 | const entityUri = this.getUriForEntity(id); 27 | return new ODataGetOperation(async (queryString: string) => { 28 | return await this.extractResponse(entityUri + queryString); 29 | }); 30 | } 31 | 32 | /** 33 | * Executes an OData Post Operation 34 | * @param entity the entity to be posted 35 | * @returns an awaitable promise with the created content 36 | */ 37 | public async Post(entity: T): Promise { 38 | return await this.extractResponse(this.entitySetUrl, { 39 | method: 'POST', 40 | body: JSON.stringify(entity), 41 | }); 42 | } 43 | 44 | /** 45 | * Executes an OData Patch Operation 46 | * @param id The entitie's unique identifier 47 | * @param entity's delta to be patched 48 | * @returns an awaitable promise 49 | */ 50 | public async Patch(id: any, entity: any): Promise { 51 | return await this.extractResponse(this.getUriForEntity(id), { 52 | method: 'PATCH', 53 | body: JSON.stringify(entity), 54 | }) 55 | } 56 | 57 | /** 58 | * Executes an OData Put Operation 59 | * @param id The entitie's unique identifier 60 | * @param entity the entity to be putted 61 | * @returns an awaitable promise with the putted content 62 | */ 63 | public async Put(id: any, entity: T): Promise { 64 | return await this.extractResponse(this.getUriForEntity(id), { 65 | method: 'PUT', 66 | body: JSON.stringify(entity), 67 | }); 68 | } 69 | 70 | /** 71 | * Executes an OData Delete Operation 72 | * @param id The entity's unique identifier 73 | * @returns an awaitable promise 74 | */ 75 | public async Delete(id: any): Promise { 76 | return await this.extractResponse(this.getUriForEntity(id), { 77 | method: 'DELETE', 78 | }); 79 | } 80 | 81 | /** 82 | * Creates an OData Query object 83 | * @param id The entitie's unique identifier 84 | * @param entity the entity to be posted 85 | * @returns an awaitable promise with the created content 86 | */ 87 | public Query(): ODataQuery { 88 | const evaluateQuery = async (queryString: string): Promise> => { 89 | const url = this.entitySetUrl + "/" + queryString; 90 | return this.extractResponse>(url); 91 | }; 92 | 93 | return new ODataQuery(evaluateQuery); 94 | } 95 | 96 | protected getUriForEntity(id: any): string { 97 | return this.entitySetUrl + this.getEntityUriSegment(id); 98 | } 99 | 100 | /** 101 | * Executes a custom action on an OData entity 102 | * @param actionName The action's actionName 103 | * @param id The entity's unique identifier 104 | * @param ...args The other optional arguments 105 | * @returns An awaitable promise 106 | */ 107 | protected async ExecCustomAction(actionName: string, entityId: any, postData?: TData): Promise { 108 | return await this.extractResponse(this.getUriForEntity(entityId) + `/${actionName}`, { 109 | method: 'POST', 110 | body: JSON.stringify(postData), 111 | }) 112 | } 113 | 114 | /** 115 | * Executes a custom action on an OData entity collection 116 | * @param actionName The action's actionName 117 | * @param ...args The other optional arguments 118 | * @returns An awaitable promise 119 | */ 120 | protected async ExecCustomCollectionAction(actionName: string, postData?: TData): Promise { 121 | return await this.extractResponse(actionName, { 122 | method: 'POST', 123 | body: JSON.stringify(postData), 124 | }) 125 | } 126 | 127 | /** 128 | * Executes a custom function on an OData entity 129 | * @param actionName The action's actionName 130 | * @param id The entity's unique identifier 131 | * @param ...args The other optional arguments 132 | * @returns An awaitable promise 133 | */ 134 | protected async ExecCustomFunction(fucntionName: string, entityId: any): Promise { 135 | return await this.extractResponse(this.getUriForEntity(entityId) + `/${fucntionName}`) 136 | } 137 | 138 | /** 139 | * Executes a custom function on an OData entity collection 140 | * @param actionName The action's actionName 141 | * @param ...args The other optional arguments 142 | * @returns An awaitable promise 143 | */ 144 | protected async ExecCustomCollectionFunction(functionName: string): Promise { 145 | return await this.extractResponse(functionName) 146 | } 147 | 148 | private async extractResponse(input?: Request | string, init?: RequestInit): Promise { 149 | const response = await fetch(input, { 150 | ...this.defaultInit, 151 | ...init 152 | }); 153 | const body: T = await response.json(); 154 | if (response.status < 200 || response.status>= 300) { 155 | throw new ODataError(response); 156 | } 157 | const entity: T = body; 158 | return entity || null; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /StaticContent/ODataError.ts: -------------------------------------------------------------------------------- 1 | export class ODataError implements Error { 2 | public Response: any; 3 | public name: string; 4 | public message: string; 5 | 6 | constructor(response: Response) { 7 | this.name = "OData Request Error"; 8 | this.message = response.statusText; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /StaticContent/ODataFilterBuilder.ts: -------------------------------------------------------------------------------- 1 | 2 | type FilterArgs = [K, string]; 3 | type FilterSegment = ODataFilterExpression | ODataFilterConnection; 4 | 5 | export class ODataFilterExpression{ 6 | 7 | private value: string = ""; 8 | 9 | private getFilterValueSegment(value: any): string { 10 | let castedValue = value.toString(); 11 | if (typeof value == "string" && !/^[0-9]*$/.test(castedValue)) { 12 | return `('${castedValue}')`; 13 | } 14 | 15 | return `(${castedValue})`; 16 | } 17 | 18 | constructor(public filterBuilderRef: ODataFilterBuilder) { } 19 | 20 | private Finialize() { 21 | this.filterBuilderRef.filterSegments.push(this); 22 | return new ODataFilterConnection(this.filterBuilderRef); 23 | } 24 | 25 | /** 26 | * Creates an instance of an Equals (~eq) filter segment 27 | * @param field The name of the field to check (String literal) 28 | * @param value The value to check 29 | * @returns The next ODataFilterConnection (Fluent) 30 | */ 31 | 32 | public Equals(field: K, value: any) { 33 | this.value = `${field} eq ${this.getFilterValueSegment(value)}`; 34 | return this.Finialize(); 35 | } 36 | 37 | /** 38 | * Creates an instance of an Not Equals (~ne) filter segment 39 | * @param field The name of the field to check (String literal) 40 | * @param value The value to check 41 | * @returns The next ODataFilterConnection (Fluent) 42 | */ 43 | public NotEquals(field: K, value: any) { 44 | this.value = `${field} ne ${this.getFilterValueSegment(value)}'`; 45 | return this.Finialize(); 46 | } 47 | 48 | /** 49 | * Creates an instance of a Greater Than (~gt) filter segment 50 | * @param field The name of the field to check (String literal) 51 | * @param value The value to check 52 | * @returns The next ODataFilterConnection (Fluent) 53 | */ 54 | public GreaterThan(field: K, value: any) { 55 | this.value = `${field} gt ${this.getFilterValueSegment(value)}`; 56 | return this.Finialize(); 57 | } 58 | 59 | /** 60 | * Creates an instance of a Greater Than or Equals (~ge) filter segment 61 | * @param field The name of the field to check (String literal) 62 | * @param value The value to check 63 | * @returns The next ODataFilterConnection (Fluent) 64 | */ 65 | public GreaterThanOrEquals(field: K, value: any) { 66 | this.value = `${field} ge ${this.getFilterValueSegment(value)}`; 67 | return this.Finialize(); 68 | } 69 | 70 | /** 71 | * Creates an instance of a Lesser Than (~lt) filter segment 72 | * @param field The name of the field to check (String literal) 73 | * @param value The value to check 74 | * @returns The next ODataFilterConnection (Fluent) 75 | */ 76 | public LessThan(field: K, value: any) { 77 | this.value = `${field} lt ${this.getFilterValueSegment(value)}`; 78 | return this.Finialize(); 79 | } 80 | 81 | 82 | /** 83 | * Creates an instance of a Lesser Than or equals (~le) filter segment 84 | * @param field The name of the field to check (String literal) 85 | * @param value The value to check 86 | * @returns The next ODataFilterConnection (Fluent) 87 | */ 88 | public LessThanOrEquals(field: K, value: any) { 89 | this.value = `${field} le ${this.getFilterValueSegment(value)}`; 90 | return this.Finialize(); 91 | } 92 | 93 | /** 94 | * Creates an instance of a HAS (~has) filter segment 95 | * @param field The name of the field to check (String literal) 96 | * @param value The value to check 97 | * @returns The next ODataFilterConnection (Fluent) 98 | */ 99 | public Has(field: K, value: any) { 100 | this.value = `${field} has ${this.getFilterValueSegment(value)}`; 101 | return this.Finialize(); 102 | } 103 | 104 | /** 105 | * Creates an instance of a nested negated (~not) FilterBuilder object 106 | * @param build The fluent chain for the filter expression 107 | * @returns The next ODataFilterConnection (Fluent) 108 | */ 109 | public Not(build: (b: ODataFilterExpression) => void) { 110 | let builder = ODataFilterBuilder.Create(); 111 | build(ODataFilterBuilder.Create()); 112 | this.value = `not (${builder.toString()})`; 113 | return this.Finialize(); 114 | } 115 | 116 | /** 117 | * Creates an instance of a nested FilterBuilder object 118 | * @param build The fluent chain for the filter expression 119 | * @returns The next ODataFilterConnection (Fluent) 120 | */ 121 | public BuildFilter(build: (b: ODataFilterExpression) => void) { 122 | let builder = ODataFilterBuilder.Create(); 123 | build(ODataFilterBuilder.Create()); 124 | this.value = `(${builder.toString()})`; 125 | return this.Finialize(); 126 | } 127 | 128 | /** 129 | * Gets the evaluated OData filter segment 130 | * @returns The OData filter segment 131 | */ 132 | public toString(): string { 133 | return this.value; 134 | } 135 | 136 | } 137 | 138 | export class ODataFilterConnection{ 139 | 140 | private type: 'and' | 'or' = "and"; 141 | constructor(public filterBuilderRef: ODataFilterBuilder) { } 142 | 143 | /** 144 | * Sets the connection between OData Filter expression segments to 'AND' type 145 | * @returns The next ODataFilterExpression (Fluent) 146 | */ 147 | public get And() { 148 | this.type = "and"; 149 | this.filterBuilderRef.filterSegments.push(this); 150 | return new ODataFilterExpression(this.filterBuilderRef); 151 | } 152 | 153 | /** 154 | * Sets the connection between OData Filter expression segments to 'OR' type 155 | * @returns The next ODataFilterExpression (Fluent) 156 | */ 157 | public get Or() { 158 | this.type = "or"; 159 | this.filterBuilderRef.filterSegments.push(this); 160 | return new ODataFilterExpression(this.filterBuilderRef); 161 | } 162 | 163 | public toString() { 164 | return this.type; 165 | } 166 | } 167 | 168 | export class ODataFilterBuilder{ 169 | 170 | public filterSegments: FilterSegment[] = []; 171 | 172 | 173 | /** 174 | * Factory method for creating ODataFilterBuilders 175 | * @returns The first ODataFilterExpression value for the ODataFilterBuilder 176 | */ 177 | public static Create(): ODataFilterExpression { 178 | let builder = new ODataFilterBuilder(); 179 | let firstSegment = new ODataFilterExpression(builder); 180 | return firstSegment; 181 | } 182 | 183 | 184 | /** 185 | * Evaluates the ODataFilterBuilder's segments into a parsed OData Filter expression 186 | * @returns The Filter query expression 187 | */ 188 | public toString(): string { 189 | return this.filterSegments.map(s => s.toString()).join(' '); 190 | } 191 | } -------------------------------------------------------------------------------- /StaticContent/ODataGetOperation.ts: -------------------------------------------------------------------------------- 1 | import { ODataOperation } from "./ODataOperation"; 2 | 3 | export class ODataGetOperation extends ODataOperation { 4 | 5 | constructor(private evaluate: (queryString: string) => Promise) { 6 | super(); 7 | } 8 | 9 | /** 10 | * Executes the Get operation 11 | * @returns An awaitable Promise 12 | */ 13 | public async Exec(): Promise { 14 | const queryUrl = this.buildQueryUrl(); 15 | return await this.evaluate(queryUrl); 16 | } 17 | 18 | private buildQueryUrl(): string { 19 | let url = "?"; 20 | if (this._expand) { url += `$expand=${this._expand}&`; } 21 | if (this._select) { url += `$expand=${this._select}&`; } 22 | if (url === "?") { url = ""; } 23 | return url; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /StaticContent/ODataOperation.ts: -------------------------------------------------------------------------------- 1 | export abstract class ODataOperation { 2 | protected _expand!: string; 3 | protected _select!: string; 4 | 5 | /** 6 | * Sets the OData $expand= property 7 | * @param ...expand The field name(s) to be expanded 8 | */ 9 | public Expand(...expand: K[]) { 10 | this._expand = this.parseStringOrStringArray(...expand); 11 | return this; 12 | } 13 | 14 | /** 15 | * Sets the OData $select= property 16 | * @param ...select The field name(s) to be included in the OData Select 17 | */ 18 | public Select(...select: K[]) { 19 | this._select = this.parseStringOrStringArray(...select); 20 | return this; 21 | } 22 | 23 | /** 24 | * Executes the operation, should return an awaitable Promise 25 | */ 26 | public abstract Exec(): Promise; 27 | 28 | protected parseStringOrStringArray(...input: Array): string { 29 | if (input instanceof Array) { 30 | return input.join(","); 31 | } 32 | 33 | return input as string; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /StaticContent/ODataQuery.ts: -------------------------------------------------------------------------------- 1 | import { ODataFilterBuilder, ODataFilterExpression } from './ODataFilterBuilder'; 2 | import { ODataOperation } from './ODataOperation'; 3 | import { ODataQueryResult } from './ODataQueryResult'; 4 | 5 | export class ODataQuery extends ODataOperation { 6 | private _filter!: string; 7 | private _top!: number; 8 | private _skip!: number; 9 | private _orderBy!: string; 10 | 11 | private evaluate: (queryString: string) => Promise>; 12 | 13 | private buildQueryUrl(): string { 14 | let url = '?'; 15 | if (this._filter) { url += `$filter=${this._filter}&`; } 16 | if (this._top) { url += `$top=${this._top}&`; } 17 | if (this._skip) { url += `$skip=${this._skip}&`; } 18 | if (this._orderBy) { url += `$orderby=${this._orderBy}&`; } 19 | if (this._expand) { url += `$expand=${this._expand}&`; } 20 | if (this._select) { url += `$expand=${this._select}&`; } 21 | if (url === '?') url = ''; 22 | return url; 23 | } 24 | 25 | constructor(_evaluate: (queryString: string) => Promise>) { 26 | super(); 27 | this.evaluate = _evaluate; 28 | } 29 | 30 | /** 31 | * Sets the '$filter=' variable in the OData Query URL. 32 | * @param filter The plain text value for the odata $filter. Overrides the FilterBuilder 33 | * @returns the ODataQuery instance (Fluent) 34 | */ 35 | public Filter(filter: string): ODataQuery { 36 | this._filter = filter; 37 | return this; 38 | }; 39 | 40 | 41 | /** 42 | * Builds a query expression for the OData Query 43 | * @param build The builder expression 44 | * @returns The ODataQuery instance (Fluent) 45 | */ 46 | public BuildFilter(build: (b: ODataFilterExpression) => void): ODataQuery { 47 | let builder = ODataFilterBuilder.Create(); 48 | build(builder); 49 | this._filter = builder.filterBuilderRef.toString(); 50 | return this; 51 | } 52 | 53 | /** 54 | * Sets the OData $top= query attribute 55 | * @param top The value to be returned by the query 56 | * @returns The ODataQuery instance (Fluent) 57 | */ 58 | public Top(top: number): ODataQuery { 59 | this._top = top; 60 | return this; 61 | }; 62 | 63 | /** 64 | * Sets the OData $skip= query attribute 65 | * @param skip The value to be skipped by the query 66 | * @returns The ODataQuery instance (Fluent) 67 | */ 68 | public Skip(skip: number): ODataQuery { 69 | this._skip = skip; 70 | return this; 71 | } 72 | 73 | /** 74 | * Sets the OData $orderby= query attribute 75 | * @param orderBy The field name(s) in string 76 | * @returns The ODataQuery instance (Fluent) 77 | */ 78 | public OrderBy(...orderBy: K[]): ODataQuery { 79 | this._orderBy = this.parseStringOrStringArray(...orderBy); 80 | return this; 81 | } 82 | 83 | /** 84 | * Executes the query. 85 | * @returns An awaitable promise with the query result. 86 | */ 87 | public async Exec(): Promise> { 88 | let queryUrl = this.buildQueryUrl(); 89 | return await this.evaluate(queryUrl); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /StaticContent/ODataQueryResult.ts: -------------------------------------------------------------------------------- 1 | export class ODataQueryResult{ 2 | public '@odata.context': string; 3 | public '@odata.count': number; 4 | 5 | /** 6 | * The '@odata.context' variable returned by the OData service 7 | */ 8 | public get Context(): string { 9 | return this['@odata.context']; 10 | } 11 | 12 | /** 13 | * The '@odata.count' variable returned by the OData service 14 | */ 15 | public get Count(): number { 16 | return this['@odata.count']; 17 | } 18 | 19 | /** 20 | * The query result in an array 21 | */ 22 | public value: T[] = []; 23 | } 24 | -------------------------------------------------------------------------------- /StaticContent/ODataServiceAbstract.ts: -------------------------------------------------------------------------------- 1 | import { ODataQuery } from './ODataQuery'; 2 | import { ODataGetOperation } from './ODataGetOperation'; 3 | 4 | export abstract class ODataServiceAbstract { 5 | 6 | protected abstract entitySetUrl: string; 7 | 8 | /** 9 | * Creates an OData Get Operation object. 10 | * @param id The entity's unique identifier 11 | */ 12 | public abstract Get(id: any): ODataGetOperation; 13 | 14 | /** 15 | * Executes an OData Post Operation 16 | * @param entity the entity to be posted 17 | * @returns an awaitable promise with the created content 18 | */ 19 | 20 | public async abstract Post(entity: T): Promise; 21 | 22 | /** 23 | * Executes an OData Patch Operation 24 | * @param id The entitie's unique identifier 25 | * @param entity's delta to be patched 26 | * @returns an awaitable promise 27 | */ 28 | public async abstract Patch(id: any, entity: T): Promise; 29 | 30 | /** 31 | * Executes an OData Put Operation 32 | * @param id The entitie's unique identifier 33 | * @param entity the entity to be putted 34 | * @returns an awaitable promise with the putted content 35 | */ 36 | public async abstract Put(id: any, entity: T): Promise; 37 | 38 | /** 39 | * Executes an OData Delete Operation 40 | * @param id The entity's unique identifier 41 | * @returns an awaitable promise 42 | */ 43 | public async abstract Delete(id: any): Promise; 44 | 45 | /** 46 | * Executes a custom action on an OData entity 47 | * @param actionName The action's actionName 48 | * @param id The entity's unique identifier 49 | * @param ...args The other optional arguments 50 | * @returns An awaitable promise 51 | */ 52 | protected abstract ExecCustomAction(actionName: string, id: any, ...args: any[]): Promise; 53 | /** 54 | * Executes a custom action on an OData entity collection 55 | * @param actionName The action's actionName 56 | * @param ...args The other optional arguments 57 | * @returns An awaitable promise 58 | */ 59 | protected abstract ExecCustomCollectionAction(actionName: string, ...args: any[]): Promise; 60 | 61 | /** 62 | * Executes a custom function on an OData entity 63 | * @param actionName The action's actionName 64 | * @param id The entity's unique identifier 65 | * @param ...args The other optional arguments 66 | * @returns An awaitable promise 67 | */ 68 | protected abstract ExecCustomFunction(fucntionName: string, id: any, ...args: any[]): Promise; 69 | /** 70 | * Executes a custom function on an OData entity collection 71 | * @param actionName The action's actionName 72 | * @param ...args The other optional arguments 73 | * @returns An awaitable promise 74 | */ 75 | protected abstract ExecCustomCollectionFunction(fucntionName: string, ...args: any[]): Promise; 76 | 77 | /** 78 | * Creates an OData Query object 79 | * @param id The entitie's unique identifier 80 | * @param entity the entity to be posted 81 | * @returns an awaitable promise with the created content 82 | */ 83 | public abstract Query(): ODataQuery; 84 | 85 | protected getEntityUriSegment(entityKey: any): string { 86 | entityKey = entityKey.toString(); 87 | if (!/^[0-9]*$/.test(entityKey)) { 88 | return `('${entityKey}')`; 89 | } 90 | 91 | return `(${entityKey})`; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TemplateRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.IO; 5 | using System.Linq; 6 | using FuryTech.OdataTypescriptServiceGenerator.Abstracts; 7 | using FuryTech.OdataTypescriptServiceGenerator.Extensions; 8 | using FuryTech.OdataTypescriptServiceGenerator.Interfaces; 9 | using FuryTech.OdataTypescriptServiceGenerator.Models; 10 | 11 | namespace FuryTech.OdataTypescriptServiceGenerator 12 | { 13 | public class TemplateRenderer 14 | { 15 | private readonly string _entityTemplate; 16 | private readonly string _propertyTemplate; 17 | private readonly string _importTemplate; 18 | private readonly string _enumTypeTemplate; 19 | private readonly string _enumMemberTemplate; 20 | private readonly string _entitySetServiceTemplate; 21 | private readonly string _contextTemplate; 22 | private readonly string _ModuleTemplate; 23 | private readonly string _CustomActionTemplate; 24 | private readonly string _CustomFunctionTemplate; 25 | 26 | 27 | private readonly string _outFolder; 28 | 29 | public TemplateRenderer(string outFolder) 30 | { 31 | _outFolder = outFolder; 32 | _entityTemplate = File.ReadAllText(ConfigurationManager.AppSettings["EntityTypeTemplate"]); 33 | _propertyTemplate = File.ReadAllText(ConfigurationManager.AppSettings["EntityPropertyTemplate"]); 34 | _importTemplate = File.ReadAllText(ConfigurationManager.AppSettings["ImportsTemplate"]); 35 | _enumTypeTemplate = File.ReadAllText(ConfigurationManager.AppSettings["EnumTypeTemplate"]); 36 | _enumMemberTemplate = File.ReadAllText(ConfigurationManager.AppSettings["EnumMemberTemplate"]); 37 | _entitySetServiceTemplate = File.ReadAllText(ConfigurationManager.AppSettings["EntitySetServiceTemplate"]); 38 | _contextTemplate = File.ReadAllText(ConfigurationManager.AppSettings["ContextTemplate"]); 39 | _ModuleTemplate = File.ReadAllText(ConfigurationManager.AppSettings["ModuleTemplate"]); 40 | _CustomActionTemplate = File.ReadAllText(ConfigurationManager.AppSettings["CustomActionTemplate"]); 41 | _CustomFunctionTemplate = File.ReadAllText(ConfigurationManager.AppSettings["CustomFunctionTemplate"]); 42 | } 43 | 44 | private string ParseImports(IHasImports entity) 45 | { 46 | return string.Join("", entity.GetImportRecords().Select(a => 47 | _importTemplate.Clone().ToString() 48 | .Replace("$moduleNames$", a.ElementTypeName) 49 | .Replace("$relativePaths$", "./" + a.RelativeNamespace))); 50 | } 51 | 52 | private void DoRender(IRenderableElement entity, string template, string fileName = null) 53 | { 54 | var ns = entity.NameSpace.Replace('.', Path.DirectorySeparatorChar); 55 | if (fileName == null) 56 | fileName = entity.Name; 57 | 58 | var imports = entity as IHasImports; 59 | if (imports != null) 60 | { 61 | template = template.Replace("$imports$", ParseImports(imports)); 62 | } 63 | 64 | template = template 65 | .Replace("$EntityType$", entity.Name) 66 | .Replace("$Name$", entity.Name) 67 | .Replace("$NameSpace$", entity.NameSpace); 68 | 69 | File.WriteAllText($"{_outFolder}\\{ns}\\{fileName}.ts", template); 70 | } 71 | 72 | public void CreateEntityTypes(IEnumerable types) 73 | { 74 | foreach (var entityType in types) 75 | { 76 | CreateTypescriptModelClass(entityType); 77 | } 78 | } 79 | 80 | public void CreateComplexTypes(IEnumerable types) 81 | { 82 | foreach (var complexType in types) 83 | { 84 | CreateTypescriptModelClass(complexType); 85 | } 86 | } 87 | 88 | private void CreateTypescriptModelClass(TypescriptModelClassAbstract entityType) 89 | { 90 | var props = entityType.Properties.Select(prop => 91 | _propertyTemplate.Clone() 92 | .ToString() 93 | .Replace("$propertyName$", prop.Name) 94 | .Replace("$propertyType$", prop.TypescriptType)); 95 | 96 | 97 | var refs = entityType.NavigationProperties.Select(nav => 98 | _propertyTemplate.Clone() 99 | .ToString() 100 | .Replace("$propertyName$", nav.Name) 101 | .Replace("$propertyType$", nav.Type.Split('.').Last() + (nav.IsCollection ? "[]" : "")) 102 | ); 103 | 104 | var template = _entityTemplate.Clone().ToString() 105 | .Replace("$properties$", string.Join("", props)) 106 | .Replace("$navigationProperties$", string.Join("", refs)); 107 | 108 | DoRender(entityType, template); 109 | } 110 | 111 | public void CreateEnums(IEnumerable types) 112 | { 113 | foreach (var enumType in types) 114 | { 115 | CreateEnum(enumType); 116 | } 117 | } 118 | 119 | private void CreateEnum(EnumType enumType) 120 | { 121 | var members = enumType.Members.Select(m => _enumMemberTemplate.Clone().ToString() 122 | .Replace("$memberName$", m.Name) 123 | .Replace("$memberValue$", m.Value)); 124 | 125 | var template = _enumTypeTemplate.Clone().ToString() 126 | .Replace("$members$", string.Join("", members).TrimEnd(',')); 127 | DoRender(enumType, template); 128 | } 129 | 130 | 131 | public void CreateServicesForEntitySets(IEnumerable entitySets) 132 | { 133 | foreach (var entitySet in entitySets) 134 | { 135 | CreateServiceForEntitySet(entitySet); 136 | } 137 | } 138 | 139 | private string GetCustomActionsTemplate(List actions) 140 | { 141 | if (!actions.Any()) 142 | { 143 | return string.Empty; 144 | } 145 | var result = "\r\n\t/*Custom Actions*/\r\n"; 146 | foreach (var customAction in actions) 147 | { 148 | var returnTypeName = !string.IsNullOrWhiteSpace(customAction.ReturnType) ? customAction.ReturnType.Split('.').Last(a => !string.IsNullOrWhiteSpace(a)) 149 | + (customAction.ReturnsCollection ? "[]" : "") : "any"; 150 | var baseExecFunctionName = customAction.IsCollectionAction 151 | ? "ExecCustomCollectionAction" 152 | : "ExecCustomAction"; 153 | 154 | var entityArgument = customAction.IsCollectionAction ? "" : customAction.BindingParameter.Split('.').Last(a => !string.IsNullOrWhiteSpace(a))+"Id"; 155 | var argumentWithType = customAction.IsCollectionAction ? "" : $"{entityArgument}: any"; 156 | 157 | result += _CustomActionTemplate.Clone().ToString() 158 | .Replace("$actionName$", customAction.Name) 159 | .Replace("$actionFullName$", customAction.NameSpace + "." + customAction.Name) 160 | .Replace("$returnType$", returnTypeName) 161 | .Replace("$execName$", baseExecFunctionName) 162 | .Replace("$argument$", ", " + entityArgument) 163 | .Replace("$argumentWithType$", argumentWithType); 164 | } 165 | return result; 166 | } 167 | 168 | private string GetCustomFunctionsTemplate(List functions) 169 | { 170 | if (!functions.Any()) 171 | { 172 | return string.Empty; 173 | } 174 | var result = "\r\n\t/*Custom Functions*/\r\n"; 175 | foreach (var customFunction in functions) 176 | { 177 | var returnTypeName = customFunction.ReturnType.Split('.').Last(a => !string.IsNullOrWhiteSpace(a)) 178 | + (customFunction.ReturnsCollection ? "[]" : ""); 179 | var baseExecFunctionName = customFunction.IsCollectionAction 180 | ? "ExecCustomCollectionFunction" 181 | : "ExecCustomFunction"; 182 | 183 | var entityArgument = customFunction.IsCollectionAction ? "" : customFunction.BindingParameter.Split('.').Last(a=>!string.IsNullOrWhiteSpace(a))+"Id"; 184 | var argumentWithType = customFunction.IsCollectionAction ? "" : $"{entityArgument}: any"; 185 | 186 | result += _CustomFunctionTemplate.Clone().ToString() 187 | .Replace("$functionName$", customFunction.Name) 188 | .Replace("$functionFullName$", customFunction.NameSpace + "." + customFunction.Name) 189 | .Replace("$returnType$", returnTypeName) 190 | .Replace("$execName$", baseExecFunctionName) 191 | .Replace("$argument$", ", " + entityArgument) 192 | .Replace("$argumentWithType$", argumentWithType); 193 | } 194 | return result; 195 | } 196 | 197 | private void CreateServiceForEntitySet(EntitySet entitySet) 198 | { 199 | var template = _entitySetServiceTemplate.Clone().ToString() 200 | .Replace("$entitySetUrl$", entitySet.EntitySetName) 201 | .Replace("$entityTypeName$", entitySet.EntityType.Split('.').Last()) 202 | .Replace("$customActions$", GetCustomActionsTemplate(entitySet.CustomActions.ToList())) 203 | .Replace("$customFunctions$", GetCustomFunctionsTemplate(entitySet.CustomFunctions.ToList())); 204 | DoRender(entitySet, template); 205 | } 206 | 207 | public void CreateContext(string metadataPath, string odataVersion) 208 | { 209 | 210 | var template = _contextTemplate.Clone().ToString() 211 | .Replace("$odataRootPath$", metadataPath.TrimEnd("$metadata".ToCharArray())) 212 | .Replace("$metadataPath$", metadataPath) 213 | .Replace("$CreationDate$", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) 214 | .Replace("$ODataVersion$", odataVersion); 215 | File.WriteAllText($"{_outFolder}\\ODataContext.ts", template); 216 | } 217 | 218 | public void CreateAngularModule(AngularModule module) 219 | { 220 | var template = _ModuleTemplate.Clone().ToString() 221 | .Replace("$moduleProviders$", string.Join(",\r\n\t",module.EntitySets.Select(a=>a.Name))) 222 | .Replace("$moduleName$", module.Name); 223 | 224 | DoRender(module, template); 225 | 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /Templates/.vscode/symbols.json: -------------------------------------------------------------------------------- 1 | {"symbols":{},"files":{}} -------------------------------------------------------------------------------- /Templates/AngularEntitySetService.tst: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | $imports$ 3 | 4 | import { Injectable } from '@angular/core'; 5 | import { Http } from '@angular/http'; 6 | import { AngularODataServiceBase } from '../AngularOdataServiceBase'; 7 | 8 | @Injectable() 9 | export class $Name$ extends AngularODataServiceBase<$entityTypeName$> { 10 | public entitySetUrlSegment = '$entitySetUrl$'; 11 | $customActions$$customFunctions$ 12 | constructor(protected http: Http) { 13 | super(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Templates/AngularModuleTemplate.tst: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | $imports$ 4 | 5 | 6 | @NgModule({ 7 | providers: [ 8 | $moduleProviders$ 9 | ] 10 | }) 11 | export class $moduleName$ { } 12 | -------------------------------------------------------------------------------- /Templates/AureliaEntitySetService.tst: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | $imports$ 3 | 4 | import { AureliaOdataServiceBase } from '../AureliaOdataServiceBase'; 5 | 6 | export class $Name$ extends AureliaOdataServiceBase<$entityTypeName$> { 7 | $customActions$$customFunctions$ 8 | constructor() { 9 | super('$entitySetUrl$'); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Templates/AureliaModuleTemplate.tst: -------------------------------------------------------------------------------- 1 | $imports$ 2 | // Aurelia Module for '$moduleName$' 3 | // 4 | export { $moduleProviders$ }; -------------------------------------------------------------------------------- /Templates/ContextTemplate.tst: -------------------------------------------------------------------------------- 1 | // 2 | 3 | export class ODataContext { 4 | public static MetadataPath = '$metadataPath$'; 5 | public static ODataRootPath = '$odataRootPath$'; 6 | public static CreationDate = '$CreationDate$'; 7 | public static ODataVersion = '$ODataVersion$'; 8 | } 9 | -------------------------------------------------------------------------------- /Templates/CustomActionTemplate.tst: -------------------------------------------------------------------------------- 1 |  public async $actionName$($argumentWithType$): Promise<$returnType$> { 2 | return await this.$execName$<$returnType$>('$actionFullName$'$argument$); 3 | } 4 | -------------------------------------------------------------------------------- /Templates/CustomFunctionTemplate.tst: -------------------------------------------------------------------------------- 1 |  public async $functionName$($argumentWithType$): Promise<$returnType$> { 2 | return await this.$execName$('$functionFullName$'$argument$); 3 | } 4 | -------------------------------------------------------------------------------- /Templates/EntityTypeTemplate.tst: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | $imports$ 3 | export interface $Name$ { 4 | 5 | /* Navigation properties */ 6 | $navigationProperties$ 7 | /* Properties */ 8 | $properties$ 9 | } -------------------------------------------------------------------------------- /Templates/EnumMemberTemplate.tst: -------------------------------------------------------------------------------- 1 |  $memberName$ = $memberValue$, 2 | -------------------------------------------------------------------------------- /Templates/EnumTypeTemplate.tst: -------------------------------------------------------------------------------- 1 | // Created by FuryTech.ODataTypeScriptGenerator 2 | 3 | export enum $Name$ { 4 | $members$ 5 | } -------------------------------------------------------------------------------- /Templates/FieldTemplate.tst: -------------------------------------------------------------------------------- 1 |  $propertyName$: $propertyType$; 2 | -------------------------------------------------------------------------------- /Templates/ImportTemplate.tst: -------------------------------------------------------------------------------- 1 | import { $moduleNames$ } from '$relativePaths$'; 2 | -------------------------------------------------------------------------------- /Templates/NativeEntitySetService.tst: -------------------------------------------------------------------------------- 1 | // created by FuryTech.ODataTypeScriptGenerator 2 | $imports$ 3 | 4 | import { NativeOdataServiceBase } from '../NativeOdataServiceBase'; 5 | 6 | export class $Name$ extends NativeOdataServiceBase<$entityTypeName$> { 7 | $customActions$$customFunctions$ 8 | constructor() { 9 | super('$entitySetUrl$'); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Templates/NativeModuleTemplate.tst: -------------------------------------------------------------------------------- 1 | $imports$ 2 | // Native Module for '$moduleName$' 3 | // 4 | export { $moduleProviders$ }; -------------------------------------------------------------------------------- /Templates/PropertyTemplate.tst: -------------------------------------------------------------------------------- 1 |  private _$propertyName$: $propertyType$; 2 | public get $propertyName$(): $propertyType$ { 3 | return this._$propertyName$; 4 | } 5 | public set $propertyName$(value: $propertyType$) { 6 | this._$propertyName$ = value; 7 | } 8 | --------------------------------------------------------------------------------