()
| 643 | * operator can tell at a glance whether the schema is fully migrated. |
| 644 | */ |
| 645 | async function getPostgresMigrationStatus(): Promise<JSONObject> { |
| 646 | const result: JSONObject = { |
| 647 | connected: false, |
| 648 | isUpToDate: false, |
| 649 | totalDefined: 0, |
| 650 | totalApplied: 0, |
| 651 | totalPending: 0, |
| 652 | latestDefinedMigration: null, |
| 653 | latestAppliedMigration: null, |
| 654 | pendingMigrations: [], |
| 655 | }; |
| 656 | |
| 657 | try { |
| 658 | // Source-of-truth list of schema migrations compiled into this build. |
| 659 | const definedNames: Array<string> = distinctNames( |
| 660 | (PostgresSchemaMigrations as Array<new () => { name: string }>).map( |
| 661 | (MigrationClass: new () => { name: string }): string => { |
| 662 | return new MigrationClass().name; |
| 663 | }, |
| 664 | ), |
| 665 | ); |
| 666 | |
| 667 | result["totalDefined"] = definedNames.length; |
| 668 | |
| 669 | // Newest migration this build knows about (highest epoch timestamp in name). |
| 670 | const latestDefined: string | undefined = [...definedNames] |
| 671 | .sort((a: string, b: string): number => { |
| 672 | return ( |
| 673 | (parseMigrationTimestamp(a) || 0) - (parseMigrationTimestamp(b) || 0) |
| 674 | ); |
| 675 | }) |
| 676 | .pop(); |
| 677 | |
| 678 | if (latestDefined) { |
| 679 | result["latestDefinedMigration"] = { |
| 680 | name: latestDefined, |
| 681 | timestamp: parseMigrationTimestamp(latestDefined), |
| 682 | }; |
| 683 | } |
| 684 | |
| 685 | const dataSource: ReturnType<typeof PostgresAppInstance.getDataSource> = |
| 686 | PostgresAppInstance.getDataSource(); |
| 687 | |
| 688 | if (!dataSource) { |
| 689 | return result; |
| 690 | } |
| 691 | |
| 692 | const rows: Array<{ name: string; timestamp: string }> = |
| 693 | await dataSource.query( |
| 694 | "SELECT name, timestamp FROM migrations ORDER BY timestamp ASC", |
| 695 | ); |
| 696 | |
| 697 | result["connected"] = true; |
| 698 | result["totalApplied"] = rows.length; |
| 699 | |
| 700 | const appliedNames: Set<string> = new Set( |
| 701 | rows.map((row: { name: string }): string => { |
| 702 | return row.name; |
no test coverage detected