Eternaltwin

Home | Contributing

Overview

This document provides an overview of the main Eternaltwin repository.

Eternaltwin is a relatively complex project since it acts as a platform to support other games. In particular, it is designed to be easily embedded in other projects through different clients.

Repository layout

DirectoryContents
bin/The eternaltwin executable, the only Rust binary that ships
crates/The Rust libraries, about forty of them
xtask/Development tasks run with cargo xtask
packages/The Node packages, including the Angular website
sdk/node/The Node SDK published to npm
sdk/php/The PHP SDK published to Packagist
clients/Kotlin, Ruby and TypeScript clients for the Eternaltwin API
examples/Small integrations, one per supported language
db/, dns/Database and DNS support files
docs/This documentation, in Markdown
test-resources/Fixtures shared by the tests

Dependencies

  • Red (or purple): deployed in Eternaltwin
  • Blue (or purple): deployed in the game

Dependencies

The graph is generated from the project structure by cargo xtask codegen structure, which writes dependencies.dot; render.sh turns it into dependencies.svg with Graphviz. The committed image is out of date. It predates seven crates, which are therefore missing along with their edges: captcha_store, composer_metadata_minifier, discord_client, eternaltwin_app_client, eternaltwin_app_store, gitlab_user_client and user_link_store. On the PHP side it is missing eternaltwin/etwin and eternaltwin/test-server.

Rust crates

Every crate lives in crates/, except the executable (bin/) and the task runner (xtask/). The directory name and the crate name differ in most cases: the directory is short (user_store), the crate is prefixed (eternaltwin_user_store).

Types and interfaces

  • core (eternaltwin_core) is the crate everything else depends on. It defines the domain types and, for each domain, the traits the rest of the code is written against: UserStore, ForumStore, HammerfestClient, TwinoidStore, and so on. Its modules follow the domains: app, auth, captcha, dinoparc, dinorpg, discord, forum, gitlab, hammerfest, job, link, mailer, opentelemetry, popotamo, twinoid, user, plus cross-cutting helpers such as clock, password, temporal, token and uuid.
  • constants (eternaltwin_constants) holds generated constant tables, such as the Dinoparc item and location lists.
  • config (eternaltwin_config) defines the configuration schema, its per-profile defaults, and the file lookup order.
  • password, log and serde_tools are small shared utilities: password hashing, structured logging, and serde helpers.

Most interfaces have several implementations and the right one is picked depending on context. For example, storage can either use memory or Postgres. Clients can use the network or a mock target.

Stores

Each store crate implements one core trait, usually twice: mem.rs for the in-memory version and pg.rs for Postgres. Several also have a trace.rs wrapper that adds telemetry, and test.rs holds the shared test suite both implementations must pass.

eternaltwin_app_store, auth_store, captcha_store, dinoparc_store, forum_store, hammerfest_store, job_store, link_store, oauth_provider_store, token_store, twinoid_store, user_link_store, user_store.

twinoid_store and eternaltwin_app_store also have a SQLite implementation.

Database plumbing

  • squirrel (eternaltwin_squirrel) manages SQL schema migrations. It is generic and reusable by other Eternaltwin projects.
  • db_schema (eternaltwin_db_schema) holds the Eternaltwin schema itself, with the create, upgrade and drop scripts.
  • postgres_tools (eternaltwin_postgres_tools) holds the Postgres helpers, in particular the macro building the snapshot upsertion query described in Archive.
  • populate (eternaltwin_populate) inserts the seed data declared in the [seed] configuration sections.

Clients for external services

  • eternaltwin_app_client talks to an Eternaltwin server on behalf of a registered application.
  • client (eternaltwin_client) is the generic client for the Eternaltwin API, used by the tests and by embedders.
  • discord_client and gitlab_user_client read the profile of a user who signed in through Discord or GitLab.
  • oauth_client implements the RFC 6749 client side, used for those sign-in flows.
  • mt_dns (eternaltwin_mt_dns) resolves Motion Twin's domains, including the ones whose DNS records are gone (dead.rs) and the ones still live (live.rs).

Each of these follows the same shape as the stores: an http implementation, a mem one for tests, and often a trace wrapper.

Services

  • services (eternaltwin_services) holds the shared high-level business logic, one module per domain, plus the background jobs in job/ (archiving Twinoid users, scraping Hammerfest profiles, themes and threads).
  • system (eternaltwin_system) is the assembly point: it reads the configuration and builds every store, client and service, picking the memory or Postgres implementation for each.
  • mailer and email_formatter render and send the outbound emails.

HTTP transport

  • rest (eternaltwin_rest) implements the HTTP interfaces: the REST API under /api/v1 (app, apps, archive, auth, captcha, clock, config, forum, job, oauth_clients, oauth_consent, outbound_email, users), the "backend-for-frontend" (BFF) API under /actions, and the telemetry intake under /v1/logs and /v1/traces.
  • app (eternaltwin_app) packages the built web application files so an embedder can serve the Eternaltwin frontend from its own binary. It is published by cargo xtask publish, never by hand.

Tooling

  • cli (eternaltwin_cli) implements the command line interface: backend, config, db, dump, job, start, version. bin/ is the thin main that calls into it, and produces the eternaltwin executable.
  • cargo_client, npm_client, packagist_client and gitlab_client query the registries during a release, to find out what is already published. composer_metadata_minifier is a Rust port of the Composer package of the same name, needed to read Packagist's responses.
  • scraper_tools (eternaltwin_scraper_tools) holds helpers for the scraper HTML crate. It is still a workspace member, but no crate depends on it since the scraping clients were removed in 0.13.0. See Archive.

xtask

xtask is a support crate for scripts used during development. Run it with cargo xtask from the repository root. Its subcommands are codegen, dns, docs, precompile, publish, release and backend (which analyzes the project structure). See Publish for the release and publication ones.

Node packages

packages/* and sdk/node/* are Yarn workspaces of the root package.json.

PackageDirectoryRole
@eternaltwin/websitepackages/websiteThe Angular frontend, and the only thing not in Rust
@eternaltwin/corepackages/coreTypeScript types and interfaces for Eternaltwin
@eternaltwin/clipackages/cliNode command line interface
@eternaltwin/exepackages/exeWrapper picking the right precompiled executable
@eternaltwin/exe-*packages/exe-*One package per target, each with a precompiled binary
@eternaltwin/koa-proxypackages/koa-proxyProxy router for the Koa web framework
@eternaltwin/mt-dnspackages/mt-dnsCustom DNS resolver for Motion Twin's websites
@eternaltwin/oauth-client-httppackages/oauth-client-httpOAuth client for Eternaltwin and Twinoid
@eternaltwin/pg-dbpackages/pg-dbHelpers for Postgres databases
@eternaltwin/client-nodesdk/node/clientEternaltwin client for Node
@eternaltwin/sdksdk/node/sdkThe SDK, without the executable

PHP packages

sdk/php holds the Composer packages: eternaltwin/etwin (the client), eternaltwin/cli, eternaltwin/exe, eternaltwin/path-tools and eternaltwin/test-server.

Other clients

clients/ holds the API clients maintained for languages without an SDK directory: kotlin, ruby and typescript. examples/ holds a small integration per language.