Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript migration #309

Merged
merged 32 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7679731
other(ts): copy parser types from bookbrainz-utils
kellnerd Jul 31, 2023
9381eee
chore(deps): update @metabrainz/bookshelf to v1.4.0
kellnerd Jul 31, 2023
9812991
refactor(types): introduce separate types for lazy-loaded properties
kellnerd Aug 3, 2023
242916d
refactor(types): replace or move old types for aliases/identifiers
kellnerd Aug 3, 2023
2d42980
fix(types): make id and default flag of aliases optional
kellnerd Aug 3, 2023
cc35dcb
refactor(types): replace redundant old type definition of parsed alias
kellnerd Aug 7, 2023
6b9235a
other(ts): export a type for the ORM
kellnerd Aug 7, 2023
3134f41
refactor(types): define type EntityTypeString based on a constant array
kellnerd Aug 7, 2023
fdcf333
refactor(func): make use of ENTITY_TYPES and EntityTypeString
kellnerd Aug 7, 2023
a2307f5
fix(import): add missing ORM parameter
kellnerd Aug 7, 2023
a93bc48
other(ts): add type definitions to import creation functions
kellnerd Aug 7, 2023
df6ddcb
other(ts): create a return type for `getEntitySetMetadataByType`
kellnerd Aug 7, 2023
53805a0
chore(deps): install types for pg
kellnerd Sep 1, 2023
959cc8e
other(ts): migrate recursivelyGetAreaParentsWithNames to TypeScript
kellnerd Sep 1, 2023
289a68e
other(ts): rename last remaining .js module in func/ to .ts
kellnerd Sep 1, 2023
aa539c2
other(ts): convert utils to TypeScript
kellnerd Sep 1, 2023
2f861f8
other(ts): use ORM type everywhere
kellnerd Sep 1, 2023
436984d
other(ts): type raw query result of `loadAuthorNames`
kellnerd Sep 1, 2023
a335e30
other(ts): type raw query result of `getEdition(Group)sCreditedToAuthor`
kellnerd Sep 1, 2023
a553d13
other(ts): add type definitions to Alias model
kellnerd Sep 1, 2023
e3c529f
other(ts): add minimal type definitions to all bookshelf models
kellnerd Sep 1, 2023
0335676
other(ts): use the vague `Bookshelf.ModelSubclass` type for set models
kellnerd Sep 1, 2023
b699ab0
refactor(models): replace `Model.forge()` with `new Model()`
kellnerd Sep 1, 2023
ee7e062
chore: use consistent type import syntax
kellnerd Sep 12, 2023
f9b5d4f
refactor: rename FormAliasT to NewOrExistingAliasT
kellnerd Sep 12, 2023
5a519ec
refactor(util): make date number parsing better readable
kellnerd Sep 12, 2023
10f9b55
fix(ts): call instance method instead of class method
kellnerd Sep 12, 2023
7843a11
other(ts): expect errors for bookshelf's non-standard class inheritance
kellnerd Sep 12, 2023
dfc71e4
other(ts): use parsed entity types in more places and enhance them
kellnerd Sep 21, 2023
1e155ab
fix(import): avoid conflicting usage of entityType by using QueuedEntity
kellnerd Oct 16, 2023
cdf0dcc
other(ts): create type definitions for import tables
kellnerd Oct 16, 2023
d0c9658
fix(import): properly extract id from knex query result
kellnerd Oct 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
},
"homepage": "https://github.com/bookbrainz/bookbrainz-data-js",
"dependencies": {
"@metabrainz/bookshelf": "^1.3.1",
"@metabrainz/bookshelf": "^1.4.0",
"bookshelf-virtuals-plugin": "^1.0.0",
"deep-diff": "^1.0.2",
"immutable": "^3.8.2",
Expand All @@ -83,6 +83,7 @@
"@babel/register": "^7.13.16",
"@types/lodash": "^4.14.168",
"@types/node": "^18.11.18",
"@types/pg": "^8.6.0",
"@typescript-eslint/eslint-plugin": "^5.48.2",
"@typescript-eslint/parser": "^5.48.2",
"babel-plugin-lodash": "^3.3.4",
Expand Down
20 changes: 9 additions & 11 deletions src/func/alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,25 @@
*/

import * as _ from 'lodash';
import type {
FormAliasT as Alias,
FormAliasWithDefaultT as AliasWithDefault,
Transaction
} from './types';
import type {AliasWithDefaultT, FormAliasT} from '../types/aliases';
import {
createNewSetWithItems,
getAddedItems,
getRemovedItems,
getUnchangedItems
} from './set';
import type {EntityTypeString} from '../types/entity';
import type {ORM} from '..';
import type {Transaction} from './types';
import {snakeToCamel} from '../util';


export async function updateAliasSet(
orm: any, transacting: Transaction, oldSet: any,
orm: ORM, transacting: Transaction, oldSet: any,
oldDefaultAliasId: number | null | undefined,
newSetItemsWithDefault: Array<AliasWithDefault>
newSetItemsWithDefault: Array<AliasWithDefaultT>
) {
function comparisonFunc(obj: Alias, other: Alias) {
function comparisonFunc(obj: FormAliasT, other: FormAliasT) {
return (
obj.name === other.name &&
obj.sortName === other.sortName &&
Expand All @@ -49,10 +47,10 @@ export async function updateAliasSet(

const {AliasSet} = orm;

const newSetItems: Array<Alias> =
const newSetItems: Array<FormAliasT> =
newSetItemsWithDefault.map((item) => _.omit(item, 'default'));

const oldSetItems: Array<Alias> =
const oldSetItems: Array<FormAliasT> =
oldSet ? oldSet.related('aliases').toJSON() : [];

if (_.isEmpty(oldSetItems) && _.isEmpty(newSetItems)) {
Expand Down Expand Up @@ -161,7 +159,7 @@ export async function getBBIDsWithMatchingAlias(
const aliasIds = _.map(
await getAliasIds(transacting, name, caseSensitive),
'id'
) as Array<string|number>;
) as Array<string | number>;

const aliasSetIds = _.map(
await transacting.distinct('set_id')
Expand Down
5 changes: 3 additions & 2 deletions src/func/annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import type {ORM} from '..';
import type {Transaction} from './types';


/**
* @param {Object} orm - Bookbrainz orm wrapper holding all models
* @param {ORM} orm - Bookbrainz orm wrapper holding all models
* @param {Transaction} transacting - The present knex transacting object
* @param {Object} oldAnnotation - The old annotation object
* @param {string} newContent - New annotation to be set
* @param {Object} revision - The present revision object
* @returns {Promise<Object>} - Returns Annotation object
*/
export function updateAnnotation(
orm: any, transacting: Transaction, oldAnnotation: any,
orm: ORM, transacting: Transaction, oldAnnotation: any,
newContent: string, revision: any
) {
const {Annotation} = orm;
Expand Down
19 changes: 15 additions & 4 deletions src/func/area.js → src/func/area.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import type Bookshelf from '@metabrainz/bookshelf';
import type {ORM} from '..';
import type {QueryResult} from 'pg';

/**
* Recursively fetches an area's parents (with "has part" link)
* Adapted from https://github.com/metabrainz/musicbrainz-server/blob/f79b6d0d2d4bd67254cc34426f17cf8eb21ec5bb/lib/MusicBrainz/Server/Data/Utils.pm#L255-L273
* @param {object} orm - the BookBrainz ORM, initialized during app setup
* @param {string} areaId - The entity model name.
* @param {object} orm - the BookBrainz ORM, initialized during app setup, or a Bookshelf instance
* @param {string} areaId - The BBID (= MBID) of the area
* @param {boolean} checkAllLevels - By default limits to the area types Country, Subdivision and City
* @returns {Promise} The returned Promise returns the entity's
* parent default alias
*/
export async function recursivelyGetAreaParentsWithNames(orm, areaId, checkAllLevels = false) {
export async function recursivelyGetAreaParentsWithNames(orm: ORM | Bookshelf, areaId: string, checkAllLevels = false) {
const levelsCondition = checkAllLevels ? '' :
'WHERE area.type IN (1, 2, 3)';
const rawSql = `
Expand All @@ -30,9 +33,17 @@ export async function recursivelyGetAreaParentsWithNames(orm, areaId, checkAllLe
`;

// Query the database to get the area parents recursively
const queryResult = await (orm.bookshelf || orm).knex.raw(rawSql);
const knex = 'bookshelf' in orm ? orm.bookshelf.knex : orm.knex;
const queryResult = await knex.raw<QueryResult<AreaDescendantRow>>(rawSql);
if (!Array.isArray(queryResult.rows)) {
return [];
}
return queryResult.rows;
}

type AreaDescendantRow = {
descendant: string;
parent: string;
depth: number;
name: string;
};
33 changes: 21 additions & 12 deletions src/func/author-credit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@

import * as _ from 'lodash';
import type {AuthorCreditNameT, Transaction} from './types';
import type Bookshelf from '@metabrainz/bookshelf';
import type {ORM} from '..';
import type {QueryResult} from 'pg';


function findAuthorCredit(
orm: any, transacting: Transaction, authorCredit: Array<AuthorCreditNameT>
orm: ORM, transacting: Transaction, authorCredit: Array<AuthorCreditNameT>
) {
const tables = {cc: 'bookbrainz.author_credit'};

Expand Down Expand Up @@ -58,16 +61,17 @@ function findAuthorCredit(


export async function fetchOrCreateCredit(
orm: any, transacting: Transaction, authorCredit: Array<AuthorCreditNameT>
orm: ORM, transacting: Transaction, authorCredit: Array<AuthorCreditNameT>
) {
const {AuthorCredit} = orm;
const result = await findAuthorCredit(orm, transacting, authorCredit);

if (result) {
return orm.AuthorCredit.forge({id: result.id})
.fetch({transacting, withRelated: 'names'});
return new AuthorCredit({id: result.id})
.fetch({transacting, withRelated: ['names']});
}

const newCredit = await new orm.AuthorCredit(
const newCredit = await new AuthorCredit(
{authorCount: authorCredit.length}
).save(null, {transacting});

Expand All @@ -88,7 +92,7 @@ export async function fetchOrCreateCredit(
}

export function updateAuthorCredit(
orm: any, transacting: Transaction, oldCredit: any,
orm: ORM, transacting: Transaction, oldCredit: any,
newCreditNames: Array<AuthorCreditNameT>
): Promise<any> {
/* eslint-disable consistent-return */
Expand Down Expand Up @@ -122,13 +126,13 @@ export function updateAuthorCredit(

/**
* Fetches all the Edition entities credited to an Author (with Author Credits)
* @param {object} bookshelf - the BookBrainz ORM, initialized during app setup
* @param {Bookshelf} bookshelf - the Bookshelf instance, initialized during app setup
* @param {string} authorBBID - The target Author's BBID.
* @returns {Promise} The returned Promise returns the Edition BBID and default alias
*/

export async function getEditionsCreditedToAuthor(
bookshelf: any, authorBBID: string
bookshelf: Bookshelf, authorBBID: string
) {
const rawSql = ` SELECT e.bbid , alias."name" from bookbrainz.author
LEFT JOIN bookbrainz.author_credit_name acn on acn.author_bbid = author.bbid
Expand All @@ -140,7 +144,7 @@ export async function getEditionsCreditedToAuthor(
AND e.master = true
AND e.data_id is not null
`;
let queryResult;
let queryResult: QueryResult<AliasAndBBIDRow>;
try {
queryResult = await bookshelf.knex.raw(rawSql);
}
Expand All @@ -156,13 +160,13 @@ export async function getEditionsCreditedToAuthor(

/**
* Fetches all the Edition Group entities credited to an Author (with Author Credits)
* @param {object} bookshelf - the BookBrainz ORM, initialized during app setup
* @param {Bookshelf} bookshelf - the Bookshelf instance, initialized during app setup
* @param {string} authorBBID - The target Author's BBID.
* @returns {Promise} The returned Promise returns the Edition Group BBID and default alias
*/

export async function getEditionGroupsCreditedToAuthor(
bookshelf: any, authorBBID: string
bookshelf: Bookshelf, authorBBID: string
) {
const rawSql = ` SELECT eg.bbid , alias."name" from bookbrainz.author
LEFT JOIN bookbrainz.author_credit_name acn on acn.author_bbid = author.bbid
Expand All @@ -174,7 +178,7 @@ export async function getEditionGroupsCreditedToAuthor(
AND eg.master = true
AND eg.data_id is not null
`;
let queryResult;
let queryResult: QueryResult<AliasAndBBIDRow>;
try {
queryResult = await bookshelf.knex.raw(rawSql);
}
Expand All @@ -187,3 +191,8 @@ export async function getEditionGroupsCreditedToAuthor(
}
return queryResult.rows;
}

type AliasAndBBIDRow = {
name: string;
bbid: string;
};
23 changes: 12 additions & 11 deletions src/func/create-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
*/

import * as _ from 'lodash';
import type {
FormAliasWithDefaultT as AliasWithDefault, FormIdentifierT as Identifier,
Transaction
} from './types';
import {
getAdditionalEntityProps, getEntityModelByType, getEntitySetMetadataByType
} from './entity';
import type {AliasWithDefaultT} from '../types/aliases';
import type {EntityTypeString} from '../types/entity';
import type {IdentifierT} from '../types/identifiers';
import type {ORM} from '..';
import type {Transaction} from './types';
import {createNote} from './note';
import {incrementEditorEditCountById} from './editor';
import {updateAliasSet} from './alias';
Expand All @@ -37,24 +38,24 @@ import {updateIdentifierSet} from './identifier';


interface EntityDataType {
aliases: Array<AliasWithDefault>,
aliases: Array<AliasWithDefaultT>,
annotation: string,
disambiguation: string,
identifiers: Array<Identifier>,
identifiers: Array<IdentifierT>,
note: string,
type: string
type: EntityTypeString
}

interface ExtraEntityDataType extends EntityDataType {
[propName: string]: any;
}

interface CreateEntityPropsType {
orm: any,
orm: ORM,
transacting: Transaction,
editorId: string,
entityData: ExtraEntityDataType,
entityType: string
entityType: EntityTypeString
}

export async function createEntity({
Expand Down Expand Up @@ -129,9 +130,9 @@ export async function createEntity({
revisionId: revisionRecord && revisionRecord.get('id')
}, entitySets, additionalProps);

const model = getEntityModelByType(orm, entityType);
const Model = getEntityModelByType(orm, entityType);

const entityModel = await model.forge(propsToSet)
const entityModel = await new Model(propsToSet)
.save(null, {
method: 'insert',
transacting
Expand Down
5 changes: 3 additions & 2 deletions src/func/disambiguation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import type {ORM} from '..';
import type {Transaction} from './types';


/**
* @param {Object} orm - The BookBrainz orm wrapper containing all models
* @param {ORM} orm - The BookBrainz orm wrapper containing all models
* @param {Transaction} transacting - The current knex transaction object
* @param {Object} oldDisambiguation - The previous disambiguation object
* @param {string} newComment - The new disambiguation string
* @returns {Promise<Object>} - Returns Promise holding Disambiguation object
*/
export function updateDisambiguation(
orm: any, transacting: Transaction, oldDisambiguation: any,
orm: ORM, transacting: Transaction, oldDisambiguation: any,
newComment: string
) {
const {Disambiguation} = orm;
Expand Down
5 changes: 3 additions & 2 deletions src/func/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import {ORM} from '..';
import type {Transaction} from './types';

/**
* Adds 1 to the edit count of the specified editor
*
* @param {object} orm - the BookBrainz ORM, initialized during app setup
* @param {ORM} orm - the BookBrainz ORM, initialized during app setup
* @param {string} id - row ID of editor to be updated
* @param {Transaction} transacting - Bookshelf transaction object (must be in
* progress)
* @returns {Promise} - Resolves to the updated editor model
*/
export function incrementEditorEditCountById(
orm: any,
orm: ORM,
id: string,
transacting: Transaction
): Promise<any> {
Expand Down
9 changes: 6 additions & 3 deletions src/func/entity-sets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import {
createNewSetWithItems, getAddedItems, getComparisonFunc, getRemovedItems,
getUnchangedItems
} from './set';
import {type EntitySetMetadataT} from './entity';
import type {ORM} from '..';
kellnerd marked this conversation as resolved.
Show resolved Hide resolved


function updateEntitySet<Item extends SetItemT>(
transacting: Transaction, oldSet: any, newItems: Array<Item>,
derivedSet: any, orm: Record<string, unknown>
derivedSet: EntitySetMetadataT, orm: ORM
): Promise<any> {
const oldItems =
oldSet ? oldSet.related(derivedSet.propName).toJSON() : [];
Expand Down Expand Up @@ -61,8 +63,8 @@ function updateEntitySet<Item extends SetItemT>(


export async function updateEntitySets(
derivedSets: Array<any> | null | undefined, currentEntity: any,
entityData: any, transacting: Transaction, orm: Record<string, unknown>
derivedSets: EntitySetMetadataT[] | null | undefined, currentEntity: any,
entityData: any, transacting: Transaction, orm: ORM
): Promise<Record<string, unknown> | null | undefined> {
// If no entity sets, return null
if (!derivedSets) {
Expand All @@ -77,6 +79,7 @@ export async function updateEntitySets(
return Promise.resolve(null);
}

// TODO: Find out why we expect a non-existing `model` property here!?
const oldSetRecord = await derivedSet.model.forge({
id: currentEntity[derivedSet.name].id
}).fetch({
Expand Down
Loading
Loading