Skip to content

ITGlobal/Fountain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fountain

Code generation library for contracts

Build status

Nuget

  • ITGlobal.Fountain.Builder
    ITGlobal.Fountain.Builder
  • ITGlobal.Fountain.Parser
    ITGlobal.Fountain.Parser
  • ITGlobal.Fountain.Annotations
    ITGlobal.Fountain.Annotations

Usage

Create contracts.

[Contract("product", "PUBLIC")] [Documentation("some description for contract")] public class Product: MetadataObject { [Documentation("Product Code")] [Required("ON_SERVER")] [ContractField("PUBLIC")] public string Code { get; set; } [Documentation("Product Name")] [ContractField("PUBLIC")] [Required("ON_SERVER")] public LocalizedText Name { get; set; } [Documentation("Product prices table")] [ContractField("MANAGER")] public Dictionary<PriceRegion, PriceDefenition> Prices { get; set; } } // abstract classes don't emit [Contract("common", "PUBLIC")] [Documentation("Метаданные")] public abstract class MetadataObject { [Documentation("Id")] [ContractField("PUBLIC"), Nullable] public string Id { get; set; } [Documentation("Some metadata")] [JsonProperty("$metadata")] [ContractField("PUBLIC")] [Nullable] public Dictionary<string, object> Metadata { get; set; } } [Contract("product", "MANAGER")] [Documentation("Price regions")] public enum PriceRegion { [Documentation("Россия")] [JsonName("RUSSIA")] [ContractField("MANAGER")] RUSSIA, [Documentation("США")] [JsonName("USA")] [ContractField("MANAGER")] USA, } [Contract("product", "MANAGER")] [Documentation("Some description of price definition")] public class PriceDefenition { [Documentation("Price")] [ContractField("MANAGER")] public float Price { get; set; } [Documentation("Price Currency")] [ContractField("MANAGER")] public string Currency { get; set; } }

[Contract("product", "PUBLIC")] - this means that Product contract belongs to product group and has PUBLIC permission. [ContractField("PUBLIC")] - this means that field is an contract field and belongs to Product contract. [Required("ON_SERVER")] - this means that field required on server when server execute validation. [JsonName("USA")] - this defines how the field is called during serialization.

Emit contracts for typescript and C#

// get assemly with contracts var assebly = typeof(Product).Assembly; // emit typescript contracts with default settings FileEmitterBuilder.Build(new TypescriptEmitterOptionsBuilder()) .SetupOptions(options => { // Filename or FileTemplate option required options.Filename = "contracts.d.ts"; // filter only public contracts options.ParserOptions.FilterContracts = attr => attr.Permission == "PUBLIC"; // filter only public fields options.ParserOptions.FilterFields = attr => attr.Permission == "PUBLIC"; }) .Emit("path/to/typescript/output/folder", assebly); // emit C# contracts with default settings FileEmitterBuilder.Build(new CsharpEmitterOptionsBuilder()) .SetupOptions(options => { // Filename or FileTemplate option required options.Filename = "Contracts.cs"; // filter only public contracts options.ParserOptions.FilterContracts = attr => attr.Permission == "PUBLIC"; // filter only public fields options.ParserOptions.FilterFields = attr => attr.Permission == "PUBLIC"; }) .Emit("path/to/C#/output/folder", assebly);

Result in contracts.d.ts

// todo

Result in Contracts.cs

using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.ComponentModel.DataAnnotations; using JetBrains.Annotations; using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Contracts { /// <summary> /// some description for contract /// </summary> public class ProductContract { /// <summary> /// Product Code /// </summary> [Required] public string Code { get; set; } /// <summary> /// Product Name /// </summary> [Required] public LocalizedText Name { get; set; } /// <summary> /// Id /// </summary> [CanBeNull] public string Id { get; set; } /// <summary> /// Some metadata /// </summary> [CanBeNull] public Dictionary<string, Object> Metadata { get; set; } } }

Options

Options setup has 2 steps.

First. Builder.

There is a possibility redefine default classes for parser and emitter.

FileEmitterBuilder.Build(new TypescriptEmitterOptionsBuilder(builder => { builder.SetParser<MyCustomParser>(); builder.SetFieldStringify<MyCustomTypescriptFieldStringify>; }))

See all available builder options here

Second. Static options

Use SetupOptions to set template for files, filtration, ident, and etc.

FileEmitterBuilder.Build(new TypescriptEmitterOptionsBuilder(builder => { builder.SetParser<MyCustomParser>(); builder.SetFieldStringify<MyCustomTypescriptFieldStringify>; })).SetupOptions((options) => { options.FieldNamingStrategy = new CamelCaseNamingStrategy(); options.ContractNameTempate = desc => $"Mgr{desc.Name}"; options.IdentSize = 4; options.Filename = "mgr-contracts.d.ts"; options.TypescriptModuleType = TypescriptModuleType.Namespace; options.Namespace = "MgrContracts"; options.ParserOptions.FilterContracts = attr => attr.Permission == ContractPermission.PUBLIC || attr.Permission == ContractPermission.MANAGER; options.ParserOptions.FilterFields = attr => attr.Permission == ContractPermission.PUBLIC || attr.Permission == ContractPermission.MANAGER; })

Options reference

Roadmap

  • Enums
  • Generics
  • Optional
  • C# builder
  • Filter by permission
  • Filter by group
  • camelCase dash_case settings
  • Modular parser
  • Get summary as description
  • Deprecation
  • Parser cache
  • Support perfile modules for typescript
  • Parser - group by base class
  • Emitter hooks
  • Tests

About

Code generation library for contracts (typescript, C#)

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors