Jade Linter — VS Code Extension
Linter, IDE support, and auto-relation detection for Jade ORM schema files.

Features
- Two schema formats — first-class
.jade declarative and Lua Entity style
- Syntax Highlighting — Jade types and modifiers in
.lua files (injection; coexists with sumneko.lua) and native .jade language registration
- Auto-Completion — Types, modifiers (
!, ?, .default, :primaryKey(), :foreignKey()), relations, table names, and model names
- Linting — Real-time error detection for invalid types, missing modifiers, and broken references
- Auto-Relation Detection — Infers
belongsTo relations from :foreignKey() modifiers, hasMany/belongsTo/hasOne calls, and _id naming conventions
- Hover — Documentation on hover for types, modifiers, relations, and FK fields (Integer, BigInt, UUID, CUID, NanoID)
- Cross-File Validation — Validates references across all schema files in the workspace
- Snippets — Common code templates for both formats
- Formatting — Auto-format schema files
Installation
- Open VS Code
- Press
Ctrl+Shift+X to open Extensions
- Search for "Jade Linter"
- Click Install
Usage
Declarative .jade (recommended for v2)
Open schema/models.jade (or any .jade file):
model User {
table = "users"
name = String(120)!
email = String(255)!
bio = Text()?
role = String(50)!default("user")
posts = hasMany(Post)
}
model Post {
title = String(255)!
content = Text()
user_id = Integer!
author = belongsTo(User)
}
Syntax is aligned with core Declarative.parsedeclarativeSchema:
Type, Type(), Type(len), Decimal(p,s) (case-insensitive)
! required (notNull) · ? nullable · !default(...) / .default(...)
- Relations:
hasMany(Model), belongsTo(Model), hasOne(Model)
- Options:
table = "...", timestamps = false, id = false
Lua Entity style (escape hatch)
Open any .lua file containing Jade schema code:
local jade = require("jade")
local User = jade.Entity("users", {
id = jade.Integer():primaryKey(),
name = jade.String(120):notNull(),
email = jade.String(255):unique():notNull(),
})
local Post = jade.Entity("posts", {
id = jade.Integer():primaryKey(),
title = jade.String(255):notNull(),
user_id = jade.Integer():foreignKey("users", "id"),
content = jade.Text(),
})
Auto-Relation Detection
The linter automatically detects relationships between entities in two ways:
Explicit :foreignKey() modifier
When a field has :foreignKey("table", "column"), the linter infers a belongsTo relation:
Post = jade.Entity("posts", {
user_id = jade.Integer():foreignKey("users", "id"),
-- Linter: "Relação 'belongsTo' inferida via 'user_id' → User"
})
_id naming convention
When a field ends with _id and the target table exists in the schema, the linter infers belongsTo automatically:
User = jade.Entity("users", { ... })
Post = jade.Entity("posts", {
user_id = jade.Integer():notNull(),
-- Linter: "Relação 'belongsTo' inferida via 'user_id' → User"
-- (works because "users" table exists in the schema)
})
Supported FK types: Integer, BigInt, UUID, CUID, NanoID.
Hover on FK fields
Hovering over a *_id field shows the inferred relation:
**user_id** (ForeignKey)
Infers: belongsTo → User
Diagnostics
The linter reports three levels of diagnostics:
| Severity |
Example |
| Error |
Invalid type (jade.Foo()), unknown modifier (:bar()), missing model reference |
| Warning |
String without length, created_at without defaultNow() |
| Information |
Auto primary key on id, inferred belongsTo relation |
Snippets
| Prefix |
Description |
jade-entity |
Entity definition with primary key |
jade-field |
Field definition with type |
jade-relation |
Relation definition |
Configuration
| Setting |
Default |
Description |
jade.schema.path |
schema/init.lua |
Path to schema file |
jade.linting.enabled |
true |
Enable linting |
jade.completion.enabled |
true |
Enable auto-completion |
jade.formatting.enabled |
true |
Enable formatting |
jade.formatting.formatOnSave |
false |
Format on save |
Commands
| Command |
Description |
Jade: Restart LSP Server |
Restart the language server |
License
MIT