1 /** 2 * WARNING: automatically generated by ort 0.14.1. 3 * DO NOT EDIT! 4 * @packageDocumentation 5 */ 6 7 import bcrypt from 'bcrypt'; 8 import Database from 'better-sqlite3'; 9 10 /** 11 * Namespace for data interfaces and representative classes. The 12 * interfaces are for the data itself, while the classes manage roles and 13 * metadata. 14 */ 15 export namespace ortns 16 { 17 /** 18 * Birthsex of individual 19 */ 20 export enum sex 21 { 22 /** 23 * Male 24 */ 25 male = '0', 26 /** 27 * Female 28 */ 29 female = '1', 30 /** 31 * Other 32 */ 33 other = '2' 34 } 35 36 /** 37 * Controlling organisation. 38 */ 39 export interface companyData 40 { 41 /** 42 * Name of the organisation. 43 */ 44 name: string; 45 id: bigint; 46 /** 47 * Simply a check for null values. 48 */ 49 somenum: bigint|null; 50 } 51 52 function db_export_company(role: string, obj: companyData): any 53 { 54 const res: any = {} 55 56 res['name'] = obj['name']; 57 res['id'] = obj['id'].toString(); 58 res['somenum'] = (obj['somenum'] === null) ? 59 null : obj['somenum'].toString(); 60 61 return res; 62 } 63 64 /** 65 * Class instance of {@link ortns.companyData}. 66 */ 67 export class company 68 { 69 readonly #role: string; 70 readonly obj: ortns.companyData; 71 72 /** 73 * A {@link ortns.companyData} as extracted from the database in 74 * a particular role. 75 * @param role The role in which this was extracted from the 76 * database. When exported, this role will be checked for 77 * permission to export. 78 * @param obj The raw data. 79 */ 80 constructor(role: string, obj: ortns.companyData) 81 { 82 this.#role = role; 83 this.obj = obj; 84 } 85 86 /** 87 * Export the contained {@link ortns.companyData} respecting 88 * fields not exported, roles, etc. It's safe to call 89 * `JSON.stringify()` on the returned object to write responses. 90 */ 91 export(): any 92 { 93 return db_export_company(this.#role, this.obj); 94 } 95 } 96 97 /** 98 * A regular user. 99 */ 100 export interface userData 101 { 102 /** 103 * This struct will be filled in from an inner join 104 * on the "cid" variable. 105 */ 106 company: ortns.companyData; 107 /** 108 * A foreign key reference. 109 */ 110 cid: bigint; 111 /** 112 * User's birth sex. 113 */ 114 sex: ortns.sex; 115 /** 116 * Password hash. 117 * This is passed to inserts and updates as a password, 118 * then hashed within the implementation and extracted 119 * (in listings and searches) as the hash value. 120 */ 121 hash: string; 122 /** 123 * Unique e-mail address. 124 */ 125 email: string; 126 /** 127 * A PNG image or something. 128 */ 129 image: Buffer|null; 130 /** 131 * User's full name. 132 */ 133 name: string; 134 uid: bigint; 135 } 136 137 function db_export_user(role: string, obj: userData): any 138 { 139 const res: any = {} 140 141 res['company'] = db_export_company(role, obj['company']) 142 res['cid'] = obj['cid'].toString(); 143 res['sex'] = obj['sex']; 144 /** 145 * Don't output hash: password. 146 */ 147 res['email'] = obj['email']; 148 res['image'] = (obj['image'] === null) ? 149 null : obj['image'].toString('base64'); 150 res['name'] = obj['name']; 151 res['uid'] = obj['uid'].toString(); 152 153 return res; 154 } 155 156 /** 157 * Class instance of {@link ortns.userData}. 158 */ 159 export class user 160 { 161 readonly #role: string; 162 readonly obj: ortns.userData; 163 164 /** 165 * A {@link ortns.userData} as extracted from the database in a 166 * particular role. 167 * @param role The role in which this was extracted from the 168 * database. When exported, this role will be checked for 169 * permission to export. 170 * @param obj The raw data. 171 */ 172 constructor(role: string, obj: ortns.userData) 173 { 174 this.#role = role; 175 this.obj = obj; 176 } 177 178 /** 179 * Export the contained {@link ortns.userData} respecting fields 180 * not exported, roles, etc. It's safe to call 181 * `JSON.stringify()` on the returned object to write responses. 182 */ 183 export(): any 184 { 185 return db_export_user(this.#role, this.obj); 186 } 187 } 188 189 /** 190 * Authenticated session. 191 */ 192 export interface sessionData 193 { 194 user: ortns.userData; 195 /** 196 * Associated user. 197 */ 198 userid: bigint; 199 /** 200 * Random cookie. 201 */ 202 token: bigint; 203 mtime: bigint; 204 id: bigint; 205 } 206 207 function db_export_session(role: string, obj: sessionData): any 208 { 209 const res: any = {} 210 211 res['user'] = db_export_user(role, obj['user']) 212 res['userid'] = obj['userid'].toString(); 213 res['token'] = obj['token'].toString(); 214 res['mtime'] = obj['mtime'].toString(); 215 res['id'] = obj['id'].toString(); 216 217 return res; 218 } 219 220 /** 221 * Class instance of {@link ortns.sessionData}. 222 */ 223 export class session 224 { 225 readonly #role: string; 226 readonly obj: ortns.sessionData; 227 228 /** 229 * A {@link ortns.sessionData} as extracted from the database in 230 * a particular role. 231 * @param role The role in which this was extracted from the 232 * database. When exported, this role will be checked for 233 * permission to export. 234 * @param obj The raw data. 235 */ 236 constructor(role: string, obj: ortns.sessionData) 237 { 238 this.#role = role; 239 this.obj = obj; 240 } 241 242 /** 243 * Export the contained {@link ortns.sessionData} respecting 244 * fields not exported, roles, etc. It's safe to call 245 * `JSON.stringify()` on the returned object to write responses. 246 */ 247 export(): any 248 { 249 return db_export_session(this.#role, this.obj); 250 } 251 } 252 } 253 254 namespace ortstmt 255 { 256 export enum ortstmt 257 { 258 STMT_company_BY_UNIQUE_id, 259 STMT_company_BY_SEARCH_0, 260 STMT_company_INSERT, 261 STMT_company_DELETE_0, 262 STMT_user_BY_UNIQUE_email, 263 STMT_user_BY_UNIQUE_uid, 264 STMT_user_BY_SEARCH_0, 265 STMT_user_BY_SEARCH_1, 266 STMT_user_BY_SEARCH_2, 267 STMT_user_INSERT, 268 STMT_user_UPDATE_0, 269 STMT_user_UPDATE_1, 270 STMT_user_DELETE_0, 271 STMT_session_BY_UNIQUE_id, 272 STMT_session_BY_SEARCH_0, 273 STMT_session_INSERT, 274 STMT_session_DELETE_0, 275 } 276 277 export function stmtBuilder(idx: ortstmt): string 278 { 279 return ortstmts[idx]; 280 } 281 282 const ortstmts: readonly string[] = 283 [ 284 /* STMT_company_BY_UNIQUE_id */ 285 'SELECT ' + ort_schema_company('company') + ' FROM company WHERE company.id = ?', 286 /* STMT_company_BY_SEARCH_0 */ 287 'SELECT ' + ort_schema_company('company') + ' FROM company ' 288 + 'WHERE company.somenum ISNULL', 289 /* STMT_company_INSERT */ 290 'INSERT INTO company (name,somenum) VALUES (?,?)', 291 /* STMT_company_DELETE_0 */ 292 'DELETE FROM company', 293 /* STMT_user_BY_UNIQUE_email */ 294 'SELECT ' + ort_schema_user('user') + ',' + ort_schema_company('_a') + ' FROM user ' 295 + 'INNER JOIN company AS _a ON _a.id=user.cid ' 296 + 'WHERE user.email = ?', 297 /* STMT_user_BY_UNIQUE_uid */ 298 'SELECT ' + ort_schema_user('user') + ',' + ort_schema_company('_a') + ' FROM user ' 299 + 'INNER JOIN company AS _a ON _a.id=user.cid ' 300 + 'WHERE user.uid = ?', 301 /* STMT_user_BY_SEARCH_0 */ 302 'SELECT ' + ort_schema_user('user') + ',' + ort_schema_company('_a') + ' FROM user ' 303 + 'INNER JOIN company AS _a ON _a.id=user.cid ' 304 + 'WHERE user.name = ? LIMIT 5', 305 /* STMT_user_BY_SEARCH_1 */ 306 'SELECT ' + ort_schema_user('user') + ',' + ort_schema_company('_a') + ' FROM user ' 307 + 'INNER JOIN company AS _a ON _a.id=user.cid ' 308 + 'WHERE user.email = ?', 309 /* STMT_user_BY_SEARCH_2 */ 310 'SELECT ' + ort_schema_user('user') + ',' + ort_schema_company('_a') + ' FROM user ' 311 + 'INNER JOIN company AS _a ON _a.id=user.cid ' 312 + 'WHERE user.uid = ? ORDER BY _a.name ASC', 313 /* STMT_user_INSERT */ 314 'INSERT INTO user (cid,sex,hash,email,image,name) VALUES ' 315 + '(?,?,?,?,?,?)', 316 /* STMT_user_UPDATE_0 */ 317 'UPDATE user SET hash = ? WHERE uid = ?', 318 /* STMT_user_UPDATE_1 */ 319 'UPDATE user SET email = ? WHERE uid = ?', 320 /* STMT_user_DELETE_0 */ 321 'DELETE FROM user', 322 /* STMT_session_BY_UNIQUE_id */ 323 'SELECT ' + ort_schema_session('session') + ',' + ort_schema_user('_b') + ',' 324 + ort_schema_company('_c') + ' FROM session ' 325 + 'INNER JOIN user AS _b ON _b.uid=session.userid ' 326 + 'INNER JOIN company AS _c ON _c.id=_b.cid ' 327 + 'WHERE session.id = ?', 328 /* STMT_session_BY_SEARCH_0 */ 329 'SELECT ' + ort_schema_session('session') + ',' + ort_schema_user('_b') + ',' 330 + ort_schema_company('_c') + ' FROM session ' 331 + 'INNER JOIN user AS _b ON _b.uid=session.userid ' 332 + 'INNER JOIN company AS _c ON _c.id=_b.cid ' 333 + 'WHERE _c.name = ? AND session.mtime = ?', 334 /* STMT_session_INSERT */ 335 'INSERT INTO session (userid,token,mtime) VALUES (?,?,?)', 336 /* STMT_session_DELETE_0 */ 337 'DELETE FROM session WHERE id = ?', 338 ]; 339 340 function ort_schema_company(v: string): string 341 { 342 return v + '.name' + ',' + 343 v + '.id' + ',' + 344 v + '.somenum'; 345 } 346 347 function ort_schema_user(v: string): string 348 { 349 return v + '.cid' + ',' + 350 v + '.sex' + ',' + 351 v + '.hash' + ',' + 352 v + '.email' + ',' + 353 v + '.image' + ',' + 354 v + '.name' + ',' + 355 v + '.uid'; 356 } 357 358 function ort_schema_session(v: string): string 359 { 360 return v + '.userid' + ',' + 361 v + '.token' + ',' + 362 v + '.mtime' + ',' + 363 v + '.id'; 364 } 365 } 366 367 /** 368 * Manages each sequence of database interaction. 369 */ 370 export class ortctx 371 { 372 #role: string = 'default'; 373 readonly #o: ortdb; 374 375 constructor(o: ortdb) 376 { 377 this.#o = o; 378 } 379 380 /** 381 * Open a transaction with a unique identifier. This is the 382 * preferred way of creating database transactions. The transaction 383 * immediately enters unshared lock mode (single writer, readers 384 * allowed). 385 * @param id The unique identifier. 386 * @throws Throws on database error. 387 */ 388 db_trans_open_immediate(id: number): void 389 { 390 this.#o.db.exec('BEGIN TRANSACTION IMMEDIATE'); 391 } 392 393 /** 394 * Open a transaction with a unique identifier. The transaction 395 * locks the database on first access with shared locks (no writes 396 * allowed, reads allowed) on queries and unshared locks (single 397 * writer, reads allowed) on modification. 398 * @param id The unique identifier. 399 * @throws Throws on database error. 400 */ 401 db_trans_open_deferred(id: number): void 402 { 403 this.#o.db.exec('BEGIN TRANSACTION DEFERRED'); 404 } 405 406 /** 407 * Open a transaction with a unique identifier. The transaction 408 * locks exclusively, preventing all other access. 409 * @param id The unique identifier. 410 * @throws Throws on database error. 411 */ 412 db_trans_open_exclusive(id: number): void 413 { 414 this.#o.db.exec('BEGIN TRANSACTION EXCLUSIVE'); 415 } 416 417 /** 418 * Roll-back a transaction opened by {@link db_trans_open_immediate} 419 * or similar. 420 * @param id The transaction identifier. 421 * @throws Throws on database error. 422 */ 423 db_trans_rollback(id: number): void 424 { 425 this.#o.db.exec('ROLLBACK TRANSACTION'); 426 } 427 428 /** 429 * Commit a transaction opened by {@link db_trans_open_immediate} or 430 * similar. 431 * @param id The transaction identifier. 432 * @throws Throws on database error. 433 */ 434 db_trans_commit(id: number): void 435 { 436 this.#o.db.exec('COMMIT TRANSACTION'); 437 } 438 439 private db_company_fill(data: {row: any[], pos: number}): 440 ortns.companyData 441 { 442 const obj: ortns.companyData = { 443 'name': <string>data.row[data.pos + 0], 444 'id': <bigint>data.row[data.pos + 1], 445 'somenum': <bigint|null>data.row[data.pos + 2], 446 }; 447 data.pos += 3; 448 return obj; 449 } 450 451 /** 452 * Insert a row. Accepts all native fields as parameters excluding 453 * rowid, which is automatically set by the database. If any fields 454 * are specified as null, they may be passed as null values. 455 * @param v1 name 456 * @param v2 somenum 457 * @return Row identifier on success or -1 on constraint violation. 458 * @throws Throws on database error. 459 */ 460 db_company_insert(v1: string, v2: bigint|null): bigint 461 { 462 const parms: any[] = []; 463 let info: Database.RunResult; 464 const stmt: Database.Statement = 465 this.#o.db.prepare(ortstmt.stmtBuilder 466 (ortstmt.ortstmt.STMT_company_INSERT)); 467 468 parms.push(v1); 469 parms.push(v2); 470 471 try { 472 info = stmt.run(parms); 473 } catch (er) { 474 if (er.code === 'SQLITE_CONSTRAINT_UNIQUE' || 475 er.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') 476 return BigInt(-1); 477 throw er; 478 } 479 480 return BigInt(info.lastInsertRowid.toString()); 481 } 482 483 /** 484 * Search for a set of {@link ortns.company}. 485 * The following fields are constrained by unary operations: 486 * somenum (checked is null) 487 * @return Result of null if no results found. 488 * @throws Throws on database error. 489 */ 490 db_company_list_by_somenum_isnull(): ortns.company[] 491 { 492 const parms: any[] = []; 493 const stmt: Database.Statement = 494 this.#o.db.prepare(ortstmt.stmtBuilder 495 (ortstmt.ortstmt.STMT_company_BY_SEARCH_0)); 496 stmt.raw(true); 497 498 const rows: any[] = stmt.all(parms); 499 const objs: ortns.company[] = []; 500 let i: number; 501 502 for (i = 0; i < rows.length; i++) { 503 const obj: ortns.companyData = 504 this.db_company_fill({row: <any[]>rows[i], pos: 0}); 505 objs.push(new ortns.company(this.#role, obj)); 506 } 507 return objs; 508 } 509 510 /** 511 * @throws Throws on database error. 512 */ 513 db_company_delete(): void 514 { 515 const parms: any[] = []; 516 let info: Database.RunResult; 517 const stmt: Database.Statement = 518 this.#o.db.prepare(ortstmt.stmtBuilder 519 (ortstmt.ortstmt.STMT_company_DELETE_0)); 520 521 522 stmt.run(parms); 523 } 524 525 private db_user_fill(data: {row: any[], pos: number}): 526 ortns.userData 527 { 528 const obj: ortns.userData = { 529 /* A dummy value for now. */ 530 'company': <ortns.companyData>{}, 531 'cid': <bigint>data.row[data.pos + 0], 532 'sex': <ortns.sex>data.row[data.pos + 1].toString(), 533 'hash': <string>data.row[data.pos + 2], 534 'email': <string>data.row[data.pos + 3], 535 'image': <Buffer|null>data.row[data.pos + 4], 536 'name': <string>data.row[data.pos + 5], 537 'uid': <bigint>data.row[data.pos + 6], 538 }; 539 data.pos += 7; 540 obj.company = this.db_company_fill(data); 541 return obj; 542 } 543 544 /** 545 * Insert a row. Accepts all native fields as parameters excluding 546 * rowid, which is automatically set by the database. If any fields 547 * are specified as null, they may be passed as null values. 548 * @param v1 cid 549 * @param v2 sex 550 * @param v3 hash 551 * @param v4 email 552 * @param v5 image 553 * @param v6 name 554 * @return Row identifier on success or -1 on constraint violation. 555 * @throws Throws on database error. 556 */ 557 db_user_insert(v1: bigint, v2: ortns.sex, v3: string, v4: string, 558 v5: Buffer|null, v6: string): bigint 559 { 560 const parms: any[] = []; 561 let info: Database.RunResult; 562 const stmt: Database.Statement = 563 this.#o.db.prepare(ortstmt.stmtBuilder 564 (ortstmt.ortstmt.STMT_user_INSERT)); 565 566 parms.push(v1); 567 parms.push(v2); 568 parms.push(bcrypt.hashSync(v3, this.#o.args.bcrypt_cost)); 569 parms.push(v4); 570 parms.push(v5); 571 parms.push(v6); 572 573 try { 574 info = stmt.run(parms); 575 } catch (er) { 576 if (er.code === 'SQLITE_CONSTRAINT_UNIQUE' || 577 er.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') 578 return BigInt(-1); 579 throw er; 580 } 581 582 return BigInt(info.lastInsertRowid.toString()); 583 } 584 585 /** 586 * Create a function that searches for users by a given 587 * name; and, when found, invokes a callback function 588 * provided the user structure. 589 * The callback is called during an implicit transaction: thus, it 590 * should not invoke any database modifications or risk deadlock. 591 * @param v1 name 592 * @param cb Callback with retrieved data. 593 * @throws Throws on database error. 594 */ 595 db_user_iterate_by_name_eq(v1: string, 596 cb: (res: ortns.user) => void): void 597 { 598 const parms: any[] = []; 599 const stmt: Database.Statement = 600 this.#o.db.prepare(ortstmt.stmtBuilder 601 (ortstmt.ortstmt.STMT_user_BY_SEARCH_0)); 602 stmt.raw(true); 603 604 parms.push(v1); 605 606 for (const cols of stmt.iterate(parms)) { 607 const obj: ortns.userData = 608 this.db_user_fill({row: <any>cols, pos: 0}); 609 cb(new ortns.user(this.#role, obj)); 610 } 611 } 612 613 /** 614 * Search for a unique user with their e-mail and 615 * password. 616 * This is a quick way to verify that a user has entered 617 * the correct password for logging in. 618 * @param v1 email 619 * @param v2 hash (hashed password) 620 * @return Result or null if no results found. 621 * @throws Throws on database error. 622 */ 623 db_user_get_creds(v1: string, v2: string): ortns.user|null 624 { 625 const parms: any[] = []; 626 const stmt: Database.Statement = 627 this.#o.db.prepare(ortstmt.stmtBuilder 628 (ortstmt.ortstmt.STMT_user_BY_SEARCH_1)); 629 stmt.raw(true); 630 631 parms.push(v1); 632 633 const cols: any = stmt.get(parms); 634 635 if (typeof cols === 'undefined') 636 return null; 637 const obj: ortns.userData = 638 this.db_user_fill({row: <any[]>cols, pos: 0}); 639 if (!bcrypt.compareSync(v2, obj.hash)) 640 return null; 641 return new ortns.user(this.#role, obj); 642 } 643 644 /** 645 * Lookup by unique identifier. 646 * @param v1 uid 647 * @return Result or null if no results found. 648 * @throws Throws on database error. 649 */ 650 db_user_get_by_uid_eq(v1: bigint): ortns.user|null 651 { 652 const parms: any[] = []; 653 const stmt: Database.Statement = 654 this.#o.db.prepare(ortstmt.stmtBuilder 655 (ortstmt.ortstmt.STMT_user_BY_SEARCH_2)); 656 stmt.raw(true); 657 658 parms.push(v1); 659 660 const cols: any = stmt.get(parms); 661 662 if (typeof cols === 'undefined') 663 return null; 664 const obj: ortns.userData = 665 this.db_user_fill({row: <any[]>cols, pos: 0}); 666 return new ortns.user(this.#role, obj); 667 } 668 669 /** 670 * @throws Throws on database error. 671 */ 672 db_user_delete(): void 673 { 674 const parms: any[] = []; 675 let info: Database.RunResult; 676 const stmt: Database.Statement = 677 this.#o.db.prepare(ortstmt.stmtBuilder 678 (ortstmt.ortstmt.STMT_user_DELETE_0)); 679 680 681 stmt.run(parms); 682 } 683 684 /** 685 * @param v1 update hash (hashed) 686 * @param v2 constraint uid (eq) 687 * @return False on constraint violation, true on success. 688 * @throws Throws on database error. 689 */ 690 db_user_update_hash_set_by_uid_eq(v1: string, v2: bigint): boolean 691 { 692 const parms: any[] = []; 693 let info: Database.RunResult; 694 const stmt: Database.Statement = 695 this.#o.db.prepare(ortstmt.stmtBuilder 696 (ortstmt.ortstmt.STMT_user_UPDATE_0)); 697 698 parms.push(bcrypt.hashSync(v1, this.#o.args.bcrypt_cost)); 699 parms.push(v2); 700 701 try { 702 info = stmt.run(parms); 703 } catch (er) { 704 if (er.code === 'SQLITE_CONSTRAINT_UNIQUE' || 705 er.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') 706 return false; 707 throw er; 708 } 709 710 return true; 711 } 712 713 /** 714 * @param v1 update email 715 * @param v2 constraint uid (eq) 716 * @return False on constraint violation, true on success. 717 * @throws Throws on database error. 718 */ 719 db_user_update_email_set_by_uid_eq(v1: string, v2: bigint): 720 boolean 721 { 722 const parms: any[] = []; 723 let info: Database.RunResult; 724 const stmt: Database.Statement = 725 this.#o.db.prepare(ortstmt.stmtBuilder 726 (ortstmt.ortstmt.STMT_user_UPDATE_1)); 727 728 parms.push(v1); 729 parms.push(v2); 730 731 try { 732 info = stmt.run(parms); 733 } catch (er) { 734 if (er.code === 'SQLITE_CONSTRAINT_UNIQUE' || 735 er.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') 736 return false; 737 throw er; 738 } 739 740 return true; 741 } 742 743 private db_session_fill(data: {row: any[], pos: number}): 744 ortns.sessionData 745 { 746 const obj: ortns.sessionData = { 747 /* A dummy value for now. */ 748 'user': <ortns.userData>{}, 749 'userid': <bigint>data.row[data.pos + 0], 750 'token': <bigint>data.row[data.pos + 1], 751 'mtime': <bigint>data.row[data.pos + 2], 752 'id': <bigint>data.row[data.pos + 3], 753 }; 754 data.pos += 4; 755 obj.user = this.db_user_fill(data); 756 return obj; 757 } 758 759 /** 760 * Insert a row. Accepts all native fields as parameters excluding 761 * rowid, which is automatically set by the database. If any fields 762 * are specified as null, they may be passed as null values. 763 * @param v1 userid 764 * @param v2 token 765 * @param v3 mtime 766 * @return Row identifier on success or -1 on constraint violation. 767 * @throws Throws on database error. 768 */ 769 db_session_insert(v1: bigint, v2: bigint, v3: bigint): bigint 770 { 771 const parms: any[] = []; 772 let info: Database.RunResult; 773 const stmt: Database.Statement = 774 this.#o.db.prepare(ortstmt.stmtBuilder 775 (ortstmt.ortstmt.STMT_session_INSERT)); 776 777 parms.push(v1); 778 parms.push(v2); 779 parms.push(v3); 780 781 try { 782 info = stmt.run(parms); 783 } catch (er) { 784 if (er.code === 'SQLITE_CONSTRAINT_UNIQUE' || 785 er.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') 786 return BigInt(-1); 787 throw er; 788 } 789 790 return BigInt(info.lastInsertRowid.toString()); 791 } 792 793 /** 794 * Search for company's logged-in users. 795 * The callback is called during an implicit transaction: thus, it 796 * should not invoke any database modifications or risk deadlock. 797 * @param v1 user.company.name 798 * @param v2 mtime 799 * @param cb Callback with retrieved data. 800 * @throws Throws on database error. 801 */ 802 db_session_iterate_foo(v1: string, v2: bigint, 803 cb: (res: ortns.session) => void): void 804 { 805 const parms: any[] = []; 806 const stmt: Database.Statement = 807 this.#o.db.prepare(ortstmt.stmtBuilder 808 (ortstmt.ortstmt.STMT_session_BY_SEARCH_0)); 809 stmt.raw(true); 810 811 parms.push(v1); 812 parms.push(v2); 813 814 for (const cols of stmt.iterate(parms)) { 815 const obj: ortns.sessionData = 816 this.db_session_fill({row: <any>cols, pos: 0}); 817 cb(new ortns.session(this.#role, obj)); 818 } 819 } 820 821 /** 822 * @param v1 constraint id (eq) 823 * @throws Throws on database error. 824 */ 825 db_session_delete_by_id_eq(v1: bigint): void 826 { 827 const parms: any[] = []; 828 let info: Database.RunResult; 829 const stmt: Database.Statement = 830 this.#o.db.prepare(ortstmt.stmtBuilder 831 (ortstmt.ortstmt.STMT_session_DELETE_0)); 832 833 parms.push(v1); 834 835 stmt.run(parms); 836 } 837 } 838 839 /** 840 * Interface configuration. 841 */ 842 export interface ortargs 843 { 844 /** 845 * The number of rounds when bcrypting passwords. 846 */ 847 bcrypt_cost: number; 848 } 849 850 /** 851 * Application-wide database instance. There should only be one of these 852 * per server. 853 */ 854 export class ortdb 855 { 856 readonly args: ortargs; 857 readonly db: Database.Database; 858 859 /** 860 * The version of ort-nodejs used to create the module. 861 */ 862 readonly version: string = '0.14.1'; 863 864 /** 865 * The numeric version of ort-nodejs used to create the module. 866 */ 867 readonly vstamp: number = 11502; 868 869 /** 870 * Do not call this: use {@link ort} instead. 871 */ 872 constructor(dbname: string, args?: ortargs) 873 { 874 this.db = new Database(dbname); 875 this.db.defaultSafeIntegers(true); 876 if (typeof args !== 'undefined') { 877 this.args = Object.assign({}, args); 878 } else { 879 this.args = { bcrypt_cost: 10 }; 880 } 881 } 882 883 /** 884 * Connect to the database. This should be invoked for each request. 885 * In applications not having a request, this corresponds to a single 886 * operator sequence. If roles are enabled, the connection will 887 * begin in the "default" role. 888 */ 889 connect(): ortctx 890 { 891 return new ortctx(this); 892 } 893 } 894 895 /** 896 * Create an application-wide database instance. This should only be 897 * called once per server. 898 * @param dbname An existing sqlite3 database. 899 * @param args Optional configuration parameters. If not given, the 900 * number of bcrypt rounds defaults to 10. 901 * @throws Throws on database error. 902 */ 903 export function ort(dbname: string, args?: optargs): ortdb 904 { 905 return new ortdb(dbname, args); 906 }