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

feat: add TS types #1904

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8fb2b6f
feat: add connector TS types
achrinza Sep 22, 2021
6281ebe
feat: add types for connector and datasource
achrinza Sep 24, 2021
b500cd7
fix: update ConnectorSettings.connector
achrinza Sep 24, 2021
6c66be8
refactor: NameMapper
achrinza Sep 24, 2021
2cbf624
feat: add missing non-function class members
achrinza Sep 24, 2021
6479173
feat: add operations typedefs
achrinza Sep 24, 2021
b460b94
feat: add missing types
achrinza Sep 24, 2021
68521cb
update operation hook context typedef
achrinza Sep 24, 2021
27496ae
feat: update datasource typedefs
achrinza Sep 24, 2021
ecb1a7b
feat(PropertyDefinition): add missing props
achrinza Sep 24, 2021
54aa233
feat(DataSource): refine `columnMetadata` return type
achrinza Sep 24, 2021
f75a599
feat(Connector): refine `_models` typedef
achrinza Sep 24, 2021
17ff165
feat: refined defs
achrinza Sep 24, 2021
7234599
feat: misc. updates
achrinza Sep 26, 2021
fe45124
feat: update model settings, prop defs
achrinza Sep 27, 2021
181578d
feat: add initial jutil typedefs
achrinza Sep 28, 2021
2e7b0cf
feat(DataSource): add prototype.mixin
achrinza Sep 28, 2021
aedf47a
feat: initial kvao typedefs
achrinza Sep 29, 2021
8b56310
feat: misc. updates
achrinza Sep 30, 2021
055efd3
feat: misc updates
achrinza Dec 3, 2021
884776b
feat: misc updates
achrinza Apr 9, 2022
db34269
feat: apply misc review suggestions
achrinza Apr 9, 2022
e1bb7a1
feat: misc. changes
achrinza Jun 30, 2022
de9ce11
feat: misc changes
achrinza Aug 22, 2022
5a52edb
feat: misc typedef updates
achrinza Jul 22, 2023
7d59e16
chore: more misc changes
achrinza Sep 1, 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
285 changes: 276 additions & 9 deletions types/connector.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,285 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Callback, DataSource, Options, PromiseOrVoid} from '..';
import { AnyObject } from 'strong-globalize/lib/config';
import {Callback, DataSource, Filter, ModelBase, ModelBaseClass, ModelDefinition, ModelProperties, Options, PromiseOrVoid, PropertyDefinition, PropertyType, Schema, Where} from '..';

// Copyright IBM Corp. 2018. All Rights Reserved.
// Node module: loopback-datasource-juggler
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
export type ConnectorSettings = Options & {
name?: string,
/**
* Overrides {@link ConnectorSettings.adapter} if defined.
*/
connector?: ConnectorStatic | string,
/**
* @deprecated Use {@link ConnectorSettings.connector} instead.
*/
adapter?: ConnectorStatic | string,
connectionTimeout?: number,
maxOfflineRequests?: number,
lazyConnect?: boolean,
debug?: boolean,
}
achrinza marked this conversation as resolved.
Show resolved Hide resolved
achrinza marked this conversation as resolved.
Show resolved Hide resolved

export type IDPropertiesDiscoveryOptions = {
owner?: string,
} | {
schema?: string
}

export type DiscoveryScopeOptions = {
owner?: string,
all?: boolean,
views?: boolean,
limit?: number,
offset?: number,
}

export type SchemaDiscoveryOptions = {
owner?: string,
/**
* Overriden by {@link SchemaDiscoveryOptions.associations}.
*/
relations?: boolean,
all?: boolean,
views?: boolean,
disableCamelCase?: boolean,
nameMapper?: NameMapper,
associations?: boolean,
}

export type NameMapper = (type: 'table' | 'model' | 'fk' | string, name: string) => string | null;

export type DiscoveredPrimaryKeys = {
owner: string | null,
tableName: string,
columnName: string,
keySeq: number,
pkName: string | null,
}

export type DiscoveredForeignKeys = {
fkOwner: string | null,
fkName: string | null,
fkTableName: string,
fkColumnName: string,
keySeq: number,

pkOwner: string | null,
pkName: string | null,
pkTableName: string,
pkColumnName: string,
}

export type DiscoveredModelProperties = {
owner?: string,
tableName?: string,
columnName?: string,
dataType?: string,
dataLength?: number,
dataPrecision?: number,
dataScale?: number,
nullable?: boolean,
}


// #TODO(achrinza): The codebase suggets that `context` differs
// depending on the situation, and that there's no cohesive interface.
// Hence, we'll need to identify all the possible contexts.
export type Context = {
Model: ModelBaseClass,
instance?: object,
query?: Filter,
where?: Where,
data?: AnyObject,
hookState?: AnyObject,
options?: Options,
isNewInstance?: boolean,
currentInstance?: Readonly<ModelBase>,
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are defined here:

Currently, this is only based on all the possible attributes for an Operation Hooks context.

Will probably need to add separate context typedefs for the other 2.

While the Operation Hooks context differs depending on the event being observed and the function called, I'm not sure if its better to create distinctive op. hook contexts for these different hooks.


/**
* Connector from `loopback-connector` module
*/
export interface Connector {
name: string; // Name/type of the connector
dataSource?: DataSource;
connect(callback?: Callback): PromiseOrVoid; // Connect to the underlying system
disconnect(callback?: Callback): PromiseOrVoid; // Disconnect from the underlying system
ping(callback?: Callback): PromiseOrVoid; // Ping the underlying system

achrinza marked this conversation as resolved.
Show resolved Hide resolved
/**
* @internal
*/
_models?: Record<string, ModelBaseClass>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most probably ModelDefinition.

connect?(callback?: Callback): PromiseOrVoid; // Connect to the underlying system
disconnect?(callback?: Callback): PromiseOrVoid; // Disconnect from the underlying system

/**
* Ping the underlying connector to test the connections.
*
* @remarks
* Unlike {@link DataSource.ping}, if no callback is provided, a
* {@link Promise} return value is not guaranteed.
*
* @param callback Callback function
* @returns a {@link Promise} or `void`
*/
ping?(callback?: Callback): PromiseOrVoid; // Ping the underlying system
execute?(...args: any[]): Promise<any>;

/**
* Get the connector's types collection.
*
* @remarks
* For example, ['db', 'nosql', 'mongodb'] would be represent a datasource of
* type 'db', with a subtype of 'nosql', and would use the 'mongodb' connector.
*
* Alternatively, ['rest'] would be a different type altogether, and would have
* no subtype.
*
* @returns The connector's type collection.
*/
getTypes?(): string[];
define?(def: {model: ModelBaseClass, properties: PropertyDefinition, settings: ModelDefinition['settings']}): void;

/**
* Define a property on the target model.
*
* @param model Name of model
* @param prop Name of property
* @param params Property settings
*/
defineProperty?(model: string, prop: string, params: PropertyDefinition): void;
defineForeignKey?(modelName: string, key: string, foreignModelName: string, cb: Callback<PropertyType>): void;
defineForeignKey?(modelName: string, key: string, cb: Callback<PropertyType>): void;
achrinza marked this conversation as resolved.
Show resolved Hide resolved

getDefaultIdType(): object;
isRelational(): boolean;

/**
* Discover existing database tables.
*
* @param options Discovery options
* @param cb Callback function
*/
discoverModelDefinitions?(options: DiscoveryScopeOptions, cb: Callback): Promise<ModelDefinition[]>;

/**
* {@inheritDoc Connector.discoverModelDefinitions}
* @deprecated
*/
discoverModelDefinitionsSync?(options: DiscoveryScopeOptions): ModelDefinition[]

/**
* Discover properties for a given model.
*
* @param modelName Target table/view name
* @param options Discovery options
* @param cb Callback function
*/
discoverModelProperties?(modelName: string, options: DiscoveryScopeOptions, cb: Callback<DiscoveredModelProperties>): Promise<DiscoveredModelProperties>;
/**
* {@inheritDoc Connector.discoverModelProperties}
* @deprecated
*/
discoverModelPropertiesSync?(modelName: string, options: DiscoveryScopeOptions): DiscoveredModelProperties;

/**
* Discover primary keys for a given owner/model name.
*
* @param modelName Target model name
* @param options Discovery options
* @param cb Callback function
*/
discoverPrimaryKeys?(modelName: string, options: IDPropertiesDiscoveryOptions, cb: Callback<DiscoveredPrimaryKeys>): Promise<DiscoveredPrimaryKeys>;

/**
* {@inheritDoc Connector.discoverPrimaryKeys}
* @deprecated
*/
discoverPrimaryKeysSync?(modelName: string, options: IDPropertiesDiscoveryOptions): DiscoveredPrimaryKeys;

/**
* Discover foreign keys for a given owner/model name.
*
* @param modelName Target model name
* @param options Discovery options
* @param cb Callback function
*/
discoverForeignKeys?(modelName: string[], options: IDPropertiesDiscoveryOptions, cb: Callback<DiscoveredForeignKeys>): Promise<DiscoveredForeignKeys>;
/**
* {@inheritDoc Connector.discoverForeignKeys}
* @deprecated
*/
discoverForeignKeysSync?(modelName: string[], options: IDPropertiesDiscoveryOptions): DiscoveredForeignKeys;

/**
* Retrieve a description of the foreign key columns that reference the given
* table's primary key columns (i.e. The foreign keys exported by a table),
* ordered by `fkOwner`, `fkTableName`, and `keySeq`.
*
* @param modelName Target model name
* @param options Discovery options
* @param cb Callback function
*/
discoverExportedForeignKeys?(modelName: string, options: IDPropertiesDiscoveryOptions, cb: Callback<DiscoveredForeignKeys>): Promise<DiscoveredForeignKeys>;

/**
* {@inheritDoc Connector/discoverExportedForeignKeys}
* @deprecated
*/
discoverExportedForeignKeysSync?(modelName: string, options?: {owner?: string}): DiscoveredForeignKeys;

/**
* Discover schema from a given table name / view name.
*
* @param tableName Target table name
* @param options Discovery options
* @param cb Callback function
*/
discoverSchemas(tableName: string, options: SchemaDiscoveryOptions, cb: Callback<Schema>): Promise<Schema>;

/**
* Check whether or not migrations are required for the database schema to match
* the model definitions attached to the {@link DataSource}.
*
* @param models Name of models to check. If not defined, all models are checked.
* @param cb
*/
isActual?(models?: string | string[], cb?: Callback<boolean>): void;
freezeDataSource?(): void;
freezeSchema?(): void;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure the difference between these functions. DataSource.prototype.freeze calls both functions if they are defined.

Copy link
Member Author

@achrinza achrinza Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

freezeDatasource seems to have been introduced by this commit:

9b169ef#diff-7de38f47065ef67b4936fbd6396bb71a580fe9a5a9ff2c9723c4fe859d1e2a6eR977-R979

freezeSchema was from JugglingDB.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the commit just before the one mentioned above, they should be identical, and the use of both is for backwards-compatibility with JugglingDB:

6af4b1b


/**
* Normalize connector-specific return data into standardised Juggler context
* data.
*
* @remarks
* Depending on the connector, the database response can contain information
* about the updated record(s). This object usually has a database-specific
* structure and does not match model properties. For example, MySQL returns
* `OkPacket: {fieldCount, affectedRows, insertId, ... , changedRows}`.
*
* The return value is normalised data.
*
* If the connector DDL and DML functions map directly to a hash-map of
* model properties and their values, this function does not need to be
* implemented.
*
* @param context
* @param dbResponse
*/
generateContextData?(context: Context, dbResponse: unknown): Context;

achrinza marked this conversation as resolved.
Show resolved Hide resolved
[property: string]: any; // Other properties that vary by connectors
}

export interface BuiltConnector extends Connector {
achrinza marked this conversation as resolved.
Show resolved Hide resolved
dataSource: DataSource;
log: DataSource['log'];
logger(query: string, start: number): (query: string) => void;
}

/**
* Base connector class
*
* @internal
*/
export declare class ConnectorBase implements Connector {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May need to extract this to loopback-connector package along with transaction-related typedefs.

name: string; // Name/type of the connector;
Expand All @@ -43,6 +300,16 @@ export declare class ConnectorBase implements Connector {
static initialize(dataSource: DataSource, callback?: Callback): void;

constructor(settings?: Options);
[property: string]: any;
_models?: Record<string, ModelBaseClass>;
getDefaultIdType(): object;
isRelational(): boolean;
discoverSchemas(tableName: string, options: SchemaDiscoveryOptions, cb: Callback<Schema>): Promise<Schema>;
}

export declare interface ConnectorStatic {
initialize(this: DataSource, callback: Callback): void;
new (settings: ConnectorSettings): Connector;
}

export declare class Memory extends ConnectorBase {}
Expand Down
Loading