Create a SPA static serverless application with F# - f#

What I am trying to do is to write an SPA application in F#. Is it possible to use Fable without the full tooling, just only as F# to html+javascript compiler?
Ideally I would like to be able to compile one or more F# files into a static html+javascript markup and send it straight to the browser from F# interactive, without any web server.
The typical workflow is:
1) Create new project from template
2) Modify project files
3) Build
4) Open browser and point to specific url
What I would like to do is something like (from F# interactive):
let html = Fable.compile([fileXYZ.fs])
do XPlot.Plotly.Html.showInBrowser html "pageid"
Is this possible?
How can I do it?

I have asked for the same in the past as sometimes the requirement is just to transpile a single file (Azure DevOps extensions for example).
Sadly, the current answer is "no".
The question is still open today: https://github.com/fable-compiler/Fable/issues/1369
People have build prototypes: https://github.com/TheAngryByrd/fantasy
But I don't think you can answer with a "yes" at this time.
I hope this helps.

Related

Resx in Blazor WASM: What is "the issue" with the old static way of using the Resx Files?

[Disclaimer: I'm a long-time Desktop developer slowly learning Web and Blazor, so might be a noob question] but,
How come, when you try to find best-practice for doing Localization in Blazor you are told from official MS Docs (https://learn.microsoft.com/en-us/aspnet/core/blazor/globalization-localization?view=aspnetcore-5.0&pivots=webassembly) and various blogs to do the following:
Add NuGet Package: Microsoft.Extensions.Localization
Register localization "builder.Services.AddLocalization();"
Add your resx Files
Make IStringLocalizer (#inject IStringLocalizer Loc)
And finally use the following in your razor pages: #Loc["Greeting"]
Sure above works, but to a Desktop developer, this feels like a massive step-back in quality and "refactor-safeness" and the new way to use "magic strings" to reference the translations.
I've tested, and the "old way" on a Blazor Page of just:
Adding a MyResource.resx
Let it use the custom tool "PublicResXFileCodeGenerator" to make the .designer file
Simply reference the translation using MyResource.MyTranslationKey;
It works, it is refactor-safe, no need for an injection or NuGet packages... It just works, but despite that, it is not the recommended way... My question is why not? What is the drawback (all the blog and documentation fail to say why the new way is better)
I think there are a number of disadvantages using PublicResXFileCodeGenerator, which may have led to the current recommendations on how to support i18n-capabilities in [blazor-]apps.
Note that this is just a list of reasons I personally came up with finding possible causes which may have led to the current recommendations:
A: Visual Studio exclusivness
The way how PublicResXFileCodeGenerator generates files seem to be VisualStudio exclusive. Today´s teams tend to use a variety of IDEs / editor to build software, (f.e. VS, VSCode, Rider, WebStorm, etc.).
At least from my perception over the last couple of years
using IStringLocalizer works for all editors, even notepad or vim.
B: no default fallback
With the recommended way of accessing a translation, there will always be a useful fallback which is provided in markup. That is not the case when using the generated types to access translation-units.
C: no builtin-support for interpolation
Using IStringLocalizer, there is a built-in, lightweight and formalized way for utilizing interpolated strings. It even encourages using such strings in favor of manually building together such values, which is considered bad-practice when translating software.
DO:
#inject IStringLocalizer<DemoPage> L
<h1>#L["Greetings, {0}", userName]</h1> <!--Greetings, Arthur-->
#code {
string userName = "Arthur";
}
DON´T:
<h1>#DemoPageRessources.Greeting #userName</h1> <!--Greetings Arthur-->
#code {
string userName = "Arthur";
}
this dictates the order of strings, which might be OK for one language, but not for another. Achieving this with the generated type is a bit more verbose, and even may lead to runtime-exceptions, when there is no actual translation, i guess.

How to securely embed the F# compiler in a asp.net web app

I am developing a asp.net web app enabling users to submit F# code, which should be dynamically compiled and executed on the server. I was thinking of either hosting the F# compiler in the web app using the approach shown here:
https://fsharp.github.io/FSharp.Compiler.Service/compiler.html
Or use F# interactive: http://fsharp.github.io/FSharp.Compiler.Service/interactive.html
The idea would be to dynamically compile the F# code and then load it as an assembly in c# or have F# interactive interpret the code. However, my main concern is security and how to stop the end user from executing arbitrary code. Is there an easy way to restrict this? Thanks!
This is an old question and things have considerably changed since it was asked. Now the Fable team have managed to run the F# compiler inside of a web-worker, removing the need to execute code on the server-side. This side-steps all of the security concerns around executing untrusted code.
You can try out the REPL here.
You can view the source-code here.

Why is there a required build step for Web UI apps?

Why must we run a build.dart script to develop with web_ui ?
I thought it was an frequent noob question about web_ui but I do not find an answer about that. Maybe I miss some web resources or articles.
With Angular.js or Polymer MDV don't need it, and they use bidirectionnal binding.
With future version of Web_ui or Chronium version, does the build.dart will be still necessary ?
This side of web_ui disappoints me a little bit and I feel it could discourage developers to use it.
Another point is I don't like project organisation with HTML sources in "web" and another "web/out" directory ? Can we configure the script to have another out directory like "templates" for templates and "web" for output ?
Than
If you want to use #observable, then you need to run a code generation step. Because Dart is a more structured language, it's not currently possible to add methods or change structure of an object at runtime. Therefore, we must run through a small code generation step that converts #observable into the code to track and notify for changes.
Polymer doesn't need this because they can alter the object at runtime. Also, Object.observe is landing in V8 (already landed?) which means the runtime performs observability automatically.
We know this is a problem, and we have a few ideas on how to solve it.
Build a devserver that does the building for you automatically.
Implement (eventually) mirror builders, which would allow you to alter program structure at runtime.
Option 1 is a near-term solution, and option 2 is a long-term solution.

How do I implement an F# Read Eval Print Loop (REPL)?

I would like to add an F# REPL to my application for live debugging purposes. I am looking at the source code for fsi.exe (F# Interactive) and there is a ton of stuff going on that looks like it pokes around with F# compiler internals. I cannot get this same code to compile in the context of our application because of this.
Is there a nice simple example of implementing an F# REPL somewhere? I would have hoped for this to be fairly easy.
The short answer is that F# (unfortunatelly) doesn't currently provide any API for hosting F# Interactive in your applications. There are a lot of people asking for this - see for example this SO question.
There are essentially two things you could do about that:
You can modify the open-source release and compile fsi.exe as some DLL library that would provide the API you need. This isn't simple task - F# Interactive is tightly bound with the compiler (it compiles code you enter on the fly), but it should be doable to encapsulate the types implementing REPL into some type you could call (But you cannot just take some file out of it - you need to compile entire F# to get this working).
You can run fsi.exe as a separate process as Visual Studio does and send commands to it using standard input/output. You can get some more flexibility by loading your library when fsi.exe starts. The library could use .NET Remoting to connect back to your application and expose some data.
Unfortunatelly, these two options are probably the only things you can do at the moment.
EDIT I was thinking that I already answered this question somewhere (perhaps in email), but couldn't
find it! Thanks to Mauricio who found the exact duplicate (even with my duplicate answer... Doh!)
I've written a series of blog posts about using the open source F# interactive executable inside and WPF application.
The code base is available on github - https://github.com/oriches/Simple.Wpf.FSharp.Repl
The series of blog posts are:
http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-1.html
http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-2.html
http://awkwardcoder.blogspot.co.uk/2013/12/simple-f-repl-in-wpf-part-3.html
The final post is to follow soon.

How best to add Load / Save file to/from a version control system to my Delphi Application

I have an Application that is based on loaded test programs, saved as text-based files in a specific user data folder. All fine. A client has just commented that they would like to have full traceability of changes to such test programs (for ISO9001 etc) and it occured to me that I could provide some kind of checkout / commit mechanism alongside the existing file load / save but which targetted a VCS (say SVN). The problem is that although I use Tortoise SVN for my own development, I've no idea how to write a simple program in Delphi to programmatically access SVN. Can anyone point me in the right direction?
You may want to look at the source code to DelphiSVN it's an OpenTool API application that integrates SVN into the Delphi IDE.
The SvnClient.pas in that project looks like an excellent way to call the SVN API
with the low level wrapper for the API in svn_client.pas
Using the SVN APIs seems like a good starting point.
Presumably you could also call the binaries directly e.g.
system( "svn checkout something" );
Although the simplest that appraoch should be avoided if at all possible.

Resources