Package Exports
- @zeroin.earth/appwrite-ts
- @zeroin.earth/appwrite-ts/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@zeroin.earth/appwrite-ts) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@zeroin.earth/appwrite-ts
A TypeScript Server Plugin + CLI that generates fully typed collections from your Appwrite database schema. Point it at your appwrite.config.json and get const-typed declarations, then use the exported utility types to build type-safe wrappers for your data layer.
How It Works
Pull your Appwrite project config using the Appwrite CLI:
appwrite pull all # or just the parts you need: appwrite pull collectionsThis writes (or updates)
appwrite.config.jsonin your project root, which includes atablesarray describing every collection and its columns.The TSS plugin (or CLI) reads that JSON and generates an
appwrite-config.d.tsfile with const-typed literal tuples.You import
typeof appwriteConfigand pass it as aConfigparameter to the library's utility types —CollectionType,AppwriteDocument, etc. — to get precise, per-collection field types.
Whenever your Appwrite schema changes, run appwrite pull again. The TSS plugin watches the file and regenerates the declaration automatically; if you're using the CLI, re-run appwrite-ts generate.
Setup
bun add @zeroin.earth/appwrite-tsPeer dependency: typescript ^5
TypeScript Server Plugin
Register the plugin in tsconfig.json so your editor regenerates the declaration file automatically whenever appwrite.config.json changes:
{
"compilerOptions": {
"plugins": [
{
"name": "@zeroin.earth/appwrite-ts",
"configPath": "./appwrite.config.json",
"outputPath": "./appwrite-config.d.ts"
}
]
}
}| Option | Description | Default |
|---|---|---|
configPath |
Path to the Appwrite config JSON | ./appwrite.config.json |
outputPath |
Path for the generated .d.ts file |
./appwrite-config.d.ts |
On load, the plugin reads the config, writes the declaration file, and watches the JSON file for changes (1 s poll interval). Errors are logged via the TSServer logger.
CLI
You can also generate the declaration file manually or in CI:
appwrite-ts generate ./appwrite.config.json -o ./appwrite-config.d.tsExported Types
CollectionType<Id, Config?>
Maps a collection $id to an object type of its fields. Pass your literal Config for precise types; omit it for a generic fallback.
AppwriteDocument<Id, Config?>
AppwriteMeta & CollectionType<Id, Config> — a fully-typed document including Appwrite system fields.
AppwriteRow
AppwriteMeta & { readonly [key: string]: unknown } — an untyped row with an index signature, useful for generic operations like iterating keys or stripping metadata.
AppwriteMeta
Appwrite system fields present on every document:
| Field | Type |
|---|---|
$id |
string |
$createdAt |
string |
$updatedAt |
string |
$permissions |
string[] |
$databaseId |
string |
$tableId |
string |
$sequence |
number (optional) |
Column, Table, AppwriteConfig
Runtime shapes for the config JSON. Used internally by the generator and available for tooling that needs to inspect the schema at runtime.
Column Type Mapping
| Appwrite column type | TypeScript type |
|---|---|
boolean |
boolean |
integer, double |
number |
varchar, text, mediumtext, string |
string |
string with format: "enum" |
Union of literal element strings |
Any column with array: true |
T[] |
Any column with required: false |
T | null |
Usage
Binding Your Config
The core pattern: import the generated declaration and pass its type as the Config parameter.
import type appwriteConfig from './appwrite-config'
import type { AppwriteDocument, CollectionType } from '@zeroin.earth/appwrite-ts'
// Bind the literal config
type Config = typeof appwriteConfig
// Extract the union of all collection IDs
type CollectionId = Config['tables'][number]['$id']
// → "users" | "posts" | "comments" | ...
// Get precise field types for a specific collection
type PostFields = CollectionType<'posts', Config>
// → { title: string; body: string; authorId: string; published: boolean; views: number | null }
// Get a full Appwrite document (system fields + collection fields)
type PostDoc = AppwriteDocument<'posts', Config>
// → AppwriteMeta & PostFieldsBuilding Typed Wrappers
In practice, you'll want to build a small set of wrapper types in your project that bind Config once and give you convenient aliases for the rest of your codebase. This is where the real value is — you define these once and every data-access function, mapper, and persister gets full type safety for free.
// types.ts — define once, import everywhere
import type appwriteConfig from './appwrite-config'
import type { AppwriteDocument, AppwriteMeta } from '@zeroin.earth/appwrite-ts'
type Config = typeof appwriteConfig
/** Union of all collection $id strings. */
export type CollectionId = Config['tables'][number]['$id']
/** A fully-typed Appwrite document for a given collection. */
export type Doc<Id extends CollectionId> = AppwriteDocument<Id, Config>
/** An untyped row with index signature for generic operations (stripping meta, etc). */
export type UntypedRow = AppwriteMeta & { [key: string]: unknown }Now you can use Doc<'posts'>, Doc<'comments'>, etc. throughout your project with zero extra ceremony:
import type { CollectionId, Doc, UntypedRow } from './types'
// Typed function — knows exactly which fields exist on a post
function formatPost(doc: Doc<'posts'>): string {
return `${doc.title} by ${doc.authorId}` // ← autocomplete + type checking
}
// Generic function — works with any collection's documents
function stripMeta(row: UntypedRow): Record<string, unknown> {
const result: Record<string, unknown> = {}
for (const [key, value] of Object.entries(row)) {
if (!key.startsWith('$')) result[key] = value
}
return result
}Distinguishing Singletons from Multi-Row Collections
If your schema has both single-document collections (e.g., user settings, app config) and multi-row collections (e.g., posts, comments), you can encode that distinction:
type SingletonIds = 'user_settings' | 'app_config'
/** Pulled data shape — singletons are a single doc or undefined, arrays for the rest. */
export type PulledCollections = {
[K in CollectionId]: K extends SingletonIds ? Doc<K> | undefined : Doc<K>[]
}This gives you a single type representing an entire pull from Appwrite, with each collection correctly typed as either a document or an array of documents.
Notes
- The plugin uses
export = init(CommonJS) as required by the TypeScript Server Plugin API. Your root tsconfig should exclude the plugin's source directory (e.g.packages/*/src) to avoid module format conflicts. - Peer dependency:
typescript ^5. - The CLI uses Commander for argument parsing.
Development
bun run build # Compile with tsc
bun run dev # Watch mode
bun test # Run tests
bun run typecheck # Type-check without emitting
bun run clean # Remove dist/