studio status report: 2024-03

month 03 of 2024 was about Songhay.Player.YouTube release 6.3.1 ๐Ÿ“ฆ๐Ÿš€

As of this writing, there is only one task left on the Songhay.Player.YouTube project for release 6.3.1. This places the Studio very, very close to replacing the Angular app in with a Bolero appโ€”this ridiculously difficult struggle to move beyond the SEO-nightmare world of Angular.

My Obsidian โ€œsecond brainโ€ is really helping this Studio to function and move forward:

Obsidian second brain

Selected notes from month 03:

[[]]: TheoryData<T> has been thereโ€ฆ

From โ€œTypesafety in xUnit with TheoryData<T>โ€:

TheoryData<T> is a class that allows to wrap the data in a strongly typed way. Here is how I used it:

public static TheoryData<Action<IServiceCollection>>Data =>new() 
    services =>services.UseSqliteAsStorageProvider(),
    services =>services.UseSqlAsStorageProvider(),
    services =>services.UseInMemoryAsStorageProvider(),
    services =>services.UseRavenDbAsStorageProvider(),
    services =>services.UseMySqlAsStorageProvider()

public void GivenAlreadyRegisteredRepository_WhenTryingToAddAnotherStorage_ThenException(Action<IServiceCollection>act)

[!important] What the article does not mention ๐Ÿ•ถโ” is that TheoryData<T> works best when one strongly type argument is being passed into the test method (as shown in the code sample above)โ€”not multiple args.

โ€œThe โ€˜missingโ€™ graph datatype already exists. It was invented in the โ€™70sโ€

I claim the reason why it is so difficult to support graphs in languages nowadays is because the imperative/structured programming model of modern programming languages is ill-suited for graph algorithms. As Wayne correctly points out, the core problem is that when you write a graph algorithm in an imperative language like Python or Rust, you have to choose some explicit representation for the graph. Then, your traversal algorithm is dependent on the representation you chose. If you find out later that your representation is no longer efficient, it is a lot of work to adapt your algorithms for a new representation.


[[SQLite]]: yes, the interactive docs are using [[WebAssembly]]

Under the hood, we leverage WebAssembly (WASM) technology to execute SQLite statements directly in the browser, providing a seamless and responsive experience. Additionally, we have preloaded a sample database, ensuring users have a rich dataset to work with from the moment they access the console.

โ€”โ€œInteractive SQLite Documentation: Experiment with Queries in Real-Time!โ€

[[eleventy]]: the most important help document

โ€œI Finally Understand Eleventyโ€™s Data Cascadeโ€ by Ben Myers is today regarded as the most important [[eleventy]] document:

When Eleventy generates the pages of your site, it aggregates data supplied from several places and then injects that data into your contents. The process of aggregating this data from each of these different places and deciding which data should have precedence in the case of a conflict is what Eleventy calls the data cascade.

According to Ben Myers (in 2021), here is the [[eleventy]] data cascade [๐Ÿ“– docs ]:

  1. global data [๐Ÿ“– docs ]
  2. config global data [๐Ÿ“– docs ]
  3. layout frontmatter [๐Ÿ“– docs ]
  4. directory data files and template data files [๐Ÿ“– docs ]
  5. template frontmatter [๐Ÿ“– docs ]
  6. computed data [๐Ÿ“– docs ]

[[eleventy]]: โ€œIntroduction to WebCโ€ #to-do

WebC is a new tool by Zach Leatherman (creator of Eleventy) for serializing custom elements at build time. It aggregates component-level CSS and JavaScript, allowing developers to keep their styles and scripts together with the markup as single file components, the way you may be used to if you work with JavaScript frameworks such as Svelte or Vue.

All without having to ship a single line of JavaScript to the client โ€” unless you want it to.


[[ASP.NET]]: FSharp.AspNetCore.WebAppBuilder

The webApp computation expression lets you define ASP.NET Core web applications in a succinct and declarative way, minimizing code, maximizing readability, and providing a simple but thorough set of escape hatches, so you can always drop down to the raw ASP.NET Core APIs when you need to.


[[Obsidian]]: โ€œJSON Canvas was originally created for Obsidian.โ€

![[Pasted image 20240311115241.png]]

Infinite canvas tools are a way to view and organize information spatially, like a digital whiteboard. Infinite canvases encourage freedom and exploration, and have become a popular interface pattern across many apps.

The JSON Canvas format was created to provide longevity, readability, interoperability, and extensibility to data created with infinite canvas apps. The format is designed to be easy to parse and give users ownership over their data. JSON Canvas files use the .canvas extension.

JSON Canvas was originally created for Obsidian. JSON Canvas can be implemented freely as an import, export, and storage format for any app or tool. This site, and all the resources associated with JSON Canvas are open source under the MIT license.


โ€œShould AVIF be the dominant image format on the web?โ€

Looks like highest fidelity but not so great file size:

Letโ€™s find out how similar AVIF, JPEG, and WebP are to their original. When we compare them using full-reference image quality assessment algorithms like mean squared error, peak signal-to-noise ratio, and the structural similarity index, we see that AVIF outperforms both JPEG and WebP starting at a quality setting between 30-40%. Also, note that WebP performs slightly better than JPEG.

โ€”Tim Severien

โ€œWeโ€™re Bringing Responsive Video Back!โ€

So along with that article, I outlined some of the points above in an explainer document, which included some markup examples that should feel familiar to folks who have used the picture element, like this:

    <source media="(min-width: 2000px)" src="large.webm" type="video/webm">
    <source media="(min-width: 2000px)" src="large.mp4" type="video/mp4">
    <source media="(min-width: 1000px)" src="medium.webm" type="video/webm">
    <source media="(min-width: 1000px)" src="medium.mp4" type="video/mp4">
    <source src="small.webm" type="video/webm">
    <source src="small.mp4" type="video/mp4">

But then, this spring the WhatWG issue thread lit up with some good news: representatives from Firefox and Chrome chimed in to say that they agreed and intend to reinstate their support! Following that, implementation bugs were filed in the Chromium and Firefox trackers.


Python-Markdown looks the the reference implementation for [[markdown]]

This is a Python implementation of John Gruber's Markdown. It is almost completely compliant with the reference implementation, though there are a few known issues. See Features for information on what exactly is supported and what is not. Additional features are supported by the Available Extensions.


[[Azure]]: dotnet user-secrets, [[PowerShell]], Microsoft.Extensions.Configuration and [[Bicep]] all mixed together by Frank Boucher

In โ€œGenerate Local .NET Secrets from Azure Deploymentsโ€ Frank Boucher basically dumps a bunch of stuff on the readerโ€”in part because there is video that might explain further:

How to Generate Local .NET Secrets From Azure Deployment

How to Generate Local .NET Secrets From Azure Deployment

What I do notice so far are the following:

  • the dotnet user-secrets command is installed by default but not documented
  • today, I assume that the dotnet user-secrets system does not scale beyond the development environment (not seamlessly related to [[Azure Key Vault]])
  • Bicep is locked into [[Azure]] while [[Terraform]] knowledge is portable

[[Obsidian]]: โ€œ๐Ÿง  Peek Inside my Personal Obsidian Vault: Dann Berg's Complete 2024 Tourโ€

๐Ÿง  Peek Inside my Personal Obsidian Vault: Dann Berg's Complete 2024 Tour

๐Ÿง  Peek Inside my Personal Obsidian Vault: Dann Berg's Complete 2024 Tour

Notable plugins shown in the video [๐Ÿ“น watch ]:

Gรฉrald Barrรฉ letโ€™s me know about a serious limitation of Swashbuckle.AspNetCoreโ€ฆ

Most .NET developers generate the specification from the code. The Swashbuckle.AspNetCore library is a popular choice to generate the OpenAPI specification from ASP.NET Core Web API projects. You can easily add a page to access the specification. However, it's hard to validate the content of the specification to ensure the specification is usable by the consumers. One way to improve that is to make the specification part of your code, so you can review the specification during code reviews.

Microsoft provides the NuGet package Microsoft.Extensions.ApiDescription.Server that allows you to generate the OpenAPI specification from the code while building the project.

โ€”โ€œGenerate OpenAPI specification at build time from the code in ASP.NET Coreโ€

Background from the docs:

The Swagger project was donated to the OpenAPI Initiative in 2015 and has since been referred to as OpenAPI. Both names are used interchangeably. However, "OpenAPI" refers to the specification. "Swagger" refers to the family of open-source and commercial products from SmartBear that work with the OpenAPI Specification. Subsequent open-source products, such as OpenAPIGenerator, also fall under the Swagger family name, despite not being released by SmartBear.

In short:

  • OpenAPI is a specification.
  • Swagger is tooling that uses the OpenAPI specification. For example, OpenAPIGenerator and SwaggerUI.

โ€”โ€œOpenAPI vs. Swaggerโ€

I think I need to take action based on โ€œ.NET OpenAPI tool command reference and installation.โ€

yes, modern [[Blazor]] needs the ::deep pseudo selector just like those used in [[Angular]]

The ::deep pseudo-selector will allow you to target child HTML elements nested within a parent component.

โ€”โ€œBlazorโ€™s CSS isolation ::deep issue and solutionโ€

[[ASP.NET]]: the Problem Details standard #to-do

The following video introduces the Problem Details standard (RFC7807) to me:

Stop returning custom error responses from your API. Do this instead.

Stop returning custom error responses from your API. Do this instead.

The ProblemDetails class [๐Ÿ“– docs ] is the ancestor of the ValidationProblemDetails class [๐Ÿ“– docs ].

Will I find the developer exception page useful?

related reading

[[Redis]] is walking slowly away from Open Source license

Beginning today, all future versions of Redis will be released with source-available licenses. Starting with Redis 7.4, Redis will be dual-licensed under the Redis Source Available License (RSALv2) and Server Side Public License (SSPLv1). Consequently, Redis will no longer be distributed under the three-clause Berkeley Software Distribution (BSD).

โ€”Rowan Trollope, Chief Executive Officer, Redis

[[Bulma]] is version 1.0

Bulma v1 is a full rewrite of the framework using Dart Sass, which is the the primary implementation of Sass. While this affects a few development details, everything has been done to make the transition as easy as possible.

What remains the same

All HTML snippets are the same. This means you don't need to update your markup. This is important because it means, if you're using Bulma straight "out of the box", you don't need to change anything.

You can just swap bulma@0.9.4/css/bulma.min.css with bulma@1.0.0/css/bulma.min.css and everything will work. Things will look slightly different, but they will still work.


[[Obsidian]]: more community plugins #to-do

The following leaves me with two community-plugin picks:

5 NEW Obsidian Plugins You NEED to Know About in 2 Minutes!

5 NEW Obsidian Plugins You NEED to Know About in 2 Minutes!

  1. Surfing [๐Ÿ“น watch ]
  2. Summary [๐Ÿ“น watch ]

[[ASP.NET]]: [[Microsoft]] Defender for APIs?

Defender for APIsย offers full lifecycle protection, detection, and response coverage for APIs. Defender for APIs helps you to gain visibility into business-critical APIs. You can investigate and improve your API security posture, prioritize vulnerability fixes, and quickly detect active real-time threats.

โ€”โ€œProtect Against OWASP API Top 10 Security Risks Using Defender for APIsโ€

[[ASP.NET]]: my introduction to WebAuthn

WebAuthn is a relatively new standard for authenticating users and is an incredibly secure way to authenticate users by being phishing resistant, and not requiring passwords at all. It accomplishes this via public-key cryptography. To read more about it, check out Wikipedia. โ€ฆ We will be utilizing Bitwarden's Passwordless service as our passkey platform.

โ€”Kai Ito

related reading

[[dotnet|.NET]]: sorting IReadOnlyCollection<T>, IReadOnlyList<T> and IEnumerable<T>

In the context of [[Entity Framework]], output of IEnumerable<T> implies that .ToArray() or .ToList() has not been called in some LINQ-to-SQLcontext which means all members of the collection have not been loaded into memory:

IEnumerable<T> is a good fit for many scenarios, but do consider that IReadOnlyCollection<T> might be a better fit in circumstances where the collection is always going to be fully available in memory. Avoid passing round mutable collection types as this can cause confusion about who owns the collection.

โ€”โ€œWhat types should I use to pass collections in C#?โ€ (2019)

The term lazy evaluation in our [[Entity Framework]] scenario makes sense here:

โ€ฆan IReadOnlyCollection<T> signals to the caller that there will be no lazy evaluation. (The Count property, as opposed to the Count extension method of IEnumerable<T> (which is inherited by IReadOnlyCollection<T> so it has the method as well), signals non-lazyness. And so does the fact that there seem to be no lazy implementations of IReadOnlyCollection.)


When the following refers to โ€œindexer supportโ€ it pointing out that the IReadOnlyList<T>.Item[Int32] property [๐Ÿ“– docs ] has no equivalent in IReadOnlyCollection<T> [๐Ÿ“– docs ]:

I would say, if you return an object that is a List<T> or T[], you may want to expose it as at least IReadOnlyCollection<T> or better IReadOnlyList<T> which has indexer support. The advantages of doing this is:

  • A call to ToList is not required to do multiple enumerations of the same output.
  • The boundaries are clearly defined
  • Using an IReadOnlyList<T>, you could enumerate with a for loop as opposed to foreach, which might be advantageous in some corner cases.

The main disadvantage I see of this, which could be a big one depending on the implementation:

  • Your API will no longer be able to return an IEnumerable<T> in a streaming fashion (e.g. reading from a Stream or IDbDataReader, etc). This would mean introducing a breaking change in your code.


[[Blazor]]: โ€œWhat Is a Blazor Layout?โ€

When a [[Blazor]] page inherits from LayoutComponentBase it becomes a layout page:

It uses the @inherits directive to specify that it inherits from the LayoutComponentBase type. It is what makes a regular Blazor component a layout component.

โ€”โ€œBlazor Basics: Working with Blazor Layoutโ€

Cโ™ฏ 12 Collection Expressions cannot use var

// Pre C# 12
var array = new[] { 1, 2 };
var spread = array.Concat(new[] { 3, 4 });

// Post C# 12
int[] array = [1, 2];
int[] spread = [..array, 3, 4];

Since collection literals are target-typed, we cannot use var but must declare the type name for our variable.

โ€”โ€œCollection Expressions โ€“ Using C# 12 in Rider and ReSharperโ€

sketching out development projects

The current, unfinished public projects on GitHub:

  • replacing the Angular app in with a Bolero app ๐Ÿšœ๐Ÿ”ฅ depends on:

    • finishing the Songhay.Player.YouTube release 6.3.1 ๐Ÿ“ฆ๐Ÿš€ project
  • start the โ€œSonghay.Publications.Models 6.0.0โ€ ๐Ÿ“ฆ๐Ÿš€ project

  • completing the Songhay.Publications 6.1.0 ๐Ÿ“ฆ๐Ÿš€ project

The proposed project items:

  • add Entity Framework (over SQLite) features to Songhay.Publications
  • generate Publication indices from SQLite for Songhay.Publications.KinteSpace
  • generate a new repo with proposed name, Songhay.Modules.Bolero.Index โœจ๐Ÿšง and add a GitHub Project
  • switch Studio from Material Design to Bulma ๐Ÿ’„ โžก๏ธ ๐Ÿ’„โœจ