# Essentials

Outdated

The tech stack is constructed upon a set of fundamental concepts where possessing their basic understanding is essential for a seamless comprehension of the content presented in the Development section.

# Terms

Before going deeper, it is essential to review the understanding of terminology used throughout the Development section.

# Application

There are three types of entities classified as applications: orchestrator, service, and package. The latter is not an application in the traditional sense; however, it is included in this category for the sake of clarity.

# Orchestrator

Typically, only one orchestrator exists per project, as it serves as the sole provider of a public API and is the only application capable of communicating with the services.

All security measures must be enforced at this level, as no additional checks are performed on the services.

# Service

One of many other services per project. Each designed to cater to a specific area based on the Single Responsibility Principle, ensuring all services operate independently, without knowledge of one another, and do not share databases, buckets, or any other resources.

Communication with the outside world occurs exclusively through the orchestrator and strictly via RPC, utilizing the WorkerEntrypoint. Each request is treated as if it has been approved by the orchestrator, allowing the service to perform the action with elevated permissions.

# Package

Public or private, centralized location for types and utilities that are appropriate to share across all applications.

# Structure

All applications are housed within a single monorepository that leverages Bun workspaces. This consolidation ensures development consistency, facilitates the sharing of types, enables unified dependency management, and streamlines the refactoring process.

# Technologies

Reinventing the wheel is discouraged, and instead, the use of widely-used and recognized libraries that solve common problems is encouraged. The list of these backbone technologies can be found below, along with a summary of the motivation behind their use and an explanation of the configuration:

Cloudflare Developer Platform
https://www.cloudflare.com/developer-platform/

TypeScript
https://www.typescriptlang.org/

Vite
https://vite.dev/

Nitro
https://nitro.build/

Drizzle ORM
https://orm.drizzle.team/

Zod
https://zod.dev/

Vitest
https://vitest.dev/

Bun
https://bun.sh/

# Cloudflare Developer Platform

Cloudflare serves as the primary provider of the infrastructure, offering a highly reliable, affordable, scalable, and DX-friendly platform for building virtually anything. Although it may currently have limited support for certain concepts that are typically found in more mature ecosystems, the Develit Backend SDK helps to fill these gaps.

The following Cloudflare services are used across the tech stack:

Workers
https://developers.cloudflare.com/workers/

D1
https://developers.cloudflare.com/d1/

KV
https://developers.cloudflare.com/kv/

Queues
https://developers.cloudflare.com/queues/

# TypeScript

Type safety is a crucial concept of the tech stack, and statically checking code before merging it is an essential step in writing maintainable code. The configuration of TypeScript, residing in tsconfig.json, prioritizes strictness and compatibility with modern JavaScript.

# erasableSyntaxOnly

Erasable syntax refers to the ability to remove certain syntax without affecting the runtime behavior of the code. Enabling this option is crucial for writing forward-compatible code that will remain maintainable in the future, even if non-erasable syntaxes or TypeScript itself are no longer used.

For instance, several proposals are currently underway to add type annotations to JavaScript, including the popular types as comments proposal, which would enable JavaScript to treat types in code as ignorable at runtime.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly

# esModuleInterop

Historically, JavaScript has had two primary options for exporting and importing: CommonJS and ESM. Modern JavaScript tends to shift towards using the ESM approach. Enabling this option allows for the use of default imports from modules that still export using the CommonJS syntax.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#esModuleInterop

# experimentalDecorators

Introspection utilities like Function.caller or arguments.callee are not a part of the modern JavaScript, but the demand for such functionality still exists. This is why the decorators propsal is nearing implementation. Enabling this option allows for the use of features from the Backend SDK, that utilize decorators, that enable more concise code to be written.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#experimentalDecorators

# isolatedModules

JavaScript files without any imports or exports are considered legacy. Enabling this option ensures that each file can be safely transpiled without relying on other imports.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#isolatedModules

# module

The module system in JavaScript has a different versioning strategy than the ECMAScript specification. Enabling this option with the ESNext value ensures that the newest features are immediately available as soon as they are available in the runtime.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#module

# moduleResolution

The use of Bundler value is not a strongly held preference, but rather a default setting that is applied when creating a new Cloudflare Worker project.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#moduleResolution

# noEmit

By default, the TypeScript compiler is designed to transpile TypeScript code into JavaScript code. Enabling this option causes the compiler available solely for type checking purposes, preventing it from attempting to compile the code and thereby avoiding the generation of unnecessary files.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#noEmit

# skipLibCheck

Libraries may define copies of the same type in an inconsistent manner. Enabling this option causes the compiler to ignore all declaration files that are not explicitly referenced.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#skipLibCheck

# strict

The compiler is inherently lenient, as its primary purpose is to compile TypeScript code into JavaScript code. For TypeScript-first codebases, it is beneficial to establish specific TypeScript rules that must be adhered to from the outset. Enabling this option enforces a multitude of rules, resulting in the production of standardized, type-safe code.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#strict

# target

The features available when programming in JavaScript are defined by the ECMAScript specification. Enabling this option with the ESNext value ensures that the newest features are immediately available as soon as they are available in the runtime.

TSConfig Reference
https://www.typescriptlang.org/tsconfig/#target

# Vite

To deploy the code on the Cloudflare infrastructure, it must be bundled. Cloudflare provides the @cloudflare/vite-plugin Vite plugin, which brings the workerd environment to localhost, ensuring that the code behaves consistently both locally and in production.

In addition to that, it provides a delightful DX by leveraging Vite's hot module replacement and supporting vite preview, enabling testing of the build output in the Workers runtime prior to deployment.

# Nitro

The Nitro team provides the nitro-cloudflare-dev Nitro module, which facilitates access to Workers runtime bindings within the development server. In the context of the orchestrator, bindings primarily represent the service workers.

Another widely recognized concept that Nitro lacks is the use of guards. Develit addresses this by offering the @develit-io/nitro-guards Nitro module, which effectively integrates this feature into Nitro.

# Drizzle ORM

Accessing the database through the same language as the one used in the codebase brings the benefit of type safety when manipulating with tables or its records.

Drizzle ORM provides native D1 integration.

# Zod

Validating input and output offers benefits akin to static type checking, as early error detection enhances both DX and UX.

Nitro utilizes h3, which features built-in utilities for validating REST inputs. These utilities can be effectively used in conjunction with Zod, allowing it to handle all validation tasks.

# Vitest

Quality ensurance is yet another important factor of our tech stack thus writing tests is an important part of the development. Cloudflare maintains @cloudflare/vitest-pool-workers Vitest plugin that enables to run tests in the context of workerd, ensuring the code will behave as close to the production as possible.

# Bun

As the tech stack is not dependent on Node, it does not make sense to utilize it just to be able to install packages.

Bun offers monorepository support, Dependabot compatibility and ultra-fast package managing.