{"id":26714668,"url":"https://github.com/dbosoft/yanco","last_synced_at":"2025-04-04T23:10:10.942Z","repository":{"id":34870334,"uuid":"152300013","full_name":"dbosoft/YaNco","owner":"dbosoft","description":".NET SAP RFC API based on SAP Netweaver RFC SDK","archived":false,"fork":false,"pushed_at":"2024-05-02T05:52:22.000Z","size":1578,"stargazers_count":120,"open_issues_count":3,"forks_count":14,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-05-02T19:35:11.045Z","etag":null,"topics":["bapi","dotnetcore","net5","sap","sapnwrfc","saprfc","yanco"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbosoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-09T18:20:01.000Z","updated_at":"2024-06-05T07:25:57.728Z","dependencies_parsed_at":"2024-03-05T22:30:01.731Z","dependency_job_id":"7352bb5d-e3f4-4b51-a437-ce7e74ee5f42","html_url":"https://github.com/dbosoft/YaNco","commit_stats":{"total_commits":188,"total_committers":5,"mean_commits":37.6,"dds":0.6276595744680851,"last_synced_commit":"9a8e28c480689a30363dc7d2c795683e696b7999"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbosoft%2FYaNco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbosoft%2FYaNco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbosoft%2FYaNco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbosoft%2FYaNco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbosoft","download_url":"https://codeload.github.com/dbosoft/YaNco/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261612,"owners_count":20910108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bapi","dotnetcore","net5","sap","sapnwrfc","saprfc","yanco"],"created_at":"2025-03-27T13:42:03.646Z","updated_at":"2025-04-04T23:10:10.917Z","avatar_url":"https://github.com/dbosoft.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# YaNco - Yet another .NET Connector\n.NET Connector for SAP Netweaver RFC\n\nStable                     |  Latest                   |\n---------------------------|---------------------------|\n[![NuGet stable](https://img.shields.io/nuget/v/Dbosoft.YaNco.svg?style=flat-square)](https://www.nuget.org/packages/Dbosoft.YaNco) | [![NuGet pre](https://img.shields.io/nuget/vpre/Dbosoft.YaNco.svg?style=flat-square)](https://www.nuget.org/packages/Dbosoft.YaNco)\n\n# This the README for version v5!\nThe readme for maintenance release v4 can be found here: https://github.com/dbosoft/YaNco/tree/support/4.3\n\n## Description\n\nThis library provides an alternative SAP .NET Connector based on the _SAP NetWeaver RFC Library_.\n\n**Features**:\n- thin, modern layer above native SAP Netweaver RFC SDK\n- DI container friendly API\n- Functional programming friendly API (using [Language.Ext](https://github.com/louthy/language-ext))\n- ABAP callbacks support (not possible with sapnco, see SAP note [2297083](https://launchpad.support.sap.com/#/notes/2297083)). \n\n\n## Platforms \u0026 Prerequisites\n\n**.NET**\n\nThe library requires .NET Framework \u003e= 4.7.1 or .NET Core 2.0 or higher. \n\n\nSupported platforms: Windows, Linux and MacOS.\n\n\n**Windows: C++ Runtimes**\n\nOn Windows the Visual Studio 2013 (VC++ 12.0) runtime library has to be installed. \nLibrary can be downloaded here: https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads\n\n\n**SAP Netweaver RFC SDK**\n\nTo use YaNco you need to obtain _SAP NW RFC SDK 750_ from _[SAP Support Portal](https://launchpad.support.sap.com/#/softwarecenter/template/products/_APP=00200682500000001943\u0026_EVENT=DISPHIER\u0026HEADER=N\u0026FUNCTIONBAR=Y\u0026EVENT=TREE\u0026TMPL=INTRO_SWDC_SP_AD\u0026V=MAINT\u0026REFERER=CATALOG-PATCHES\u0026ROUTENAME=products/By%20Category%20-%20Additional%20Components)_.\n\nA prerequisite to download is having a **customer or partner account** on _SAP Support Portal_ and if you\nare SAP employee please check [SAP Note 1037575 - Software download authorizations for SAP employees](https://launchpad.support.sap.com/#/notes/1037575).\n\n_SAP NW RFC SDK 750_ is fully backwards compatible, supporting all NetWeaver systems, from today, down to release R/3 4.6C.\nYou can therefore always use the newest version released on SAP Support Portal and connect to older systems as well.\n\n## Getting started\n\nThe easiest way to get started is by installing [the available NuGet package](https://www.nuget.org/packages/Dbosoft.YaNco). Take a look at the [Using](#using) section learning how to configure and use YaNco. Go to the [Build](#build) section to find out how to build YaNco. \n\n**Samples and articles**\n\n- [Creating a SAP DMS library with YaNco (Part 1)](https://dbosoft.eu/en-us/blog/creating-a-sap-dms-library-with-yanco-part-1)\n- [Creating a SAP DMS library with YaNco (Part 2)](https://dbosoft.eu/en-us/blog/creating-a-sap-dms-library-with-yanco-part-2)\n- [Sample app: Using YaNco in ASP.NET Core](https://github.com/dbosoft/YaNco/tree/main/samples/netcore3.1/SAPWebAPI)\n- [Sample app: Command line tool to create sales orders](https://github.com/dbosoft/YaNco/tree/main/samples/netcore3.1/CreateSalesOrder)\n- [Sample app: IDoc Receiver - Export Material Master](https://github.com/dbosoft/YaNco/tree/main/samples/net6.0/ExportMATMAS)\n- [SAPHub - How to build reliable and scaleable SAP integrated microservices with Hosuto and YaNco](https://github.com/dbosoft/SAPHub) \n\nPlease note that most samples have not yet been updated to version 5!\n\n## Using\n\n### Prepare connection\nIn order to call remote enabled ABAP function module (ABAP RFM), first a connection must be opened.\nThe connection settings have to be build from a string/string dictionary, for example from a ConfigurationBuilder.\n\n```csharp\nvar configurationBuilder =\n    new ConfigurationBuilder();\n\nconfigurationBuilder.AddUserSecrets\u003cProgram\u003e();\nvar config = configurationBuilder.Build();\n\nvar settings = new Dictionary\u003cstring, string\u003e\n{\n    {\"ashost\", config[\"saprfc:ashost\"]},\n    {\"sysnr\", config[\"saprfc:sysnr\"]},\n    {\"client\", config[\"saprfc:client\"]},\n    {\"user\", config[\"saprfc:username\"]},\n    {\"passwd\", config[\"saprfc:password\"]},\n    {\"lang\", \"EN\"}\n\n};\n```\nWith these settings you can now create a ConnectionBuilder instance and use it to build a connection builder function.\n\n```csharp\n\nvar connectionBuilder = new ConnectionBuilder(settings);\nvar connFunc = connectionBuilder.Build();\n\n```\n\nThe connection builders Build() method returns a function that can be reused to open connections. \n\nUnder the hood the ConnectionBuilder also creates also a SAPRfcRuntime instance. The SAPRfcRuntime abstracts between the SAP Netweaver RFC SDK and YaNco and encapsulates all I/O between YaNco and the RFC SDK.\n\nYou can customize the runtime on the ConnectionBuilder with the ConfigureRuntime() method. For example to add a logger:\n\n```csharp\nvar connectionBuilder = new ConnectionBuilder(connFunc)\n    .ConfigureRuntime(c =\u003e \n        c.WithLogger(new MyLogger()));\n```\n\n\u003e**Please note:** In versions below 5.0 we used the IRfcRuntime interface implemented by type RfcRuntime. IRfcRuntime and RfcRuntime are now deprecated.  \nThe new **SAPRfcRuntime** has a different concept (see below for functional IO patterns). Therefore ConfigureRuntime now configures the runtime settings used to create a new SAPRfcRuntime.\n\n### RfcContext\n\nFor classic OO usage the RfcContext is the easiest method call functions from .NET to SAP. You can open a RfcContext directly from the connection function that you build with ConnectionBuilder.Build()\n\n```csharp\n\nvar connectionBuilder = new ConnectionBuilder(settings);\nvar connFunc = connectionBuilder.Build();\n\nusing (var context = new RfcContext(connFunc))\n{\n   ...\n\n}\n```\n\nThe RfcContext will automatically open and close the connection and is disposeable.\n\n### Calling ABAP Function Modules \n\nWe provide a extension method on the RFCContext that supports a syntax similar to the ABAP call function command, except that it is using function callbacks to pass or retrieve data: \n\n- *IMPORTING* parameters are passed in the *Input* function\n- *EXPORTING* parameters are retured in the *Output* function\n- *CHANGING* and *TABLES* parameters can be used in both functions \n\n```csharp\nusing (var context = new RfcContext(connFunc))\n{\n    await context.CallFunction(\"DDIF_FIELDLABEL_GET\",\n            Input: f =\u003e f\n                .SetField(\"TABNAME\", \"USR01\")\n                .SetField(\"FIELDNAME\", \"BNAME\"),\n            Output: f =\u003e f\n                .GetField\u003cstring\u003e(\"LABEL\"))\n\n        // this is from language.ext to extract the value from a either\n        .Match(r =\u003e Console.WriteLine($\"Result: {r}\"), // should return: User Name\n            l =\u003e Console.WriteLine($\"Error: {l.Message}\"));\n}\n  ```\nThe Result of the function is a Either\u003cL,R\u003e type (see language.ext [Either left right monad](https://louthy.github.io/language-ext/LanguageExt.Core/LanguageExt/Either_L_R.htm)). The Match call at the end either writes the result (right value) or a rfc error (left value). \n\n**Structures**\n\nStructures can be set or retrieved the same way. Another example extracting company code details (you may have to change the company code if you try this example):\n\n```csharp\nusing (var context = new RfcContext(connFunc))\n{\n    await context.CallFunction(\"BAPI_COMPANYCODE_GETDETAIL\",\n            Input: f =\u003e f\n                .SetField(\"COMPANYCODEID\", \"1000\"),\n            Output: f =\u003e f\n                .MapStructure(\"COMPANYCODE_DETAIL\", s=\u003e s\n                    .GetField\u003cstring\u003e(\"COMP_NAME\"))\n        )\n        .Match(r =\u003e Console.WriteLine($\"Result: {r}\"),\n            l =\u003e Console.WriteLine($\"Error: {l.Message}\"));\n\n}\n  ```\n\nAlternatively, you can also use a LINQ syntax:\n\n```csharp\nusing (var context = new RfcContext(connFunc))\n{\n    await context.CallFunction(\"BAPI_COMPANYCODE_GETDETAIL\",\n        Input: f =\u003e f\n            .SetField(\"COMPANYCODEID\", \"1000\"),\n        Output: f =\u003e f\n            .MapStructure(\"COMPANYCODE_DETAIL\", s =\u003e\n                from name in s.GetField\u003cstring\u003e(\"COMP_NAME\")\n                select name\n            ))\n\n            .Match(r =\u003e Console.WriteLine($\"Result: {r}\"),\n                l =\u003e Console.WriteLine($\"Error: {l.Message}\"));\n\n}\n  ```\nEspecially for complex structures, the LINQ syntax is often easier to read.\n\n**Tables**\n\nGetting table results is possible by iterating over the table rows to retrieve the table structures. Here an example to extract all company code name and descriptions:\n\n```csharp\nusing (var context = new RfcContext(connFunc))\n{\n    await context.CallFunction(\"BAPI_COMPANYCODE_GETLIST\",\n            Output: f =\u003e f\n                .MapTable(\"COMPANYCODE_LIST\", s =\u003e\n                    from code in s.GetField\u003cstring\u003e(\"COMP_CODE\")\n                    from name in s.GetField\u003cstring\u003e(\"COMP_NAME\")\n                    select (code, name)))\n        .Match(\n            r =\u003e\n            {\n                foreach (var (code, name) in r)\n                {\n                    Console.WriteLine($\"{code}\\t{name}\");\n                }\n            },\n            l =\u003e Console.WriteLine($\"Error: {l.Message}\"));\n\n}\n  ```\n  \n**Input mapping**\n\nFor Input (importing / changing ) arguments you can pass the value with the methods SetField, SetStructure and SetTable or a combination of all. \nFor example to set values for a table you pass a IEnumerable to be processed to the SetTable method and provide a mapping function for each record in the IEnumerable:\n\n```csharp\nvar userNamesSearch = new string[] {\"A*\", \"B*\", \"C*\"};\n\nvar userList = await context.CallFunction(\"BAPI_USER_GETLIST\",\n    Input:f =\u003e f.SetTable(\"SELECTION_RANGE\", userNamesSearch , \n        (structure,userName) =\u003e structure\n                .SetField(\"PARAMETER\", \"USERNAME\")\n                .SetField(\"SIGN\", \"I\")\n                .SetField(\"OPTION\", \"CP\")\n                .SetField(\"LOW\", userName)\n        ),\n\n    Output: f=\u003e f.MapTable(\"USERLIST\", s=\u003es.GetField\u003cstring\u003e(\"USERNAME\"))\n).IfLeftAsync(l=\u003ethrow new Exception(l.Message));\n\nforeach (var userName in userList)\n{\n    Console.WriteLine(userName);\n}\n  ```\n\n\u003cbr/\u003e  \n\n### Functional programming usage\n\nYaNco is build to be used in [functional programming](https://en.wikipedia.org/wiki/Functional_programming). Functional programming allows you to make your code more reliable and move your code toward declarative and functional code rather than imperative.\n\nIn functional code you typical start with your own Runtime instance:\n\n```csharp\nvar runtime = SAPRfcRuntime.New();\nvar connectionEffect = new ConnectionBuilder\u003cSAPRfcRuntime\u003e(settings)\n    .Build();\n```\n\nPlease note the type argument on the `ConnectionBuilder`.  \nThe Build method now returns an IO effect (`Aff\u003cRT, IConnection\u003e`) that is not executed immediately, but only when the IO effect is called with runtime. \n\n```csharp\nvar fin = await connectionEffect.Run(runtime);\nfin.IfFail(error =\u003e error.Throw());\n```\n\nUsing this concept, you can chain multiple effects to build the call to the SAP system: \n```csharp\nusing static Dbosoft.YaNco.SAPRfc\u003cDbosoft.YaNco.Live.SAPRfcRuntime\u003e;\n\nvar call = useConnection(connectionEffect, connection=\u003e \n    from userName in callFunction(connection, \"BAPI_USER_GET_DETAIL\", f=\u003e \n        f.SetField(\"USERNAME\", \"SAP*\"), \n        f=\u003e f.GetField\u003cstring\u003e(\"USERNAME\"))\n    select userName);\n\nvar fin = await call.Run(runtime);\nfin.IfFail(error =\u003e error.Throw());\n```\n\nThe call from above is without side effects, that means it will not cause any I/O without the runtime.\n\nThe static using imports methods of `SAPRfc\u003cRT\u003e` so you can call useConnection and callFunction without any type. \nYou can also declare your own static classes where runtime is a type parameter, so you can replace SAPRfcRuntime with another runtime, e. g. for testing. \n\nYou can find a more general description of this concept in the language.ext wiki: https://github.com/louthy/language-ext/wiki/How-to-deal-with-side-effects\n\n\n### Calling functions from SAP to .NET\n\n\n**ABAP Callbacks**\n\nABAP callbacks allows the backend system to call functions on the client.  \nThere is build in support for the RFC_START_PROGRAM callback, that is used by SAP to request start of additional programs like saprfc and saphttp. \nTo register a start program callback you use the method `WithStartProgramCallback` of the `ConnectionBuilder`: \n\n```csharp\nvar connectionBuilder = new ConnectionBuilder(settings)\n    .WithStartProgramCallback(callback)\n    \n    StartProgramDelegate callback = command =\u003e\n    {\n        // validate and check the start request and start processes if necessary\n        // return ok if everything works or a error\n        return RfcErrorInfo.Ok();\n    };\n  ```\n\nYou can register also other functions using following syntax:  \n\n```csharp\nvar connectionBuilder = new ConnectionBuilder(settings)\n    .WithFunctionHandler(\"ZYANCO_SERVER_FUNCTION_1\",\n        cf =\u003e cf\n            .Input(i =\u003e\n                i.GetField\u003cstring\u003e(\"SEND\"))\n            .Process(Console.WriteLine)\n            .Reply((_, f) =\u003e f\n                .SetField(\"RECEIVE\", \"Hello from YaNco\")))\n ```\n \nIn this example a function with the name ZYANCO_SERVER_FUNCTION_1 has to exist on the backend server, with two parameters (and CHAR field SEND and a CHAR field RECEIVE). \n\nThe registered function handler consists of 3 chained steps: \n- Input mapping  \n  Extraction of values from the incoming function call and return extracted value for further processing. Any error here will stop the chain. Mapping features are the   same as in `CallFunction` output mapping.\n- Processing  \n  The extracted value will be passed as argument to the process function. In this example the input is just written to the console. \n  The process function can return a output value, that is passed to last step in chain. \n- Reply mapping  \n  The reply step sets the values of the response (same as Input mapping in `CallFunction`). If you have no reply you can also call `NoReply` to end the chain.  \n  \n\u003cbr/\u003e\n\n**RFC Servers**\n\nRFC servers can process RFC calls that have their origin in the SAP backend.  \nInstead of a opening a client connection a RFC server registers itself on the SAP system gateway. A pure RFC Server therefore needs no client connection at all.  \n\nHowever in practice also a client connection is used in most RFC Servers to obtain function and type metadata. \nYaNco supports both server only RFC Servers and RFC Servers with client connections: \n\n```csharp\n\nvar serverSettings = new Dictionary\u003cstring, string\u003e\n{\n    { \"SYSID\", _configuration[\"saprfc:sysid\"] },  // required for servers\n    { \"PROGRAM_ID\", _configuration[\"saprfc:program_id\"] },\n    { \"GWHOST\", _configuration[\"saprfc:ashost\"] },\n    { \"GWSERV\", _configuration[\"saprfc:gateway\"] },\n    { \"REG_COUNT\", \"1\" },  // number of servers\n\n};\n\nvar serverBuilder = new ServerBuilder(serverSettings)\n    .WithFunctionHandler(\n        \"ZYANCO_SERVER_FUNCTION_1\",\n\n        //build function definition\n        b =\u003e b\n            .AddChar(\"SEND\", RfcDirection.Import, 30)\n            .AddChar(\"RECEIVE\", RfcDirection.Export, 30),\n        cf =\u003e cf\n            .Input(i =\u003e\n                i.GetField\u003cstring\u003e(\"SEND\"))\n            .Process(s =\u003e\n            {\n                Console.WriteLine($\"Received message from backend: {s}\");\n                cancellationTokenSource.Cancel();\n                \n            })\n            .Reply((_, f) =\u003e f\n                .SetField(\"RECEIVE\", \"Hello from YaNco\")));\n ```\n\n\n or by lookup of function metadata from client connection: \n\n\n ```csharp\nvar serverBuilder = new ServerBuilder(serverSettings)\n.WithClientConnection(clientSettings, c =\u003e c\n    .WithFunctionHandler(\"ZYANCO_SERVER_FUNCTION_1\",\n        cf =\u003e cf\n            .Input(i =\u003e\n                i.GetField\u003cstring\u003e(\"SEND\"))\n            .Process(Console.WriteLine)\n            .Reply((_, f) =\u003e f\n                .SetField(\"RECEIVE\", \"Hello from YaNco\"))))\n ```\n\nAfter configuring the RFC Server it can be started like this: \n\n ```csharp\nusing var rfcServer = serverBuilder\n    .Build()\n    .StartOrException();\n ```\n\n**Transactional RFC**  \nTransactional RFC (tRFC) is used in SAP Systems to synchronize transactions cross system boundaries. A tRFC call is identified by a unique transaction id that has is announced to the receiving side before the actual function call is send. \n\nAssuming SAP is sending a tRFC call to your application following steps will happen during a tRFC call: \n1. **Check tRFC**  \n  In that step you save the incoming tRFC and verify if it was not allready saved before  \n\n2. **Send tRFC call**  \n   The actual call will now be send. The recipient should process the data from the call but should not process it further.  \n\n3. **Commit or Rollback**  \n   In case of a commit data can now be processed further or it has to be rolled back. \n\n4. **Confirm**  \n   Transaction is completed and can be removed or other cleanup operations can be executed. \n      \n\nTo handle these steps in a RFC Server you can register a transactional RFC handler that will be called for each of these steps: \n\n ```csharp\nvar serverBuilder = new ServerBuilder(serverSettings)\n .WithTransactionalRfc(new MyTransactionRfcHandler())\n\n // MyTransactionRfcHandler has to implement interface \n // ITransactionalRfcHandler\u003cRT\u003e\n\npublic interface ITransactionalRfcHandler\u003cRT\u003e\n{\n    Eff\u003cRT,RfcRc\u003e OnCheck( \n            IRfcHandle rfcHandle, string transactionId);\n    \n    ...\n}\n ```\n\nA sample implementation can be found in [samples/net6.0/ExportMATMAS](https://github.com/dbosoft/YaNco/tree/main/samples/net6.0/ExportMATMAS). This sample demonstrates how to receive IDocs with YaNco.  \n\n\n## Build\n\nWe use Visual Studio 2022 for building. \n\nAs explained above you have to obtain _SAP NW RFC Library 750_ from _SAP Support Portal_. \nBut the SDK is only required to run test applications, so just building works without the RFC SDK. \n\nIf you download the SDK use the x64 version and copy to DLLs from lib folder to a directory in your PATH environment variable. \n\n\n## Versioning\n\nWe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/dbosoft/YaNco/tags). \n\n## Authors\n\n* **Frank Wagner** - *Initial work* - [fw2568](https://github.com/fw2568)\n\nSee also the list of [contributors](https://github.com/Dbosoft/YaNco/contributors) who participated in this project.\n\n## Commercial support\n\nThe creators of YaNco, [dbosoft](https://www.dbosoft.eu), offer [professional support plans](https://support.dbosoft.eu/hc/en-us/articles/360021454080-YaNco-Support-Plans) which we strongly recommend for any organization using YaNco on a commercial basis. \n\nThey includes:\n\n- Prioritised resolution of any bugs. If you find a bug that’s blocking you, we’ll prioritise it and release a hot fix as soon as it’s ready.\n- Prioritised resolution and escalation of issues. If there’s a possible issue or question, we’ll prioritise dealing with it.\n- Prioritised feature requests: Get new features that are important to you added first.\n- Personalised support and guidance via email, telephone or video. Speak to one of our team for advice and best practices on how to best manage deployments.\n- Discounts on training and coaching services\n\n\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n\n## Trademark notice\n\nSAP, Netweaver are trademarks of SAP SE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbosoft%2Fyanco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbosoft%2Fyanco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbosoft%2Fyanco/lists"}