16 Commits

Author SHA1 Message Date
6fc901b3ec bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-11-25 17:05:22 -06:00
50e0cf3090 Fix prototype access issue with model scopes property
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-25 17:02:43 -06:00
d245d15ad6 Bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-11-25 16:52:35 -06:00
265837b5cd Fix stupid typescript error...
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-25 16:50:01 -06:00
fe0b4d6d8f bump version
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2021-11-25 16:39:53 -06:00
ce1d22ff44 Make the linter happy
Some checks failed
continuous-integration/drone/push Build is failing
2021-11-25 16:39:25 -06:00
b7bfb3e153 Model: fix eager-loaded relation loading from static query 2021-11-25 16:39:17 -06:00
e57819d318 Bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-11-15 14:00:29 -06:00
0a9dd30909 Implement scopes on models and support interacting with them via ModelBuilder
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-11 16:42:37 -06:00
d92c8b5409 Start implementation of model relations
All checks were successful
continuous-integration/drone/push Build is passing
2021-11-10 21:30:59 -06:00
589cb7d579 Bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-10-19 22:29:34 -05:00
3680ad1914 Fix back-fill on insert for Model.save 2021-10-19 22:29:15 -05:00
96e13d85fc Bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-10-19 13:59:14 -05:00
5a9283ad85 orm(PostgreSQLDialect): double-quote column names in INSERT field lists 2021-10-19 13:59:00 -05:00
b1ea489ccb Bump version
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-10-19 13:00:27 -05:00
c3f2779650 Add generic to APIResponse 2021-10-19 13:00:14 -05:00
26 changed files with 818 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@extollo/lib",
"version": "0.5.5",
"version": "0.5.12",
"description": "The framework library that lifts up your code.",
"main": "lib/index.js",
"types": "lib/index.d.ts",

View File

@@ -1,7 +1,6 @@
import {
Authenticatable,
AuthenticatableCredentials,
AuthenticatableIdentifier,
AuthenticatableRepository,
} from '../../types'
import {Inject, Injectable} from '../../../di'
@@ -46,7 +45,7 @@ export class OAuth2Repository implements AuthenticatableRepository {
return this.getAuthenticatableFromBearer(credentials.credential)
}
getByIdentifier(id: AuthenticatableIdentifier): Awaitable<Maybe<Authenticatable>> {
getByIdentifier(): Awaitable<Maybe<Authenticatable>> {
return undefined
}

37
src/di/InjectionAware.ts Normal file
View File

@@ -0,0 +1,37 @@
import {Container} from './Container'
import {TypedDependencyKey} from './types'
/**
* Base class for Injection-aware classes that automatically
* pass along their configured container to instances created
* via their `make` method.
*/
export class InjectionAware {
private ci: Container
constructor() {
this.ci = Container.getContainer()
}
/** Set the container for this instance. */
public setContainer(ci: Container): this {
this.ci = ci
return this
}
/** Get the container for this instance. */
public getContainer(): Container {
return this.ci
}
/** Instantiate a new injectable using the container. */
public make<T>(target: TypedDependencyKey<T>, ...parameters: any[]): T {
const inst = this.ci.make<T>(target, ...parameters)
if ( inst instanceof InjectionAware ) {
inst.setContainer(this.ci)
}
return inst
}
}

View File

@@ -13,3 +13,4 @@ export * from './ScopedContainer'
export * from './types'
export * from './decorator/injection'
export * from './InjectionAware'

View File

@@ -1,10 +1,10 @@
/**
* Base type for an API response format.
*/
export interface APIResponse {
export interface APIResponse<T> {
success: boolean,
message?: string,
data?: any,
data?: T,
error?: {
name: string,
message: string,
@@ -17,7 +17,7 @@ export interface APIResponse {
* @param {string} displayMessage
* @return APIResponse
*/
export function message(displayMessage: string): APIResponse {
export function message(displayMessage: string): APIResponse<void> {
return {
success: true,
message: displayMessage,
@@ -29,7 +29,7 @@ export function message(displayMessage: string): APIResponse {
* @param record
* @return APIResponse
*/
export function one(record: unknown): APIResponse {
export function one<T>(record: T): APIResponse<T> {
return {
success: true,
data: record,
@@ -41,7 +41,7 @@ export function one(record: unknown): APIResponse {
* @param {array} records
* @return APIResponse
*/
export function many(records: any[]): APIResponse {
export function many<T>(records: T[]): APIResponse<{records: T[], total: number}> {
return {
success: true,
data: {
@@ -56,7 +56,7 @@ export function many(records: any[]): APIResponse {
* @return APIResponse
* @param thrownError
*/
export function error(thrownError: string | Error): APIResponse {
export function error(thrownError: string | Error): APIResponse<void> {
if ( typeof thrownError === 'string' ) {
return {
success: false,

View File

@@ -1,5 +1,5 @@
import {Application} from './Application'
import {Container, DependencyKey, Injectable} from '../di'
import {Container, Injectable, TypedDependencyKey} from '../di'
/**
* Base type for a class that supports binding methods by string.
@@ -43,7 +43,7 @@ export class AppClass {
}
/** Call the `make()` method on the global container. */
protected make<T>(target: DependencyKey, ...parameters: any[]): T {
protected make<T>(target: TypedDependencyKey<T>, ...parameters: any[]): T {
return this.container().make<T>(target, ...parameters)
}

View File

@@ -69,6 +69,13 @@ export abstract class AbstractBuilder<T> extends AppClass {
*/
public abstract getResultIterable(): AbstractResultIterable<T>
/**
* Get a copy of this builder with its values finalized.
*/
public finalize(): AbstractBuilder<T> {
return this.clone()
}
/**
* Clone the current query to a new AbstractBuilder instance with the same properties.
*/
@@ -489,7 +496,7 @@ export abstract class AbstractBuilder<T> extends AppClass {
throw new ErrorWithContext(`No connection specified to execute update query.`)
}
const query = this.registeredConnection.dialect().renderUpdate(this, data)
const query = this.registeredConnection.dialect().renderUpdate(this.finalize(), data)
return this.registeredConnection.query(query)
}
@@ -515,7 +522,7 @@ export abstract class AbstractBuilder<T> extends AppClass {
throw new ErrorWithContext(`No connection specified to execute update query.`)
}
const query = this.registeredConnection.dialect().renderDelete(this)
const query = this.registeredConnection.dialect().renderDelete(this.finalize())
return this.registeredConnection.query(query)
}
@@ -548,7 +555,7 @@ export abstract class AbstractBuilder<T> extends AppClass {
throw new ErrorWithContext(`No connection specified to execute update query.`)
}
const query = this.registeredConnection.dialect().renderInsert(this, rowOrRows)
const query = this.registeredConnection.dialect().renderInsert(this.finalize(), rowOrRows)
return this.registeredConnection.query(query)
}
@@ -560,7 +567,7 @@ export abstract class AbstractBuilder<T> extends AppClass {
throw new ErrorWithContext(`No connection specified to execute update query.`)
}
const query = this.registeredConnection.dialect().renderExistential(this)
const query = this.registeredConnection.dialect().renderExistential(this.finalize())
const result = await this.registeredConnection.query(query)
return Boolean(result.rows.first())
}

View File

@@ -19,6 +19,6 @@ export class Builder extends AbstractBuilder<QueryRow> {
throw new ErrorWithContext(`No connection specified to fetch iterator for query.`)
}
return Container.getContainer().make<ResultIterable>(ResultIterable, this, this.registeredConnection)
return Container.getContainer().make<ResultIterable>(ResultIterable, this.finalize(), this.registeredConnection)
}
}

View File

@@ -230,7 +230,7 @@ export class PostgreSQLDialect extends SQLDialect {
const table: string = tableString.split('.').map(x => `"${x}"`)
.join('.')
queryLines.push('INSERT INTO ' + (typeof source === 'string' ? table : `${table} AS "${source.alias}"`)
+ (columns.length ? ` (${columns.join(', ')})` : ''))
+ (columns.length ? ` (${columns.map(x => `"${x}"`).join(', ')})` : ''))
}
if ( Array.isArray(data) && !data.length ) {

View File

@@ -18,6 +18,16 @@ export * from './model/ModelResultIterable'
export * from './model/events'
export * from './model/Model'
export * from './model/relation/RelationBuilder'
export * from './model/relation/Relation'
export * from './model/relation/HasOneOrMany'
export * from './model/relation/HasOne'
export * from './model/relation/HasMany'
export * from './model/relation/decorators'
export * from './model/scope/Scope'
export * from './model/scope/ActiveScope'
export