diff --git a/.gitignore b/.gitignore index 9de3e53..8978a20 100644 --- a/.gitignore +++ b/.gitignore @@ -86,4 +86,6 @@ $RECYCLE.BIN/ *.lnk -# End of https://www.gitignore.io/api/hexo,windows \ No newline at end of file +# End of https://www.gitignore.io/api/hexo,windows + +themes/** \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5b1ec09..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "themes/again"] - path = themes/again - url = https://github.com/Code-Sharp/hexo-theme-again diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..2052192 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +codesharp.net \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 98b46a1..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# CodeSharp.net -A repository for CodeSharp.net - -[![License](https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-nc-sa/4.0/) This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/). \ No newline at end of file diff --git a/_config.yml b/_config.yml deleted file mode 100644 index fda201f..0000000 --- a/_config.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Hexo Configuration -## Docs: https://hexo.io/docs/configuration.html -## Source: https://github.com/hexojs/hexo/ - -# Site -title: CodeSharp -subtitle: -description: A blog for the CodeSharp team -author: CodeSharp -language: -timezone: - -# URL -## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/' -url: http://codesharp.net -root: / -permalink: posts/:title/ -permalink_defaults: - -# Directory -source_dir: source -public_dir: public -tag_dir: tags -archive_dir: archives -category_dir: categories -code_dir: downloads/code -i18n_dir: :lang -skip_render: - -# Writing -new_post_name: :title.md # File name of new posts -default_layout: post -titlecase: false # Transform title into titlecase -external_link: true # Open external links in new tab -filename_case: 0 -render_drafts: false -post_asset_folder: false -relative_link: false -future: true -highlight: - enable: true - line_number: true - auto_detect: false - tab_replace: - -# Home page setting -# path: Root path for your blogs index page. (default = '') -# per_page: Posts displayed per page. (0 = disable pagination) -# order_by: Posts order. (Order by date descending by default) -index_generator: - path: '' - per_page: 10 - order_by: -date - -# Category & Tag -default_category: uncategorized -category_map: -tag_map: - -# Date / Time format -## Hexo uses Moment.js to parse and display date -## You can customize the date format as defined in -## http://momentjs.com/docs/#/displaying/format/ -date_format: YYYY-MM-DD -time_format: HH:mm:ss - -# Pagination -## Set per_page to 0 to disable pagination -per_page: 10 -pagination_dir: page - -# Extensions -## Plugins: https://hexo.io/plugins/ -## Themes: https://hexo.io/themes/ -theme: again - -# Deployment -## Docs: https://hexo.io/docs/deployment.html -deploy: - type: - -feed: - type: atom - path: atom.xml - limit: 20 - hub: - content: - content_limit: 140 - content_limit_delim: ' ' - diff --git a/archives/2016/06/index.html b/archives/2016/06/index.html new file mode 100644 index 0000000..019a6fa --- /dev/null +++ b/archives/2016/06/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ +
+

+ Introducing TypedAutobahn +

+ + +
+ + + + + +
+ + + diff --git a/archives/2016/index.html b/archives/2016/index.html new file mode 100644 index 0000000..019a6fa --- /dev/null +++ b/archives/2016/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ +
+

+ Introducing TypedAutobahn +

+ + +
+ + + + + +
+ + + diff --git a/archives/2018/03/index.html b/archives/2018/03/index.html new file mode 100644 index 0000000..3daf338 --- /dev/null +++ b/archives/2018/03/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ +
+

+ Non-prerelease WampSharp version +

+ + +
+ + + + + +
+ + + diff --git a/archives/2018/index.html b/archives/2018/index.html new file mode 100644 index 0000000..3daf338 --- /dev/null +++ b/archives/2018/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ +
+

+ Non-prerelease WampSharp version +

+ + +
+ + + + + +
+ + + diff --git a/archives/index.html b/archives/index.html new file mode 100644 index 0000000..7cae618 --- /dev/null +++ b/archives/index.html @@ -0,0 +1,73 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ +
+

+ Non-prerelease WampSharp version +

+ + +
+ + +
+

+ Introducing TypedAutobahn +

+ + +
+ + + + + +
+ + + diff --git a/atom.xml b/atom.xml new file mode 100644 index 0000000..543b38e --- /dev/null +++ b/atom.xml @@ -0,0 +1,76 @@ + + + CodeSharp + + + + + + 2018-03-15T03:28:00.526Z + http://codesharp.net/ + + + CodeSharp + + + + Hexo + + + Non-prerelease WampSharp version + + http://codesharp.net/posts/Non-prerelease-WampSharp-version/ + 2018-03-15T02:07:47.000Z + 2018-03-15T03:28:00.526Z + + + + + + + + <p>Yesterday I released the first non-prerelease version of <a href="http://wampsharp.net" target="_blank" rel="noopener">WampSharp</a>. + + + + + + + + + + + + + + Introducing TypedAutobahn + + http://codesharp.net/posts/introducing-typedautobahn/ + 2016-06-19T21:58:00.000Z + 2018-03-15T03:28:00.527Z + + + + + + + + <p>In this post I want to introduce a project I’ve been working on lately.</p> +<p>The project is named TypedAutobahn. It is a project that + + + + + + + + + + + + + + + + + diff --git a/css/app.css b/css/app.css new file mode 100644 index 0000000..c055f81 --- /dev/null +++ b/css/app.css @@ -0,0 +1,402 @@ +@font-face { + font-family: 'Source Code Pro'; + font-style: normal; + font-weight: 400; + src: local("Source Code Pro"), local("SourceCodePro-Regular"), url(http://7xrcp8.com1.z0.glb.clouddn.com/Source%20Code%20Pro.woff) format("woff"); } + +* { + box-sizing: border-box; } + +html, body { + height: 100%; + width: 100%; } + +html { + font-size: 16px; } + +body { + margin: 0; + font-family: PingFang SC, Verdana, Helvetica Neue, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif; + -webkit-font-smoothing: antialiased; } + +a { + text-decoration: none; + color: inherit; } + +/* https://github.com/twitter/twemoji#inline-styles */ +img.emoji { + height: 1em; + width: 1em; + margin: 0 .05em 0 .1em; + vertical-align: -0.2em; } + +.grid { + display: flex; + align-items: center; } + +.grid-item { + flex: 1; } + +.app-nav { + position: absolute; + top: 0; + right: 0; + margin: 15px; } + .app-nav a { + color: #5badf0; + text-transform: capitalize; + padding: 6px 10px; } + .app-nav .active { + background-color: #5badf0; + color: #fff; } + +.app-header { + text-align: center; } + .app-header .banner { + position: relative; + overflow: hidden; + z-index: -1024; + background-color: #f6f6f6; + background-size: cover; + background-repeat: no-repeat; } + .app-header .banner .placeholder { + padding-bottom: 33.3%; } + .app-header .banner img { + position: absolute; + top: 0; + left: 0; + width: 100%; + opacity: 0; + transition: opacity 2s linear; } + .app-header .banner img.loaded { + opacity: 1; } + .app-header .banner .banner-small { + filter: blur(50px); + -webkit-filter: blur(25px); } + .app-header .description .avatar { + width: 100px; + height: 100px; + margin-top: -50px; + border-radius: 50%; + border: 4px solid #fff; } + .app-header .description .title { + font-size: 1.875rem; + font-weight: 600; + letter-spacing: 1px; + color: #222; + margin: 0; + padding: 15px; } + .app-header .description .subtitle { + margin: 0; + letter-spacing: 1px; + font-size: .9rem; + color: #EB298C; + padding-bottom: 15px; } + .app-header .social-list { + margin: 0; + margin-top: 15px; + padding: 0; + list-style: none; } + .app-header .social-list a { + color: #5badf0; + padding: 8px 12px; } + +main.index { + max-width: 700px; + margin: 0 auto; + padding: 15px; } + main.index article { + margin-top: 45px; } + main.index .article-entry { + padding: 15px 0 30px 0; } + main.index .article-title { + margin: 0; + padding-top: 30px; + text-transform: capitalize; } + main.index .article-date { + color: #aaa; } + main.index .page-nav { + text-align: center; + margin-top: 45px; + font-size: 1.25rem; } + main.index .page-nav .page-number { + padding: 5px; + color: #5badf0; } + main.index .page-nav .current { + color: inherit; } + main.index .page-nav .extend { + padding: 0 15px; + color: #5badf0; } + +main.archive { + max-width: 500px; + padding: 90px 15px 0 15px; + margin: 0 auto; } + main.archive article { + margin-top: 30px; } + main.archive .article-title { + margin: 0; + font-size: 1.2rem; + text-transform: capitalize; } + main.archive .article-meta { + padding-left: 30px; } + main.archive .article-meta .article-date { + color: #aaa; } + main.archive .page-nav { + text-align: center; + margin-top: 90px; + font-size: 1.25rem; } + main.archive .page-nav .page-number { + padding: 5px; + color: #5badf0; } + main.archive .page-nav .current { + color: inherit; } + main.archive .page-nav .extend { + padding: 0 15px; + color: #5badf0; } + +main.post { + max-width: 700px; + margin: 0 auto; + padding: 15px; } + main.post article { + padding-top: 45px; + line-height: 1.7; } + main.post .article-entry { + margin-top: 75px; + /* * markdown it -> anchors in config.yml */ } + main.post .article-entry > h2, main.post .article-entry > h3, main.post .article-entry > h4, main.post .article-entry > h5, main.post .article-entry > h6 { + margin-bottom: 1rem; } + main.post .article-entry > h2 { + margin-top: 3rem; } + main.post .article-entry > h3 { + margin-top: 2rem; } + main.post .article-entry > h4 { + margin-top: 1.5rem; } + main.post .article-entry a { + color: #5badf0; } + main.post .article-entry a.header-anchor { + margin-right: .5rem; + display: none; } + main.post .article-entry > h2 a.header-anchor { + display: inline; } + main.post .article-entry > h3:hover .header-anchor, + main.post .article-entry > h4:hover .header-anchor, + main.post .article-entry > h5:hover .header-anchor, + main.post .article-entry > h6:hover .header-anchor { + display: inline; } + main.post .article-entry img { + max-width: 700px; } + main.post .article-title { + margin: 0; + text-align: center; + text-transform: capitalize; + padding-top: 30px; } + main.post .article-date { + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + color: #aaa; } + main.post .article-comment { + margin-top: 90px; } + +.app-footer { + height: 80px; + margin-top: 45px; + padding: 15px; + text-align: center; + color: #666; + font-size: .9rem; } + .app-footer p { + margin: 0; + padding: 3px; + font-style: italic; } + .app-footer a { + color: #666; } + +.page { + max-width: 700px; + margin: 0 auto; + padding: 15px; + padding-top: 90px; + line-height: 1.7; } + .page h1, .page h2 { + border-bottom: 1px solid #eee; + margin-top: 2.5rem; + padding-bottom: .3rem; } + .page h2 { + font-size: 1.75rem; } + .page a { + color: #5badf0; } + .page li { + margin-left: 15px; } + +.sharing { + margin: 90px 0; + padding: 15px 0; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; } + .sharing .profile .avatar { + padding: 15px; + width: 70px; + height: 70px; + border-radius: 50%; } + .sharing .profile .title { + margin: 0; + font-style: italic; + font-size: 1rem; } + .sharing .profile .subtitle { + margin: 0; + padding: 5px 0; + font-size: .8rem; + font-style: italic; + color: #999; } + .sharing .share-btns > p { + margin: 15px; + color: #EB298C; + font-style: italic; + text-transform: capitalize; } + +.code-block, .article-entry pre, .article-entry .highlight { + background: #2d2d2d; + margin: 1.6rem 0; + padding: 3rem 1.8rem; + border-style: solid; + border-width: 1px 0; + overflow: auto; + color: #ccc; + line-height: 20px; } + +.line-numbers, .article-entry .highlight .gutter pre { + color: #666; + font-size: 0.9rem; } + +.article-entry pre, .article-entry code { + font-family: "Source Code Pro", Consolas, Monaco, Menlo, monospace; } + +.article-entry code { + background: rgba(0, 0, 0, 0.07); + color: #EB298C; + padding: 2px 3px; + border-radius: 2px; } + +.article-entry pre code { + background: none; + text-shadow: none; + padding: 0; } + +.article-entry blockquote { + color: #aaa; + margin: 2.5rem 1rem; + padding: 0 0 0 30px; + border-left: 4px solid #aaa; } + .article-entry blockquote p { + margin: 0; } + +.article-entry table { + margin: 15px 0; + border-collapse: collapse; } + .article-entry table tr { + border-top: 1px solid #ccc; + background-color: #fff; } + .article-entry table th, .article-entry table td { + border: 1px solid #ddd; + padding: 6px 13px; } + +.article-entry .highlight pre { + border: none; + margin: 0; + padding: 0; } + +.article-entry .highlight table { + margin: 0; + width: auto; } + +.article-entry .highlight td { + border: none; + padding: 0; } + +.article-entry .highlight tr { + border: 0; } + +.article-entry .highlight figcaption { + font-size: 0.85em; + color: #999; + line-height: 1em; + margin-bottom: 1em; } + .article-entry .highlight figcaption a { + float: right; } + +.article-entry .highlight .gutter pre { + text-align: right; + padding-right: 20px; } + +.article-entry .highlight .line { + height: 20px; } + +pre .comment, +pre .title { + color: #999; } + +pre .variable, +pre .attribute, +pre .tag, +pre .regexp, +pre .ruby .constant, +pre .xml .tag, pre .title, +pre .xml .pi, +pre .xml .doctype, +pre .html .doctype, +pre .css .id, +pre .css .class, +pre .css .pseudo { + color: #f2777a; } + +pre .number, +pre .preprocessor, +pre .built_in, +pre .literal, +pre .params, +pre .constant { + color: #f99157; } + +pre .class, +pre .ruby .class .title, +pre .css .rules .attribute { + color: #99cc99; } + +pre .string, +pre .value, +pre .inheritance, +pre .header, +pre .ruby .symbol, +pre .xml .cdata { + color: #99cc99; } + +pre .css .hexcolor { + color: #66cccc; } + +pre .function, +pre .python .decorator, +pre .python .title, +pre .ruby .function .title, +pre .ruby .title .keyword, +pre .perl .sub, +pre .javascript .title, +pre .coffeescript .title { + color: #6699cc; } + +pre .keyword, +pre .javascript .function { + color: #cc99cc; } + +.back-to-home { + position: absolute; + top: 0; + right: 0; + margin: 15px; + padding: 8px 12px; + background-color: #5badf0; + color: #fff; + text-align: center; + font-size: .9rem; } diff --git a/images/avatar.png b/images/avatar.png new file mode 100644 index 0000000..6ce9e7e Binary files /dev/null and b/images/avatar.png differ diff --git a/images/cover.png b/images/cover.png new file mode 100644 index 0000000..ae5ea31 Binary files /dev/null and b/images/cover.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..ac4ce62 --- /dev/null +++ b/index.html @@ -0,0 +1,116 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ + +
+ avatar +

CodeSharp

+

Stronger Better Faster Sharper

+
+ + +
+ +
+ +
+

+ Non-prerelease WampSharp version +

+ +
+ +
+ + +
+ +
+

+ Introducing TypedAutobahn +

+ +
+ +
+ + +
+ + + + +
+ + + + + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..0c1b1d9 --- /dev/null +++ b/js/app.js @@ -0,0 +1,29 @@ +var app = (function () { + var loadBanner = function () { + var bannerSmall = document.querySelector('.banner-small') + + // can't just listen the bannerSmall's load event + // but why ? + var img = new Image() + img.src = bannerSmall.src + img.addEventListener('load', function (e) { + bannerSmall.classList.add('loaded') + }, false) + + var bannerLarge = new Image() + bannerLarge.src = bannerSmall.dataset.src + bannerLarge.addEventListener('load', function (e) { + e.target.classList.add('loaded') + }, false) + + bannerSmall.parentNode.appendChild(bannerLarge) + } + + return { + loadBanner: loadBanner + } +})() + +window.addEventListener('load', function (e) { + app.loadBanner() +}, false) diff --git a/package.json b/package.json deleted file mode 100644 index 89fb9d2..0000000 --- a/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "hexo-site", - "version": "0.0.0", - "private": true, - "hexo": { - "version": "3.6.0" - }, - "dependencies": { - "hexo": "^3.2.0", - "hexo-generator-archive": "^0.1.4", - "hexo-generator-category": "^0.1.3", - "hexo-generator-feed": "^1.2.2", - "hexo-generator-index": "^0.2.0", - "hexo-generator-tag": "^0.2.0", - "hexo-renderer-ejs": "^0.3.0", - "hexo-renderer-markdown-it": "^3.4.1", - "hexo-renderer-marked": "^0.3.0", - "hexo-renderer-sass": "^0.3.2", - "hexo-renderer-stylus": "^0.3.1", - "hexo-server": "^0.2.0", - "hexo-tag-rtl": "0.0.3", - "markdown-it-emoji": "^1.4.0", - "twemoji": "^2.5.1" - } -} diff --git a/posts/Non-prerelease-WampSharp-version/index.html b/posts/Non-prerelease-WampSharp-version/index.html new file mode 100644 index 0000000..3eadc1e --- /dev/null +++ b/posts/Non-prerelease-WampSharp-version/index.html @@ -0,0 +1,113 @@ + + + + + Non-prerelease WampSharp version | CodeSharp + + + + + + + + + + + + +
+
+

+ Non-prerelease WampSharp version +

+ + + +
+

Yesterday I released the first non-prerelease version of WampSharp. This was requested and discussed by the community in this issue.

+

I thought to take this opportunity to write a bit about this open source project, and my journey in the WAMP world.

+

I began working on WampSharp in April 2013. I looked for a WebSocket subprotocol which supports both RPC and PubSub, and came across this answer on StackOverflow. The first version was released around July 2013 and contained WAMP v1 support for both server and client sides. During its first year, the project did not receive almost any attention from the community.

+

Around December 2013, work on WAMP v2 spec began. Around late September 2014, the first WampSharp version supporting WAMP v2 was released. Since then, I’ve released every year at least one major WampSharp version, and several hotfix versions, summing up to 53 versions. Usually the annual major version tries to catch up with Crossbar.io.

+

Community

Nowadays, WampSharp has dozens of users, spread all over the world. A lot of WampSharp’s development is due to the community. This involves some features (mainly authentication features), bug reporting and bug fixes. There were several times where community members helped me figure out how to reproduce a previously reported bug.

+

Contribution to other open source projects

WampSharp’s presence made me and others contribute to other non-WAMP related projects, as some of the issues filed for WampSharp turned out to be issues of other libraries. These include feature requests and issue filing for WebSockets libraries, and sometimes even pull requests to resolve these! Beside these, I submitted various pull requests for LibLog and also filed issues for the .NET MessagePack implementation, and even for Mono and IIS Express! These were all found via WampSharp related scenarios.

+

I also tried to contribute to the WAMP ecosystem in various ways. These include providing a C# template to Crossbar.io, providing type declarations for AutobahnJS (the most popular JavaScript implementation of WAMP), providing WAMP messages parsing code for a Firefox developer extension. I also created a project called meta-wamp which provides WAMP messages declaration files, from which one can generate a WAMP related library.

+

Bringing WampSharp features to other languages

In my opinion, the reflection based roles are among the nicest features WampSharp has to offer. I tried mimicking this in other languages. One attempt was the TypedAutobahn project, which, unfortunately, was never completed. A couple months ago, I submitted an initial reflection based features pull request to autobahn-java, which was merged. Hopefully, this feature will be useful for WAMP Java developers.

+

Future

It seems that WAMPv2 has kind of staled, and that the most critical period of its development was around 2014-2015. Hopefully, .NET Core has staled, and I won’t have to make any more crazy changes in order to keep supporting this platform. I do plan to continue maintaining WampSharp, which includes answering questions and handling issues on GitHub. I hope I’ll be able to release at least one major version per year.

+ +
+
+ +
+
+ avatar +
+

CodeSharp

+

Stronger Better Faster Sharper

+
+
+ + +
+ + + +
+ + + diff --git a/posts/introducing-typedautobahn/index.html b/posts/introducing-typedautobahn/index.html new file mode 100644 index 0000000..01e2c4d --- /dev/null +++ b/posts/introducing-typedautobahn/index.html @@ -0,0 +1,144 @@ + + + + + Introducing TypedAutobahn | CodeSharp + + + + + + + + + + + + +
+
+

+ Introducing TypedAutobahn +

+ + + +
+

In this post I want to introduce a project I’ve been working on lately.

+

The project is named TypedAutobahn. It is a project that aims to bring strongly typed programming style for WAMP in TypeScript.

+

I don’t intend to write here much about WAMP. WAMP (not to be confused with Windows Apache MySQL PHP) is a protocol that provides patterns of Remote Procedure Call and Publish/Subscribe. WAMP usually runs over WebSocket + JSON, but other options exist as well (such as RawSocket and MsgPack). WAMP has various implementations in various languages.

+

I have written a C# implementation for WAMP, which provides both client and router support, it is called WampSharp.

+

WampSharp reflection based-api

One of the features WampSharp provides, is some reflection-based api for the WAMP roles. The api reminds a bit WCF’s ServiceContracts. For instance, in order in to call a procedure, we define the following contract:

+
1
2
3
4
5
public interface ICalculatorProxy
{
[WampProcedure("com.arguments.add2")]
Task<int> Add2Async(int a, int b);
}
+

and then request a proxy for it and call the procedure:

1
2
3
4
5
6
ICalculatorProxy proxy =
channel.RealmProxy.Services.GetCalleeProxy<ICalculatorProxy>();

int five = await proxy.Add2Async(2, 3);

Console.WriteLine($"Result: {five}");

+

(This code isn’t complete, I am omitting for clarity the code that setups the WampChannel object denoted as the channel variable).

+

Similarly, registering a procedure is done in the following way:

+

Define a contract and implement it:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface ICalculator
{
[WampProcedure("com.arguments.add2")]
int Add2(int a, int b);
}

public interface Calculator : ICalculator
{
public int Add2(int a, int b)
{
return (a + b);
}
}
+

then register an instance of it:

+
1
2
3
4
5
6
ICalculator instance = new Calculator();

IWampRealmProxy realm = channel.RealmProxy;

IAsyncDisposable disposable =
await channel.RealmProxy.Services.RegisterCallee(instance).ConfigureAwait(false);
+

Similar features are available also for publisher and subscriber roles. (see also documentation)

+

AutobahnJS

AutobahnJS is a WAMP client library written in JavaScript. It runs both on Node.js and browsers. It has been written and maintained by the Crossbar.io team which consists of the people who have created WAMP. AutobahnJS is very popular among WAMP implementations.

+

Lets review how the preceding samples look using AutobahnJS:

+

Procedure call:

1
2
3
4
5
session.call('com.arguments.add2', [2, 3]).then(
function (res) {
console.log("Result:", res);
}
);

+

Procedure registration:

1
2
3
4
5
function add2(args) {
return args[0] + args[1];
}

session.register('com.arguments.add2', add2);

+

As before, similar api exists for Publish/Subscribe roles.

+

The problem

Although AutobahnJS api is very simple, it might be challenging to consume services which have a large domain.

+

Suppose you have written a service that takes a use of lot of contracts in C#. Suppose that now you want to consume that service from JavaScript. It might be challenging to be familiar with all service aspects from JavaScript, since JavaScript is a dynamic-typed language, i.e. has no “hard-coded types”, and therefore you don’t have intellisense.

+

So you might consider using TypeScript, which allows you to define types and interfaces and enjoy advantages of static-typed languages (such as intellisense) for JavaScript programming.

+

Luckily, there exist type declarations for AutobahnJS that give intellisense for AutobahnJS (These declarations were mostly written by me). These give intellisense for AutobahnJS, but don’t help you consume your services.

+

It would be nice if we could just “export” our domain written C# to TypeScript, so we could immediately start consuming our services from TypeScript. This is what TypedAutobahn attempts to achieve.

+

TypedAutobahn

TypedAutobahn currently consists of two parts: a (relatively small) TypeScript library which consists of types and methods that are been used by generated code, and a code generator written in C# which generates code based on given contracts.

+

For instance, suppose we have the following contract in C#:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IArgumentsService
{
[WampProcedure("com.arguments.ping")]
void Ping();

[WampProcedure("com.arguments.add2")]
int Add2(int a, int b);

[WampProcedure("com.arguments.stars")]
string Stars(string nick = "somebody", int stars = 0);

[WampProcedure("com.arguments.orders")]
string[] Orders(string product, int limit = 5);
}

+

Running the code generator for this contract yields some code which contains the following contracts:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface IArgumentsService {
ping(): When.Promise<void> | void;

add2(a : number, b : number): When.Promise<number> | number;

stars(nick? : string, stars? : number): When.Promise<string> | string;

orders(product : string, limit? : number): When.Promise<string[]> | string[];
}

interface IArgumentsServiceProxy {
ping(): When.Promise<void>;

add2(a : number, b : number): When.Promise<number>;

stars(nick? : string, stars? : number): When.Promise<string>;

orders(product : string, limit? : number): When.Promise<string[]>;
}
+

A class named IArgumentsServiceProvider which allows us to consume the services is also generated.

+

Consuming caller services with TypedAutobahn has the following form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let serviceProvider = new IArgumentsServiceProvider(session);

let proxy = serviceProvider.getCalleeProxy();

proxy.ping().then(() => console.log("Pinged!"));
proxy.add2(2, 3).then(res => console.log("Add2:", res));

proxy.stars().then(res => console.log("Starred 1:", res));
proxy.stars("Homer").then(res => console.log("Starred 2:", res));
proxy.stars(null, 5).then(res => console.log("Starred 3:", res));
proxy.stars("Homer", 5).then(res => console.log("Starred 4:", res));

proxy.orders("coffee").then(res => "Orders 1:", res);
proxy.orders("coffee", 10).then(res => "Orders 2:", res);

+

The nice thing is that we have intellisense - the editor gives us auto-completion for proxy methods and for their return values. Also, we don’t need to be worried about the WAMP procedure uris - these are specified in the generated code. The sample here is rather simple, but the generator also generates contracts for composite types your methods receive/return.

+

This is even more incredible than it looks: if we’re targeting Node.js, we can use async/await:

1
2
var five = await proxy.add2(2, 3);
console.log("Add2: ", five);

+

Similarly, we can register WAMP procedures using the IArgumentsServiceProvider. Consider this implementation for instance:

+
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
class ArgumentsServiceCallee implements IArgumentsService {
private _orders: number[];

constructor() {
this._orders = [];

for (let i = 0; i < 50; i++) {
this._orders.push(i);
}
}

ping(): void {
}

add2(a: number, b: number): number {
return (a + b);
}

stars(nick: string = "somebody", stars: number = 0): string {
return (nick + " starred " + stars + "x");
}

orders(product: string, limit: number = 5): string[] {
return this._orders.slice(0, limit);
}
}
+

We simply register it using

+
1
2
3
4
let serviceProvider = new IArgumentsServiceProvider(session);
let instance = new ArgumentsServiceCallee();
let promise = serviceProvider.registerCallee(instance);
promise.then(() => console.log("all registered!"));
+

This registers all methods of the IArgumentsService contract, using the procedure uris specified in the C# code. Note that the methods no longer receive an arguments array that needs to be manually unpacked, but TypedAutobahn unpacks it automatically: first it searches for positional arguments, and if those aren’t present, it searches for keyword arguments having the names of the method arguments. If none of these are found, the default value specified is used.

+

A similar mechanism which mimics WampSharp’s reflection-based subscriber exists for subscribers.

+

Current status

I made the TypedAutobahn repository public not long ago. You can find it on GitHub.
There are a few things that are missing: regarding features, there is currently no support for publisher role.
Regarding other stuff: some work on deployment needs to be done: the project currently targets Node (since it uses export/import syntax). A build that creates a version that is browser-friendly should be set. Also, a package for npm/bower/NuGet should be created and published automatically on builds.
I should probably open GitHub issues regarding these. Any help on these or on anything else would be appreciated!

+

Future

TypedAutobahn is cool, but it is very limiting, since it requires you to have C# code representing your WAMP service contracts. It would be awesome if we could be able to generate code for WAMP service contracts, regardless the language they are written in. This should be possible in the future, since WAMP has reflection on its roadmap (See also these links: #1 #2 #3 #4).
This feature should allow to generate code representing a WAMP service contract of a living contract. Once it would be present, the current code generator could be replaced with a new code generator (probably written in JavaScript/TypeScript) which allows to generate code to many target languages regardless of the language the original service was written in.

+ +
+
+ +
+
+ avatar +
+

CodeSharp

+

Stronger Better Faster Sharper

+
+
+ + +
+ + + +
+ + + diff --git a/scaffolds/draft.md b/scaffolds/draft.md deleted file mode 100644 index 498e95b..0000000 --- a/scaffolds/draft.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: {{ title }} -tags: ---- diff --git a/scaffolds/page.md b/scaffolds/page.md deleted file mode 100644 index f01ba3c..0000000 --- a/scaffolds/page.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: {{ title }} -date: {{ date }} ---- diff --git a/scaffolds/post.md b/scaffolds/post.md deleted file mode 100644 index 1f9b9a4..0000000 --- a/scaffolds/post.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: {{ title }} -date: {{ date }} -tags: ---- diff --git a/source/_posts/Non-prerelease-WampSharp-version.md b/source/_posts/Non-prerelease-WampSharp-version.md deleted file mode 100644 index bc1fdfe..0000000 --- a/source/_posts/Non-prerelease-WampSharp-version.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Non-prerelease WampSharp version -date: 2018-03-14 22:07:47 -tags: - - WampSharp - - WAMP ---- -Yesterday I released the first non-prerelease version of [WampSharp](http://wampsharp.net). This was requested and discussed by the community in this [issue](https://github.com/Code-Sharp/WampSharp/issues/237). - -I thought to take this opportunity to write a bit about this open source project, and my journey in the WAMP world. - -I began working on WampSharp in April 2013. I looked for a WebSocket subprotocol which supports both RPC and PubSub, and came across [this answer on StackOverflow](https://stackoverflow.com/a/10882808). The first version [was released](https://groups.google.com/d/msg/wampws/dR2j0U6E5m4/ijkrlHCgbF0J) around July 2013 and contained [WAMP v1](https://web.archive.org/web/20130511044655/http://wamp.ws:80/spec) support for both server and client sides. During its first year, the project did not receive almost any attention from the community. - -Around December 2013, work on [WAMP v2 spec](https://groups.google.com/d/msg/wampws/7KykR53SP1w/kzoIWV5JOP8J) began. Around late September 2014, the first WampSharp version supporting [WAMP v2](http://wamp-proto.org/spec/) was [released](https://groups.google.com/d/msg/wampws/lLxrrRYDozw/DVLx31-p7sAJ). Since then, I've released every year at least one major WampSharp version, and several hotfix versions, summing up to 53 versions. Usually the annual major version tries to catch up with [Crossbar.io](https://crossbar.io). - -### Community - -Nowadays, WampSharp has dozens of users, spread all over the world. A lot of WampSharp's development is due to the community. This involves some features (mainly authentication features), bug reporting and bug fixes. There were [several times](https://github.com/Code-Sharp/WampSharp/issues/92) where community members [helped me](https://gist.github.com/darkl/28380eced333ac8ff0fcc4df6cb2f21e#gistcomment-1975910) figure out how to reproduce a previously reported bug. - -### Contribution to other open source projects - -WampSharp's presence made me and others contribute to other non-WAMP related projects, as some of the issues filed for WampSharp turned out to be issues of other libraries. These include [feature requests](https://github.com/statianzo/Fleck/issues/70) and [issue filing](https://github.com/vtortola/WebSocketListener/issues/47) for WebSockets libraries, and sometimes even [pull requests](https://github.com/kerryjiang/WebSocket4Net/pull/41) to resolve these! Beside these, I submitted [various pull requests](https://github.com/damianh/LibLog/pulls?q=is%3Apr+author%3Adarkl+is%3Aclosed) for LibLog and also filed issues for the [.NET MessagePack implementation](https://github.com/msgpack/msgpack-cli/issues/39), and even [for Mono](https://bugzilla.xamarin.com/show_bug.cgi?id=13110) and [IIS Express](https://github.com/aspnet/AspNetKatana/issues/155)! These were all found via WampSharp related scenarios. - -I also tried to contribute to the WAMP ecosystem in various ways. These include providing a [C# template](https://github.com/crossbario/crossbar/pull/135) to Crossbar.io, providing [type declarations](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/3956) for [AutobahnJS](https://github.com/crossbario/autobahn-js) (the most popular JavaScript implementation of WAMP), providing WAMP messages parsing code for a [Firefox developer extension](https://github.com/firebug/websocket-monitor/issues/32). I also created a project called [meta-wamp](https://github.com/darkl/meta-wamp) which provides WAMP messages declaration files, from which one can generate a WAMP related library. - -### Bringing WampSharp features to other languages - -In my opinion, the [reflection based roles](http://wampsharp.net/tags/reflection/) are among the nicest features WampSharp has to offer. I tried mimicking this in other languages. One attempt was {% post_link introducing-typedautobahn the TypedAutobahn project %}, which, unfortunately, was never completed. A couple months ago, I submitted an initial reflection based features [pull request](https://github.com/crossbario/autobahn-java/pull/356) to [autobahn-java](https://github.com/crossbario/autobahn-java), which was merged. Hopefully, this feature will be useful for WAMP Java developers. - -### Future - -It seems that WAMPv2 has kind of staled, and that the most critical period of its development was around 2014-2015. Hopefully, .NET Core has staled, and I won't have to make any more crazy changes in order to keep supporting this platform. I do plan to continue maintaining WampSharp, which includes answering questions and handling issues on GitHub. I hope I'll be able to release at least one major version per year. \ No newline at end of file diff --git a/source/_posts/introducing-typedautobahn.md b/source/_posts/introducing-typedautobahn.md deleted file mode 100644 index b8999c9..0000000 --- a/source/_posts/introducing-typedautobahn.md +++ /dev/null @@ -1,242 +0,0 @@ -title: Introducing TypedAutobahn -date: 2016/06/19 17:58:00 -tags: -- TypeScript -- TypeAutobahn -- WAMP -- WampSharp ---- -In this post I want to introduce a project I've been working on lately. - -The project is named TypedAutobahn. It is a project that aims to bring strongly typed programming style for [WAMP](http://wamp-proto.org/) in [TypeScript](http://www.typescriptlang.org). - -I don't intend to write here much about WAMP. [WAMP](http://wamp-proto.org/) (not to be confused with [Windows Apache MySQL PHP](http://www.wampserver.com/en/)) is a protocol that provides patterns of Remote Procedure Call and Publish/Subscribe. WAMP usually runs over WebSocket + JSON, but other options exist as well (such as RawSocket and MsgPack). WAMP has various implementations in various languages. - -I have written a C# implementation for WAMP, which provides both client and router support, it is called [WampSharp](http://github.com/Code-Sharp/WampSharp). - -#### WampSharp reflection based-api - -[MSDN]: https://msdn.microsoft.com/en-us/library/bb412178(v=vs.110).aspx - -One of the features WampSharp provides, is some reflection-based api for the WAMP roles. The api reminds a bit [WCF's ServiceContracts][MSDN]. For instance, in order in to call a procedure, we define the following contract: - -```csharp -public interface ICalculatorProxy -{ - [WampProcedure("com.arguments.add2")] - Task Add2Async(int a, int b); -} -``` - -and then request a proxy for it and call the procedure: -```csharp -ICalculatorProxy proxy = - channel.RealmProxy.Services.GetCalleeProxy(); - -int five = await proxy.Add2Async(2, 3); - -Console.WriteLine($"Result: {five}"); -``` - -(This code isn't complete, I am omitting for clarity the code that setups the WampChannel object denoted as the channel variable). - -Similarly, registering a procedure is done in the following way: - -Define a contract and implement it: - -```csharp -public interface ICalculator -{ - [WampProcedure("com.arguments.add2")] - int Add2(int a, int b); -} - -public interface Calculator : ICalculator -{ - public int Add2(int a, int b) - { - return (a + b); - } -} -``` - -then register an instance of it: - -```csharp -ICalculator instance = new Calculator(); - -IWampRealmProxy realm = channel.RealmProxy; - -IAsyncDisposable disposable = - await channel.RealmProxy.Services.RegisterCallee(instance).ConfigureAwait(false); -``` - -Similar features are available also for [publisher](http://wampsharp.net/wamp2/roles/publisher/reflection-based-publisher/) and [subscriber](http://wampsharp.net/wamp2/roles/subscriber/reflection-based-subscriber/) roles. ([see also documentation](http://wampsharp.net/)) - -#### AutobahnJS - -[AutobahnJS](http://github.com/crossbario/AutobahnJS) is a WAMP client library written in JavaScript. It runs both on [Node.js](https://nodejs.org/) and browsers. It has been written and maintained by the [Crossbar.io team](http://crossbar.io/) which consists of the people who have created WAMP. AutobahnJS is very popular among WAMP implementations. - -Lets review how the preceding samples look using AutobahnJS: - -Procedure call: -```javascript -session.call('com.arguments.add2', [2, 3]).then( - function (res) { - console.log("Result:", res); - } -); -``` - -Procedure registration: -```javascript -function add2(args) { - return args[0] + args[1]; -} - -session.register('com.arguments.add2', add2); -``` - -As before, similar api exists for Publish/Subscribe roles. - -#### The problem -Although AutobahnJS api is very simple, it might be challenging to consume services which have a large domain. - -Suppose you have written a service that takes a use of lot of contracts in C#. Suppose that now you want to consume that service from JavaScript. It might be challenging to be familiar with all service aspects from JavaScript, since JavaScript is a dynamic-typed language, i.e. has no "hard-coded types", and therefore you don't have intellisense. - -So you might consider using [TypeScript](http://www.typescriptlang.org), which allows you to define types and interfaces and enjoy advantages of static-typed languages (such as intellisense) for JavaScript programming. - -Luckily, there exist [type declarations for AutobahnJS](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/autobahn/index.d.ts) that give intellisense for AutobahnJS (These declarations were mostly written by me). These give intellisense for AutobahnJS, but don't help you consume your services. - -It would be nice if we could just "export" our domain written C# to TypeScript, so we could immediately start consuming our services from TypeScript. This is what TypedAutobahn attempts to achieve. - -#### TypedAutobahn - -TypedAutobahn currently consists of two parts: a (relatively small) TypeScript library which consists of types and methods that are been used by generated code, and a code generator written in C# which generates code based on given contracts. - -For instance, suppose we have the following contract in C#: -```csharp -public interface IArgumentsService -{ - [WampProcedure("com.arguments.ping")] - void Ping(); - - [WampProcedure("com.arguments.add2")] - int Add2(int a, int b); - - [WampProcedure("com.arguments.stars")] - string Stars(string nick = "somebody", int stars = 0); - - [WampProcedure("com.arguments.orders")] - string[] Orders(string product, int limit = 5); -} -``` - -Running the code generator for this contract yields some code which contains the following contracts: - -```typescript -interface IArgumentsService { - ping(): When.Promise | void; - - add2(a : number, b : number): When.Promise | number; - - stars(nick? : string, stars? : number): When.Promise | string; - - orders(product : string, limit? : number): When.Promise | string[]; -} - -interface IArgumentsServiceProxy { - ping(): When.Promise; - - add2(a : number, b : number): When.Promise; - - stars(nick? : string, stars? : number): When.Promise; - - orders(product : string, limit? : number): When.Promise; -} -``` - -A class named IArgumentsServiceProvider which allows us to consume the services is also generated. - -Consuming caller services with TypedAutobahn has the following form: -```typescript -let serviceProvider = new IArgumentsServiceProvider(session); - -let proxy = serviceProvider.getCalleeProxy(); - -proxy.ping().then(() => console.log("Pinged!")); -proxy.add2(2, 3).then(res => console.log("Add2:", res)); - -proxy.stars().then(res => console.log("Starred 1:", res)); -proxy.stars("Homer").then(res => console.log("Starred 2:", res)); -proxy.stars(null, 5).then(res => console.log("Starred 3:", res)); -proxy.stars("Homer", 5).then(res => console.log("Starred 4:", res)); - -proxy.orders("coffee").then(res => "Orders 1:", res); -proxy.orders("coffee", 10).then(res => "Orders 2:", res); -``` - -The nice thing is that we have intellisense - the editor gives us auto-completion for proxy methods and for their return values. Also, we don't need to be worried about the WAMP procedure uris - these are specified in the generated code. The sample here is rather simple, but the generator also generates contracts for composite types your methods receive/return. - -This is even more incredible than it looks: if we're targeting Node.js, we can use [async/await](https://blogs.msdn.microsoft.com/typescript/2015/11/03/what-about-asyncawait/): -```typescript -var five = await proxy.add2(2, 3); -console.log("Add2: ", five); -``` - -Similarly, we can register WAMP procedures using the IArgumentsServiceProvider. Consider this implementation for instance: - -```typescript -class ArgumentsServiceCallee implements IArgumentsService { - private _orders: number[]; - - constructor() { - this._orders = []; - - for (let i = 0; i < 50; i++) { - this._orders.push(i); - } - } - - ping(): void { - } - - add2(a: number, b: number): number { - return (a + b); - } - - stars(nick: string = "somebody", stars: number = 0): string { - return (nick + " starred " + stars + "x"); - } - - orders(product: string, limit: number = 5): string[] { - return this._orders.slice(0, limit); - } -} - -``` - -We simply register it using - -```typescript -let serviceProvider = new IArgumentsServiceProvider(session); -let instance = new ArgumentsServiceCallee(); -let promise = serviceProvider.registerCallee(instance); -promise.then(() => console.log("all registered!")); -``` - -This registers all methods of the IArgumentsService contract, using the procedure uris specified in the C# code. Note that the methods no longer receive an arguments array that needs to be manually unpacked, but TypedAutobahn unpacks it automatically: first it searches for positional arguments, and if those aren't present, it searches for keyword arguments having the names of the method arguments. If none of these are found, the default value specified is used. - -A similar mechanism which mimics [WampSharp's reflection-based subscriber](http://wampsharp.net/wamp2/roles/subscriber/reflection-based-subscriber/) exists for subscribers. - -#### Current status - -I made the TypedAutobahn repository public not long ago. You can find it [on GitHub](http://github.com/darkl/TypedAutobahn). -There are a few things that are missing: regarding features, there is currently no support for publisher role. -Regarding other stuff: some work on deployment needs to be done: the project currently targets Node (since it uses export/import syntax). A build that creates a version that is browser-friendly should be set. Also, a package for npm/bower/NuGet should be created and published automatically on builds. -I should probably open GitHub issues regarding these. Any help on these or on anything else would be appreciated! - -#### Future - -TypedAutobahn is cool, but it is very limiting, since it requires you to have C# code representing your WAMP service contracts. It would be awesome if we could be able to generate code for WAMP service contracts, regardless the language they are written in. This should be possible in the future, since WAMP has [reflection](https://github.com/tavendo/WAMP/issues/61) on its roadmap (See also these links: [#1](https://groups.google.com/forum/#!searchin/wampws/swagger/wampws/5Z2o25vx9nQ/1CR1LaSmKawJ) [#2](https://groups.google.com/forum/#!msg/wampws/jW_6UZYBhpQ/u8MQ70NMzrYJ) [#3](https://github.com/crossbario/crossbar/blob/master/DEVELOPERS.md) [#4](https://github.com/crossbario/crossbar/issues/301)). -This feature should allow to generate code representing a WAMP service contract of a living contract. Once it would be present, the current code generator could be replaced with a new code generator (probably written in JavaScript/TypeScript) which allows to generate code to many target languages regardless of the language the original service was written in. \ No newline at end of file diff --git a/tags/TypeAutobahn/index.html b/tags/TypeAutobahn/index.html new file mode 100644 index 0000000..019a6fa --- /dev/null +++ b/tags/TypeAutobahn/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/tags/TypeScript/index.html b/tags/TypeScript/index.html new file mode 100644 index 0000000..019a6fa --- /dev/null +++ b/tags/TypeScript/index.html @@ -0,0 +1,62 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ + + + + + + +
+ + + diff --git a/tags/WAMP/index.html b/tags/WAMP/index.html new file mode 100644 index 0000000..7b0b070 --- /dev/null +++ b/tags/WAMP/index.html @@ -0,0 +1,73 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + diff --git a/tags/WampSharp/index.html b/tags/WampSharp/index.html new file mode 100644 index 0000000..7b0b070 --- /dev/null +++ b/tags/WampSharp/index.html @@ -0,0 +1,73 @@ + + + + + CodeSharp + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + diff --git a/themes/again b/themes/again deleted file mode 160000 index eae4ec8..0000000 --- a/themes/again +++ /dev/null @@ -1 +0,0 @@ -Subproject commit eae4ec87a371ccb24fb759df958488f6e8675f6b