or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

associations.mddata-types.mddatabase-connection.mderror-handling.mdhooks.mdindex.mdmodel-definition.mdquery-operators.mdquerying.mdtransactions.md

model-definition.mddocs/

0

# Model Definition

1

2

Model creation, configuration, and lifecycle management including attributes, validations, scopes, and schema operations.

3

4

## Capabilities

5

6

### Model Initialization

7

8

Initialize a model with attributes and configuration options.

9

10

```typescript { .api }

11

/**

12

* Initialize model with attributes and options

13

* @param attributes - Model attribute definitions

14

* @param options - Model configuration options

15

* @returns The initialized model class

16

*/

17

static init(attributes: ModelAttributes, options: InitOptions): typeof Model;

18

19

interface ModelAttributes {

20

[name: string]: DataType | ModelAttributeColumnOptions;

21

}

22

23

interface ModelAttributeColumnOptions {

24

/** Column data type */

25

type: DataType;

26

/** Allow null values */

27

allowNull?: boolean;

28

/** Default value */

29

defaultValue?: any;

30

/** Primary key column */

31

primaryKey?: boolean;

32

/** Unique constraint */

33

unique?: boolean | string | { name: string; msg?: string };

34

/** Auto increment (integers only) */

35

autoIncrement?: boolean;

36

/** Column comment */

37

comment?: string;

38

/** Custom column name */

39

field?: string;

40

/** Validation rules */

41

validate?: ModelValidateOptions;

42

/** Virtual field getter */

43

get?: () => any;

44

/** Virtual field setter */

45

set?: (value: any) => void;

46

}

47

48

interface InitOptions {

49

/** Sequelize instance */

50

sequelize: Sequelize;

51

/** Model name */

52

modelName?: string;

53

/** Table name */

54

tableName?: string;

55

/** Schema name */

56

schema?: string;

57

/** Enable timestamps (createdAt, updatedAt) */

58

timestamps?: boolean;

59

/** Paranoid mode (soft delete) */

60

paranoid?: boolean;

61

/** Use underscored column names */

62

underscored?: boolean;

63

/** Freeze table name (disable pluralization) */

64

freezeTableName?: boolean;

65

/** Table indexes */

66

indexes?: IndexesOptions[];

67

/** Model hooks */

68

hooks?: Partial<ModelHooks>;

69

/** Model scopes */

70

scopes?: ModelScopeOptions;

71

/** Default scope */

72

defaultScope?: FindOptions;

73

/** Model validation options */

74

validate?: ModelValidateOptions;

75

}

76

```

77

78

**Usage Examples:**

79

80

```typescript

81

import { Model, DataTypes, Sequelize } from "sequelize";

82

83

const sequelize = new Sequelize("sqlite::memory:");

84

85

// Basic model definition

86

class User extends Model {}

87

User.init({

88

firstName: DataTypes.STRING,

89

lastName: DataTypes.STRING,

90

email: DataTypes.STRING

91

}, {

92

sequelize,

93

modelName: 'user'

94

});

95

96

// Advanced model with all options

97

class Product extends Model {

98

public id!: number;

99

public name!: string;

100

public price!: number;

101

public description?: string;

102

public createdAt!: Date;

103

public updatedAt!: Date;

104

}

105

106

Product.init({

107

id: {

108

type: DataTypes.INTEGER,

109

primaryKey: true,

110

autoIncrement: true

111

},

112

name: {

113

type: DataTypes.STRING(100),

114

allowNull: false,

115

unique: true,

116

validate: {

117

len: [3, 100],

118

notEmpty: true

119

}

120

},

121

price: {

122

type: DataTypes.DECIMAL(10, 2),

123

allowNull: false,

124

validate: {

125

min: 0

126

}

127

},

128

description: {

129

type: DataTypes.TEXT,

130

allowNull: true

131

},

132

slug: {

133

type: DataTypes.VIRTUAL,

134

get() {

135

return this.name.toLowerCase().replace(/\s+/g, '-');

136

}

137

}

138

}, {

139

sequelize,

140

modelName: 'product',

141

tableName: 'products',

142

timestamps: true,

143

paranoid: true,

144

underscored: true,

145

indexes: [

146

{ fields: ['name'] },

147

{ fields: ['price'] }

148

]

149

});

150

```

151

152

### Model Schema Operations

153

154

Synchronize and manage model schemas in the database.

155

156

```typescript { .api }

157

/**

158

* Sync model with database

159

* @param options - Sync options

160

* @returns Promise resolving to the model class

161

*/

162

static sync(options?: SyncOptions): Promise<typeof Model>;

163

164

/**

165

* Drop model table from database

166

* @param options - Drop options

167

* @returns Promise resolving when table is dropped

168

*/

169

static drop(options?: DropOptions): Promise<void>;

170

171

/**

172

* Get table name for the model

173

* @returns Table name

174

*/

175

static getTableName(): string | { tableName: string; schema?: string; };

176

177

/**

178

* Describe table structure

179

* @returns Promise resolving to table description

180

*/

181

static describe(): Promise<ColumnsDescription>;

182

183

interface DropOptions {

184

/** Also drop dependent objects */

185

cascade?: boolean;

186

/** SQL query logging */

187

logging?: boolean | ((sql: string, timing?: number) => void);

188

}

189

```

190

191

**Usage Examples:**

192

193

```typescript

194

// Sync individual model

195

await User.sync();

196

197

// Force recreate table

198

await User.sync({ force: true });

199

200

// Drop table

201

await User.drop();

202

203

// Get table information

204

const tableName = User.getTableName();

205

const description = await User.describe();

206

```

207

208

### Model Validation

209

210

Define validation rules for model attributes and instances.

211

212

```typescript { .api }

213

interface ModelValidateOptions {

214

/** Built-in validators */

215

is?: string | RegExp;

216

not?: string | RegExp;

217

isEmail?: boolean;

218

isUrl?: boolean;

219

isIP?: boolean;

220

isAlpha?: boolean;

221

isAlphanumeric?: boolean;

222

isNumeric?: boolean;

223

isInt?: boolean;

224

isFloat?: boolean;

225

isDecimal?: boolean;

226

isLowercase?: boolean;

227

isUppercase?: boolean;

228

notNull?: boolean;

229

isNull?: boolean;

230

notEmpty?: boolean;

231

equals?: string;

232

contains?: string;

233

notIn?: any[][];

234

isIn?: any[][];

235

notContains?: string;

236

len?: [number, number];

237

isUUID?: number;

238

isDate?: boolean;

239

isAfter?: string;

240

isBefore?: string;

241

max?: number;

242

min?: number;

243

isCreditCard?: boolean;

244

245

/** Custom validator functions */

246

[key: string]: any;

247

}

248

249

/**

250

* Validate model instance

251

* @param options - Validation options

252

* @returns Promise that resolves if valid, rejects with ValidationError if invalid

253

*/

254

validate(options?: ValidationOptions): Promise<void>;

255

```

256

257

**Usage Examples:**

258

259

```typescript

260

class User extends Model {}

261

User.init({

262

email: {

263

type: DataTypes.STRING,

264

validate: {

265

isEmail: true,

266

notEmpty: true

267

}

268

},

269

age: {

270

type: DataTypes.INTEGER,

271

validate: {

272

min: 0,

273

max: 120,

274

isInt: true

275

}

276

},

277

username: {

278

type: DataTypes.STRING,

279

validate: {

280

len: [3, 20],

281

is: /^[a-zA-Z0-9_]+$/,

282

async isUnique(value) {

283

const user = await User.findOne({ where: { username: value } });

284

if (user) {

285

throw new Error('Username already exists');

286

}

287

}

288

}

289

}

290

}, {

291

sequelize,

292

modelName: 'user',

293

validate: {

294

// Model-level validation

295

emailOrPhone() {

296

if (!this.email && !this.phone) {

297

throw new Error('Either email or phone must be provided');

298

}

299

}

300

}

301

});

302

```

303

304

### Model Scopes

305

306

Define reusable query scopes for common filtering and inclusion patterns.

307

308

```typescript { .api }

309

interface ModelScopeOptions {

310

[scopeName: string]: FindOptions | (() => FindOptions);

311

}

312

313

/**

314

* Apply a scope to the model

315

* @param scopes - Scope names to apply

316

* @returns Scoped model class

317

*/

318

static scope(...scopes: (string | ScopeOptions)[]): typeof Model;

319

320

/**

321

* Remove all scopes from the model

322

* @returns Unscoped model class

323

*/

324

static unscoped(): typeof Model;

325

326

interface ScopeOptions {

327

method: [string, ...any[]];

328

}

329

```

330

331

**Usage Examples:**

332

333

```typescript

334

class User extends Model {}

335

User.init({

336

firstName: DataTypes.STRING,

337

lastName: DataTypes.STRING,

338

email: DataTypes.STRING,

339

isActive: DataTypes.BOOLEAN,

340

role: DataTypes.STRING

341

}, {

342

sequelize,

343

modelName: 'user',

344

scopes: {

345

// Static scope

346

active: {

347

where: { isActive: true }

348

},

349

// Dynamic scope with parameters

350

byRole: (role) => ({

351

where: { role }

352

}),

353

// Complex scope with includes

354

withOrders: {

355

include: [{ model: Order, as: 'orders' }]

356

}

357

},

358

defaultScope: {

359

where: { isActive: true }

360

}

361

});

362

363

// Using scopes

364

const activeUsers = await User.scope('active').findAll();

365

const admins = await User.scope({ method: ['byRole', 'admin'] }).findAll();

366

const usersWithOrders = await User.scope('active', 'withOrders').findAll();

367

const allUsers = await User.unscoped().findAll(); // Ignore default scope

368

```

369

370

### Instance Methods

371

372

Methods available on model instances for lifecycle management.

373

374

```typescript { .api }

375

/**

376

* Save instance to database

377

* @param options - Save options

378

* @returns Promise resolving to the saved instance

379

*/

380

save(options?: SaveOptions): Promise<this>;

381

382

/**

383

* Reload instance from database

384

* @param options - Reload options

385

* @returns Promise resolving to the reloaded instance

386

*/

387

reload(options?: FindOptions): Promise<this>;

388

389

/**

390

* Update instance attributes

391

* @param values - Values to update

392

* @param options - Update options

393

* @returns Promise resolving to the updated instance

394

*/

395

update(values: Partial<Attributes>, options?: InstanceUpdateOptions): Promise<this>;

396

397

/**

398

* Delete instance from database

399

* @param options - Destroy options

400

* @returns Promise resolving when instance is deleted

401

*/

402

destroy(options?: InstanceDestroyOptions): Promise<void>;

403

404

/**

405

* Restore soft-deleted instance

406

* @param options - Restore options

407

* @returns Promise resolving when instance is restored

408

*/

409

restore(options?: RestoreOptions): Promise<void>;

410

```

411

412

**Usage Examples:**

413

414

```typescript

415

// Create and modify instance

416

const user = User.build({ firstName: 'John', lastName: 'Doe' });

417

user.email = 'john@example.com';

418

await user.save();

419

420

// Update instance

421

await user.update({ firstName: 'Jane' });

422

423

// Reload from database

424

await user.reload();

425

426

// Soft delete (if paranoid: true)

427

await user.destroy();

428

429

// Restore soft-deleted

430

await user.restore();

431

```

432

433

### Attribute Access

434

435

Methods for getting and setting model attribute values.

436

437

```typescript { .api }

438

/**

439

* Get attribute value

440

* @param key - Attribute name

441

* @param options - Get options

442

* @returns Attribute value

443

*/

444

get(key?: string, options?: { plain?: boolean; clone?: boolean }): any;

445

446

/**

447

* Set attribute value

448

* @param key - Attribute name or object of key-value pairs

449

* @param value - Attribute value (if key is string)

450

* @param options - Set options

451

*/

452

set(key: string | object, value?: any, options?: { raw?: boolean; reset?: boolean }): void;

453

454

/**

455

* Get raw attribute value

456

* @param key - Attribute name

457

* @returns Raw attribute value

458

*/

459

getDataValue(key: string): any;

460

461

/**

462

* Set raw attribute value

463

* @param key - Attribute name

464

* @param value - Attribute value

465

*/

466

setDataValue(key: string, value: any): void;

467

468

/**

469

* Check if attribute has changed

470

* @param key - Attribute name

471

* @returns True if changed, false otherwise

472

*/

473

changed(key?: string): boolean | string[];

474

475

/**

476

* Get previous attribute value

477

* @param key - Attribute name

478

* @returns Previous value

479

*/

480

previous(key: string): any;

481

```

482

483

**Usage Example:**

484

485

```typescript

486

const user = await User.findByPk(1);

487

488

// Get values

489

const name = user.get('firstName');

490

const allValues = user.get({ plain: true });

491

492

// Set values

493

user.set('firstName', 'Jane');

494

user.set({ firstName: 'Jane', lastName: 'Smith' });

495

496

// Check for changes

497

if (user.changed()) {

498

console.log('Changed fields:', user.changed());

499

console.log('Previous name:', user.previous('firstName'));

500

}

501

502

// Raw data access

503

const rawValue = user.getDataValue('firstName');

504

user.setDataValue('firstName', 'John');

505

```

506

507

### Model Management

508

509

Static methods for managing model attributes and metadata.

510

511

```typescript { .api }

512

/**

513

* Get all model attributes

514

* @returns Object containing all attribute definitions

515

*/

516

static getAttributes(): ModelAttributes;

517

518

/**

519

* Remove an attribute from the model

520

* @param attribute - Attribute name to remove

521

*/

522

static removeAttribute(attribute: string): void;

523

524

/**

525

* Refresh model attributes from database

526

* @returns Promise resolving when attributes are refreshed

527

*/

528

static refreshAttributes(): Promise<void>;

529

530

/**

531

* Add a named scope to the model

532

* @param name - Scope name

533

* @param scope - Scope definition

534

* @param options - Scope options

535

*/

536

static addScope(name: string, scope: FindOptions | (() => FindOptions), options?: AddScopeOptions): void;

537

538

interface AddScopeOptions {

539

/** Override existing scope */

540

override?: boolean;

541

}

542

```

543

544

**Usage Examples:**

545

546

```typescript

547

// Get model attributes

548

const attributes = User.getAttributes();

549

console.log('User attributes:', Object.keys(attributes));

550

551

// Remove an attribute (e.g., after migration)

552

User.removeAttribute('deprecatedField');

553

554

// Refresh attributes after schema changes

555

await User.refreshAttributes();

556

557

// Add dynamic scopes

558

User.addScope('activeUsers', {

559

where: { isActive: true }

560

});

561

562

User.addScope('byRole', (role: string) => ({

563

where: { role }

564

}));

565

566

// Use added scopes

567

const activeUsers = await User.scope('activeUsers').findAll();

568

const admins = await User.scope({ method: ['byRole', 'admin'] }).findAll();

569

```