A few notes on coding conventions used in this project.
Run these commands to perform type and style checks and automatically reformat code based on conventions:
make check # Type check + lint frontend and backend
make fmt # Format all code// Use relative imports by default (include .ts extension)
import { Space } from "./space.ts";
// Use `type` for type-only imports (part of the lint rules)
import type { Command } from "./types/command.ts";
// Use package-prefixed absolute when available (defined in deno.json)
import { sleep } from "@silverbulletmd/silverbullet/lib/async";- Use
typeoverinterfacefor object shapes - Use
typefor unions and complex types - Always type function parameters explicitly
- Type return values for public APIs
- Let TypeScript infer obvious variable types
- Use
anyfor error objects in catch blocks
- Variables & functions:
camelCase - Classes:
PascalCase - Files:
snake_case.ts(e.g.,http_space_primitives.ts) - Test files:
*.test.tsalongside source files - Types:
PascalCase(e.g.,PageMeta,SpacePrimitives) - Constants:
camelCase
TypeScript tests run with Deno.
Test structure:
Deno.test("Test description in plain English", async () => {
// Setup
const kv = new MemoryKvPrimitives();
const space = new Space(new DataStoreSpacePrimitives(kv), eventHook);
// Execute
await space.writePage("test", testPage);
// Assert
assertEquals(await space.readPage("test"), testPage);
});Assertions:
import { assertEquals, assertNotEquals } from "@std/assert";
assertEquals(actual, expected);
assertNotEquals(actual, notExpected);Test configuration:
Deno.test("Test with options", {
sanitizeResources: false,
sanitizeOps: false,
}, async () => {
// test code
});Use JSDoc for public APIs:
/**
* Lists all pages (files ending in .md) in the space.
* @param unfiltered - Whether to include filtered pages
* @returns A list of all pages represented as PageMeta objects
*/
export function listPages(unfiltered?: boolean): Promise<PageMeta[]> {
return syscall("space.listPages", unfiltered);
}Inline comments:
- In case of doubt: add comments around the why of the code (not what)
- Add TODO comments for known issues
// Note: these events are dispatched asynchronously (not waiting for results)
this.eventHook.dispatchEvent(...);
// TODO: Clean this up, this has become a god class
export class Client {Definite assignment for late initialization:
class Client {
space!: Space; // Initialized in init()
editorView!: EditorView;
}Destructuring:
const { name, def } = command;
const { text, meta } = await this.space.readPage(name);Follow common Go conventions. make fmt also reformats Go code.
See website/Space Lua/Conventions