prscrew.com

Creating Custom Extensions in Toolips.jl: A Comprehensive Guide

Written on

Introduction to Toolips.jl Extensions

This guide provides an insight into the development of extensions for Toolips.jl. As of version 0.1.0, Toolips is in the Unstable phase, awaiting finalization of documentation and server tests. Toolips has seen significant advancements since its inception, largely due to its focus on extensibility. At its foundation, Toolips embraces a functional design pattern. For a deeper understanding of this approach, refer to the article discussing a functional core in JavaScript.

The functional core allows for high mutability because it revolves around functions instead of data. Functions can modify data without directly altering it, presenting a unique and intriguing method for a web-development framework, particularly within Julia's closure paradigm. This strategy has proven to be effective. In Toolips, every server operation, from logging to serving public files, can be added as an optional extension. If your project doesn't require a logger, there's no need to include that extension. Similarly, if serving a directory of files isn't necessary, you can skip that too. This flexibility is crucial since web projects in languages like Julia can differ vastly, as seen in Python's varied frameworks.

Comparing Frameworks: Python Examples

In Python, two prominent frameworks dominate the web-development landscape: Flask and Django. Flask is a lightweight option suitable for web applications, though it can be complex for extensive projects. Django, on the other hand, is typically used for building full websites rather than APIs, leading to a split in learning for Python developers who wish to do both. This dichotomy can create issues with dependencies and functionality, leaving developers with either excess or insufficient tools tailored to their specific project needs.

The closure-based architecture of Toolips.jl addresses these challenges by making web-development capabilities easily extendable. Toolips can serve simple tasks like providing an API for a model's predictions or support full-stack applications, as demonstrated by the Pasta.jl text editor example.

Creating Your Own Extensions

Today, we’ll delve into the process of building custom extensions for Toolips. Surprisingly, it's quite straightforward to implement a lot of functionality with minimal code! If you're eager to explore Toolips further, visit our GitHub repository: Our Project.

We will start by creating a project named ToolipsDefaults.jl. This will offer a default set of indexable styles and the ability to generate a stylesheet automatically on selected routes. First, we’ll generate the project using the command:

using Pkg; Pkg.generate("ToolipsDefaults")

Our new ToolipsDefaults/src/ToolipsDefaults.jl file will now serve as a basic module:

module ToolipsDefaults

greet() = print("Hello World!")

end

Next, we need to handle our imports. We'll directly import the Servable abstract type since we're developing a Servable extension, along with the Toolips module:

using Toolips

import Toolips: Servable

Structuring the Stylesheet

Before we begin creating our stylesheet structure, we must determine the required fields. To investigate any abstract type in Toolips, we can access its documentation:

help?> Servable

The essential consistency for a Servable is its f() function. While there exists a lower hierarchical step called StyleComponent, it does not align with our new StyleSheet Servable. Therefore, we will focus on the f consistency in our constructor:

mutable struct StyleSheet

f::Function

end

What additional components should our StyleSheet include? The beauty of Servable extensions lies in how f functions resemble typical routing functions. For instance:

rt = route("/") do c::Connection

write!(c, "hello world!")

end

An f function, however, is structured like this:

f(c::Connection) = begin

write!(c, "hello world!")

end

Given that both functions accept similar arguments, we can create Servable extensions as preset compositions of components. Thus, we will include a vector of Servables in our type:

mutable struct StyleSheet

f::Function

comps::Vector{Servable}

end

Next, we’ll build an inner constructor to initialize our StyleSheet:

mutable struct StyleSheet

f::Function

comps::Vector{Servable}

function StyleSheet()

end

end

Now, let's define our f function using the syntax discussed earlier:

mutable struct StyleSheet

f::Function

comps::Vector{Servable}

function StyleSheet(comps::Vector{Servable})

f(c::AbstractConnection) = begin

write!(c, comps)

end

end

end

Setting Default Styles

Our next step involves establishing default styles for our StyleSheet. We can create individual methods for each style, returning a single Servable:

function da_div()

end

function ds_div()

end

function ds_p()

end

function ds_a()

end

function ds_button()

end

function ds_li()

end

function ds_ul()

end

function ds_h1()

end

function ds_h2()

end

function ds_h3()

end

While the complete implementation of these functions isn’t necessary here, their outputs will be single Servables, which we will incorporate into the StyleSheet constructor:

mutable struct StyleSheet

f::Function

comps::Vector{Servable}

function StyleSheet(comps::Vector{Servable} = [

ds_div(), ds_p(), ds_a(), ds_button(), ds_li(), ds_ul(), ds_h1(),

ds_h2(), ds_h3()

])

f(c::AbstractConnection) = begin

write!(c, comps)

end

end

end

Sub-typing as a Servable

Next, we will sub-type this as a Servable and return our StyleSheet using the inner constructor:

mutable struct StyleSheet <: Servable

f::Function

comps::Vector{Servable}

function StyleSheet(comps::Vector{Servable} = [

ds_div(), ds_p(), ds_a(), ds_button(), ds_li(), ds_ul(), ds_h1(),

ds_h2(), ds_h3()

])

f(c::AbstractConnection) = begin

write!(c, comps)

end

new(f, comps)::StyleSheet

end

end

Implementing a ServerExtension

Now, we’ll create a simple ServerExtension that will automatically write the stylesheet to predefined routes. Let's start by examining the consistencies of the ServerExtension abstract type:

help?> ServerExtension

Server extensions are loaded at server startup and can possess different capabilities based on the value of their type field, which can be a Symbol or a Vector of Symbols. For our needs, we want a function that runs before each routing, so we will use :func:

mutable struct StyleSheetLoader

type::Symbol

f::Function

stylesheet::StyleSheet

active_routes::Vector{String}

function StyleSheetLoader(active_routes::Vector{String} = ["/"],

stylesheet = StyleSheet())

new(:func, f, stylesheet, active_routes)

end

end

This leads us to write an f function similar to the previous example, where we utilize the write! function to render our stylesheet:

mutable struct StyleSheetLoader <: ServerExtension

type::Symbol

f::Function

stylesheet::StyleSheet

active_routes::Vector{String}

function StyleSheetLoader(active_routes::Vector{String} = ["/"],

stylesheet = StyleSheet())

f(c::Connection) = begin

write!(c, stylesheet)

end

new(:func, f, stylesheet, active_routes)

end

end

Conclusion: Embracing Minimalism in Development

We have now successfully created a new StyleSheet servable that can be utilized with Toolips, along with a straightforward extension that applies our stylesheet to predetermined routes. This guide serves as a resource for those looking to develop customized structures and Servables within Toolips. Such techniques can greatly enhance your projects, especially when certain functionalities may be lacking.

I appreciate your reading this guide, and I hope it motivates you to explore creating your own extensions in Toolips!

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Debunking Common Misconceptions About Time Management

Explore five common time management myths that hinder productivity and learn how to effectively manage your time for better results.

Embracing Plant-Based Living: My Journey and Reflections

A personal reflection on the benefits and challenges of adopting a vegan lifestyle and the reactions it can provoke.

Unlocking the Potential of Online Courses for Passive Income

Discover how to create and profit from online courses while generating passive income.