From f5f62ae4cf3f6c9a8fb7d90e296246f61d007662 Mon Sep 17 00:00:00 2001
From: Kia King Ishii
Date: Wed, 1 Apr 2020 01:07:12 +0900
Subject: [PATCH 01/56] feat: add repository class (#585) (#591)
---
src/database/Database.ts | 18 +-
src/database/HackedDatabase.ts | 28 +++
src/index.cjs.ts | 3 +
src/index.ts | 4 +
src/model/Model.ts | 2 +-
src/plugins/use.ts | 3 +
src/query/Query.ts | 4 +-
src/repository/Repository.ts | 166 ++++++++++++++++
src/store/install.ts | 84 +++++++-
src/types/index.ts | 1 +
src/types/vuex.ts | 27 ++-
test/feature/repositories/Crud_Create.spec.ts | 31 +++
test/feature/repositories/Crud_Delete.spec.ts | 74 +++++++
test/feature/repositories/Crud_Insert.spec.ts | 31 +++
.../repositories/Crud_InsertOrUpdate.spec.ts | 39 ++++
test/feature/repositories/Crud_New.spec.ts | 29 +++
.../repositories/Crud_Retrieve.spec.ts | 185 ++++++++++++++++++
test/feature/repositories/Crud_Update.spec.ts | 35 ++++
test/feature/repositories/Repository.spec.ts | 100 ++++++++++
test/unit/database/Database.spec.ts | 72 +++----
test/unit/query/Query.spec.ts | 8 +-
test/unit/support/Utils.spec.ts | 97 +++------
tslint.json | 5 +-
23 files changed, 917 insertions(+), 129 deletions(-)
create mode 100644 src/database/HackedDatabase.ts
create mode 100644 src/repository/Repository.ts
create mode 100644 src/types/index.ts
create mode 100644 test/feature/repositories/Crud_Create.spec.ts
create mode 100644 test/feature/repositories/Crud_Delete.spec.ts
create mode 100644 test/feature/repositories/Crud_Insert.spec.ts
create mode 100644 test/feature/repositories/Crud_InsertOrUpdate.spec.ts
create mode 100644 test/feature/repositories/Crud_New.spec.ts
create mode 100644 test/feature/repositories/Crud_Retrieve.spec.ts
create mode 100644 test/feature/repositories/Crud_Update.spec.ts
create mode 100644 test/feature/repositories/Repository.spec.ts
diff --git a/src/database/Database.ts b/src/database/Database.ts
index 881c524c..e07c5b5d 100644
--- a/src/database/Database.ts
+++ b/src/database/Database.ts
@@ -45,6 +45,11 @@ export default class Database {
*/
entities: Entity[] = []
+ /**
+ * The hacked models registered to the store.
+ */
+ hackedModels: Models = {}
+
/**
* The normalizr schema.
*/
@@ -63,8 +68,6 @@ export default class Database {
this.store = store
this.namespace = namespace
- this.connect()
-
this.registerModules()
this.createSchema()
@@ -80,10 +83,12 @@ export default class Database {
const entity: Entity = {
name: model.entity,
base: model.baseEntity || model.entity,
- model: this.createBindingModel(model),
+ model,
module
}
+ this.hackedModels[model.entity] = this.createBindingModel(model)
+
this.entities.push(entity)
if (this.isStarted) {
@@ -356,13 +361,6 @@ export default class Database {
this.schemas[entity.name] = Schema.create(entity.model)
}
- /**
- * Inject database to the store instance.
- */
- private connect (): void {
- this.store.$db = () => this
- }
-
/**
* Warn user if the given model is a type of an inherited model that is being
* defined without overwriting `Model.types()` because the user will not be
diff --git a/src/database/HackedDatabase.ts b/src/database/HackedDatabase.ts
new file mode 100644
index 00000000..c5cb2c5f
--- /dev/null
+++ b/src/database/HackedDatabase.ts
@@ -0,0 +1,28 @@
+import Database from './Database'
+import Model from '../model/Model'
+
+export default class HackedDatabase {
+ /**
+ * The database instance to look up models.
+ */
+ database: Database
+
+ /**
+ * Create a new hacked database.
+ */
+ constructor (database: Database) {
+ this.database = database
+ }
+
+ /**
+ * Get the hacked model of the given name from the entities list.
+ */
+ model (model: M): M
+ model (model: string): typeof Model
+ model (model: typeof Model | string): typeof Model | string {
+ /* istanbul ignore next */
+ const name = typeof model === 'string' ? model : model.entity
+
+ return this.database.hackedModels[name]
+ }
+}
diff --git a/src/index.cjs.ts b/src/index.cjs.ts
index d069bf2f..32496d6f 100644
--- a/src/index.cjs.ts
+++ b/src/index.cjs.ts
@@ -26,6 +26,7 @@ import MorphOne from './attributes/relations/MorphOne'
import MorphMany from './attributes/relations/MorphMany'
import MorphToMany from './attributes/relations/MorphToMany'
import MorphedByMany from './attributes/relations/MorphedByMany'
+import Repository from './repository/Repository'
import Getters from './modules/Getters'
import Actions from './modules/Actions'
import RootGetters from './modules/RootGetters'
@@ -64,6 +65,7 @@ export interface VuexORM {
MorphMany: typeof MorphMany
MorphToMany: typeof MorphToMany
MorphedByMany: typeof MorphedByMany
+ Repository: typeof Repository
Getters: GettersContract
Actions: ActionsContract
RootGetters: RootGettersContract
@@ -96,6 +98,7 @@ export default {
MorphMany,
MorphToMany,
MorphedByMany,
+ Repository,
Getters,
Actions,
RootGetters,
diff --git a/src/index.ts b/src/index.ts
index d2ebacd2..ead67a3e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -26,6 +26,7 @@ import MorphOne from './attributes/relations/MorphOne'
import MorphMany from './attributes/relations/MorphMany'
import MorphToMany from './attributes/relations/MorphToMany'
import MorphedByMany from './attributes/relations/MorphedByMany'
+import Repository from './repository/Repository'
import Getters from './modules/Getters'
import Actions from './modules/Actions'
import RootGetters from './modules/RootGetters'
@@ -73,6 +74,7 @@ export interface VuexORM {
MorphMany: typeof MorphMany
MorphToMany: typeof MorphToMany
MorphedByMany: typeof MorphedByMany
+ Repository: typeof Repository
Getters: GettersContract
Actions: ActionsContract
RootGetters: RootGettersContract
@@ -108,6 +110,7 @@ export {
MorphMany,
MorphToMany,
MorphedByMany,
+ Repository,
Getters,
Actions,
RootGetters,
@@ -151,6 +154,7 @@ export default {
MorphMany,
MorphToMany,
MorphedByMany,
+ Repository,
Getters,
Actions,
RootGetters,
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 65de2bb5..812184c9 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -284,7 +284,7 @@ export default class Model {
* Get the database instance from store.
*/
static database (): Database {
- return this.store().$db()
+ return this.store().$database
}
/**
diff --git a/src/plugins/use.ts b/src/plugins/use.ts
index b42c2b6e..2f077cdb 100644
--- a/src/plugins/use.ts
+++ b/src/plugins/use.ts
@@ -1,3 +1,4 @@
+import Repository from '../repository/Repository'
import Model from '../model/Model'
import Attribute from '../attributes/Attribute'
import Type from '../attributes/types/Type'
@@ -32,6 +33,7 @@ import Query from '../query/Query'
import Database from '../database/Database'
export interface PluginComponents {
+ Repository: typeof Repository
Model: typeof Model
Attribute: typeof Attribute
Type: typeof Type
@@ -73,6 +75,7 @@ export type Use = (plugin: Plugin, options?: Options) => void
export default function (plugin: Plugin, options: Options = {}): void {
const components: PluginComponents = {
+ Repository,
Model,
Attribute,
Type,
diff --git a/src/query/Query.ts b/src/query/Query.ts
index d531a3e3..a5428261 100644
--- a/src/query/Query.ts
+++ b/src/query/Query.ts
@@ -139,7 +139,7 @@ export default class Query {
*/
constructor (store: Store, entity: string) {
this.store = store
- this.database = store.$db()
+ this.database = store.$database
this.model = this.getModel(entity)
this.baseModel = this.getBaseModel(entity)
@@ -157,7 +157,7 @@ export default class Query {
* Delete all records from the store.
*/
static deleteAll (store: Store): void {
- const database = store.$db()
+ const database = store.$database
const models = database.models()
for (const entity in models) {
diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts
new file mode 100644
index 00000000..b8f19284
--- /dev/null
+++ b/src/repository/Repository.ts
@@ -0,0 +1,166 @@
+import { Store } from 'vuex'
+import { ConstructorOf as BaseConstructorOf } from '../types'
+import Database from '../database/Database'
+import { Record, Item, Collection, Collections } from '../data'
+import Model from '../model/Model'
+import * as Payloads from '../modules/payloads/Actions'
+import Query from '../query/Query'
+import Predicate from '../query/contracts/Predicate'
+
+interface ConstructorOf extends BaseConstructorOf {
+ entity: string
+}
+
+export default class Repository {
+ /**
+ * A special flag to indicate if this is the repository class or not. It's
+ * used when retrieving repository instance from `store.$repo()` method to
+ * determine whether the passed in class is either a repository or a model.
+ */
+ static _isRepository: boolean = true
+
+ /**
+ * The store instance for the repository.
+ */
+ store: Store
+
+ /**
+ * The model for the repository.
+ */
+ model!: ConstructorOf
+
+ /**
+ * Create a new repository instance.
+ */
+ constructor (store: Store, model?: ConstructorOf) {
+ this.store = store
+
+ if (model) {
+ this.model = model
+ }
+ }
+
+ /**
+ * Get the database instance from the store instance.
+ */
+ database (): Database {
+ return this.store.$database
+ }
+
+ /**
+ * Create a namespaced method name for Vuex Module from the given
+ * method name.
+ */
+ namespace (method: string): string {
+ return `${this.database().namespace}/${this.model.entity}/${method}`
+ }
+
+ /**
+ * Call Vuex Getetrs.
+ */
+ getters (method: string): any {
+ return this.store.getters[this.namespace(method)]
+ }
+
+ /**
+ * Dispatch Vuex Action.
+ */
+ dispatch (method: string, payload?: any): Promise {
+ return this.store.dispatch(this.namespace(method), payload)
+ }
+
+ /**
+ * Create a new model instance.
+ */
+ make (record?: Record): M {
+ return new this.model(record)
+ }
+
+ /**
+ * Get all records.
+ */
+ all (): Collection {
+ return this.getters('all')()
+ }
+
+ /**
+ * Find a record.
+ */
+ find (id: string | number | (number | string)[]): Item {
+ return this.getters('find')(id)
+ }
+
+ /**
+ * Get the record of the given array of ids.
+ */
+ findIn (idList: (number | string | (number | string)[])[]): Collection {
+ return this.getters('findIn')(idList)
+ }
+
+ /**
+ * Get query instance.
+ */
+ query (): Query {
+ return this.getters('query')()
+ }
+
+ /**
+ * Check wether the associated database contains data.
+ */
+ exists (): boolean {
+ return this.query().exists()
+ }
+
+ /**
+ * Create new data with all fields filled by default values.
+ */
+ new (): Promise {
+ return this.dispatch('new')
+ }
+
+ /**
+ * Save given data to the store by replacing all existing records in the
+ * store. If you want to save data without replacing existing records,
+ * use the `insert` method instead.
+ */
+ create (payload: Payloads.Create): Promise {
+ return this.dispatch('create', payload)
+ }
+
+ /**
+ * Insert records.
+ */
+ insert (payload: Payloads.Insert): Promise {
+ return this.dispatch('insert', payload)
+ }
+
+ /**
+ * Update records.
+ */
+ update (payload: Payloads.Update): Promise {
+ return this.dispatch('update', payload)
+ }
+
+ /**
+ * Insert or update records.
+ */
+ insertOrUpdate (payload: Payloads.InsertOrUpdate): Promise {
+ return this.dispatch('insertOrUpdate', payload)
+ }
+
+ /**
+ * Delete records that matches the given condition.
+ */
+ delete (id: string | number | (number | string)[]): Promise- >
+ delete (condition: Predicate): Promise>
+ delete (payload: any): any {
+ return this.dispatch('delete', payload)
+ }
+
+ /**
+ * Delete all records from the store.
+ */
+ deleteAll (): Promise> {
+ return this.dispatch('deleteAll')
+ }
+}
diff --git a/src/store/install.ts b/src/store/install.ts
index b450483b..4589fa4b 100644
--- a/src/store/install.ts
+++ b/src/store/install.ts
@@ -1,19 +1,91 @@
-import * as Vuex from 'vuex'
+import { Store, Plugin } from 'vuex'
import Container from '../container/Container'
import Database from '../database/Database'
+import HackedDatabase from '../database/HackedDatabase'
+import Repository from '../repository/Repository'
-export type Install = (database: Database, options?: Options) => Vuex.Plugin
+export type Install = (database: Database, options?: Options) => Plugin
export interface Options {
namespace?: string
}
-export default (database: Database, options: Options = {}): Vuex.Plugin => {
+/**
+ * Install Vuex ORM database to the store.
+ */
+export default function install (database: Database, options: Options = {}): Plugin {
const namespace = options.namespace || 'entities'
- return (store: Vuex.Store): void => {
- database.start(store, namespace)
+ return (store) => { mixin(store, database, namespace) }
+}
+
+/**
+ * Mixin Vuex ORM feature to the store.
+ */
+function mixin (store: Store, database: Database, namespace: string): void {
+ registerDatabase(store, database)
+ mixinRepoFunction(store)
+ mixinDbFunction(store)
+ registerToContainer(store)
+ startDatabase(store, namespace)
+}
+
+/**
+ * Register the database to the store.
+ */
+function registerDatabase (store: Store, database: Database): void {
+ store.$database = database
+}
+
+/**
+ * Mixin repo function to the store.
+ */
+function mixinRepoFunction (store: Store): void {
+ store.$repo = function (modelOrRepository: any): any {
+ const repository = modelOrRepository._isRepository
+ ? new modelOrRepository(this)
+ : new Repository(this, modelOrRepository)
- Container.register(store)
+ if (!repository.model) {
+ throw new Error(
+ '[Vuex ORM] The repository was instantiated without a model being ' +
+ 'set. It happens when you forgot to register the model to the ' +
+ 'custom repository. Please check if you have correctly set `model` ' +
+ 'property at the repository class.'
+ )
+ }
+
+ return repository
}
}
+
+/**
+ * Mixin db function to the store.
+ */
+function mixinDbFunction (store: Store): void {
+ store.$db = function (): HackedDatabase {
+ /* istanbul ignore next */
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn(
+ '[Vuex ORM] `store.$db()` method is deprecated. Please use ' +
+ '`store.$repo(Model)` method instead.'
+ )
+ }
+
+ return new HackedDatabase(this.$database)
+ }
+}
+
+/**
+ * Register the store to the container.
+ */
+function registerToContainer (store: Store): void {
+ Container.register(store)
+}
+
+/**
+ * Start the database.
+ */
+function startDatabase (store: Store, namespace: string): void {
+ store.$database.start(store, namespace)
+}
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 00000000..c5ddf026
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1 @@
+export type ConstructorOf = { new (...args: any[]): C }
diff --git a/src/types/vuex.ts b/src/types/vuex.ts
index 1fdea2f3..0dcb78e2 100644
--- a/src/types/vuex.ts
+++ b/src/types/vuex.ts
@@ -1,7 +1,32 @@
+import { ConstructorOf } from '../types'
import Database from '../database/Database'
+import HackedDatabase from '../database/HackedDatabase'
+import Model from '../model/Model'
+import Repository from '../repository/Repository'
declare module 'vuex' {
interface Store
{
- $db (): Database
+ /**
+ * The database instance registered to the store.
+ */
+ $database: Database
+
+ /**
+ * Get a new repository instance for the given model.
+ */
+ $repo > (repository: ConstructorOf): R
+ $repo (model: ConstructorOf): Repository
+
+ /**
+ * Get the database attached to the store. It's the old syntax and should
+ * avoid using it.
+ *
+ * It will return a "Hacked" database that capable of finding a copied
+ * model object. It's an old way of interacting with the database.
+ *
+ * TODO: Update the version.
+ * @deprecated Since v0.XX.X
+ */
+ $db (): HackedDatabase
}
}
diff --git a/test/feature/repositories/Crud_Create.spec.ts b/test/feature/repositories/Crud_Create.spec.ts
new file mode 100644
index 00000000..a177a8ac
--- /dev/null
+++ b/test/feature/repositories/Crud_Create.spec.ts
@@ -0,0 +1,31 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD Create', () => {
+ it('can create given record to the store', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ await store.$repo(User).create({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_Delete.spec.ts b/test/feature/repositories/Crud_Delete.spec.ts
new file mode 100644
index 00000000..b6d7b320
--- /dev/null
+++ b/test/feature/repositories/Crud_Delete.spec.ts
@@ -0,0 +1,74 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD Delete', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null)
+ }
+ }
+
+ id!: any
+ }
+
+ it('can delete a record by specifying the id', async () => {
+ const store = createStore([User])
+
+ const user = store.$repo(User)
+
+ await user.insert({
+ data: [{ id: 1 }, { id: 2 }]
+ })
+
+ await user.delete(1)
+
+ const expected = createState({
+ users: {
+ 2: { $id: '2', id: 2 }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can delete records by specifying a closure', async () => {
+ const store = createStore([User])
+
+ const user = store.$repo(User)
+
+ await user.insert({
+ data: [{ id: 1 }, { id: 2 }]
+ })
+
+ await user.delete(user => user.id === 2)
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1 }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can delete all records in the entity', async () => {
+ const store = createStore([User])
+
+ const user = store.$repo(User)
+
+ await user.insert({
+ data: [{ id: 1 }, { id: 2 }]
+ })
+
+ await user.deleteAll()
+
+ const expected = createState({
+ users: {}
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_Insert.spec.ts b/test/feature/repositories/Crud_Insert.spec.ts
new file mode 100644
index 00000000..08c5bddf
--- /dev/null
+++ b/test/feature/repositories/Crud_Insert.spec.ts
@@ -0,0 +1,31 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD Insert', () => {
+ it('can insert given record to the store', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ await store.$repo(User).insert({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_InsertOrUpdate.spec.ts b/test/feature/repositories/Crud_InsertOrUpdate.spec.ts
new file mode 100644
index 00000000..91df28fa
--- /dev/null
+++ b/test/feature/repositories/Crud_InsertOrUpdate.spec.ts
@@ -0,0 +1,39 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD Insert or Update', () => {
+ it('can insert or update given record to the store', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ await store.$repo(User).insert({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ await store.$repo(User).insertOrUpdate({
+ data: [
+ { id: 1, name: 'Jane Doe' },
+ { id: 2, name: 'Johnny Doe' }
+ ]
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'Jane Doe' },
+ 2: { $id: '2', id: 2, name: 'Johnny Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_New.spec.ts b/test/feature/repositories/Crud_New.spec.ts
new file mode 100644
index 00000000..b55c0002
--- /dev/null
+++ b/test/feature/repositories/Crud_New.spec.ts
@@ -0,0 +1,29 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD New', () => {
+ it('can insert a new record to the store', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.uid(),
+ name: this.string('John Doe')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ await store.$repo(User).new()
+
+ const expected = createState({
+ users: {
+ '$uid1': { $id: '$uid1', id: '$uid1', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_Retrieve.spec.ts b/test/feature/repositories/Crud_Retrieve.spec.ts
new file mode 100644
index 00000000..e24f39b0
--- /dev/null
+++ b/test/feature/repositories/Crud_Retrieve.spec.ts
@@ -0,0 +1,185 @@
+import { createStore } from 'test/support/Helpers'
+import { Model, Query } from '@/index'
+
+describe('Feature - Repositories - CRUD Retrieve', () => {
+ it('can get a new query instance', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const store = createStore([User])
+
+ const query = store.$repo(User).query()
+
+ expect(query).toBeInstanceOf(Query)
+ })
+
+ it('can get all records', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null)
+ }
+ }
+
+ id!: number
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ await userRepo.insert({
+ data: [{ id: 1 }, { id: 2 }]
+ })
+
+ const users = userRepo.all()
+
+ expect(users.length).toBe(2)
+ expect(users[0].id).toBe(1)
+ expect(users[1].id).toBe(2)
+ })
+
+ it('can find a single record', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null)
+ }
+ }
+
+ id!: number
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ await userRepo.insert({
+ data: [{ id: 1 }, { id: 2 }]
+ })
+
+ const user = userRepo.find(2) as User
+
+ expect(user.id).toBe(2)
+ })
+
+ it('can find a single record with composite primary key', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static primaryKey = ['idA', 'idB']
+
+ static fields () {
+ return {
+ idA: this.attr(null),
+ idB: this.attr(null)
+ }
+ }
+
+ idA!: number
+ idB!: number
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ await userRepo.insert({
+ data: [{ idA: 1, idB: 2 }, { idA: 3, idB: 4 }]
+ })
+
+ const user = userRepo.find([1, 2]) as User
+
+ expect(user.idA).toBe(1)
+ expect(user.idB).toBe(2)
+ })
+
+ it('can find records by ids', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null)
+ }
+ }
+
+ id!: number
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ await userRepo.insert({
+ data: [{ id: 1 }, { id: 2 }, { id: 3 }]
+ })
+
+ const users = userRepo.findIn([1, 3])
+
+ expect(users[0].id).toBe(1)
+ expect(users[1].id).toBe(3)
+ })
+
+ it('can find records by ids with composite primary key', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static primaryKey = ['idA', 'idB']
+
+ static fields () {
+ return {
+ idA: this.attr(null),
+ idB: this.attr(null)
+ }
+ }
+
+ idA!: number
+ idB!: number
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ await userRepo.insert({
+ data: [{ idA: 1, idB: 2 }, { idA: 3, idB: 4 }, { idA: 5, idB: 6 }]
+ })
+
+ const users = userRepo.findIn([[1, 2], [5, 6]])
+
+ expect(users[0].idA).toBe(1)
+ expect(users[0].idB).toBe(2)
+ expect(users[1].idA).toBe(5)
+ expect(users[1].idB).toBe(6)
+ })
+
+ it('can check whether record exists', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null)
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ expect(userRepo.exists()).toBe(false)
+
+ await userRepo.insert({
+ data: { id: 1 }
+ })
+
+ expect(userRepo.exists()).toBe(true)
+ })
+})
diff --git a/test/feature/repositories/Crud_Update.spec.ts b/test/feature/repositories/Crud_Update.spec.ts
new file mode 100644
index 00000000..6acad1e2
--- /dev/null
+++ b/test/feature/repositories/Crud_Update.spec.ts
@@ -0,0 +1,35 @@
+import { createStore, createState } from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('Feature - Repositories - CRUD Update', () => {
+ it('can update record by including primary key in the data', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields () {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ const user = store.$repo(User)
+
+ await user.insert({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ await user.update({ id: 1, name: 'Jane Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Repository.spec.ts b/test/feature/repositories/Repository.spec.ts
new file mode 100644
index 00000000..9bef239c
--- /dev/null
+++ b/test/feature/repositories/Repository.spec.ts
@@ -0,0 +1,100 @@
+import { createStore } from 'test/support/Helpers'
+import Repository from '@/repository/Repository'
+import Model from '@/model/Model'
+
+describe('Feature - Repository', () => {
+ it('can retrieve a new repository instance from the store', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const store = createStore([User])
+
+ const user = store.$repo(User)
+
+ expect(user).toBeInstanceOf(Repository)
+ })
+
+ it('can instantiate a new model instance without a record', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ expect(userRepo.make()).toBeInstanceOf(User)
+ })
+
+ it('can instantiate a new model instance with a record', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute('')
+ name!: string
+
+ // @Attribute('')
+ email!: string
+
+ static fields () {
+ return {
+ id: this.attr(''),
+ name: this.attr('')
+ }
+ }
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(User)
+
+ const user = userRepo.make({ name: 'John Doe' })
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.name).toBe('John Doe')
+ })
+
+ it('injects store instance to the instantiated model.', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const store = createStore([User])
+
+ const user = store.$repo(User).make()
+
+ expect(user.$store()).toBe(store)
+ })
+
+ it('can retrieve a custom repository', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ class UserRepository extends Repository {
+ model = User
+ foo = 'bar'
+ }
+
+ const store = createStore([User])
+
+ const userRepo = store.$repo(UserRepository)
+
+ expect(userRepo.foo).toBe('bar')
+ })
+
+ it('throws if the custom repository has no assigned model', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ class UserRepository extends Repository {
+ foo = 'bar'
+ }
+
+ const store = createStore([User])
+
+ expect(() => store.$repo(UserRepository)).toThrow()
+ })
+})
diff --git a/test/unit/database/Database.spec.ts b/test/unit/database/Database.spec.ts
index ea67335d..793d604e 100644
--- a/test/unit/database/Database.spec.ts
+++ b/test/unit/database/Database.spec.ts
@@ -3,30 +3,6 @@ import Database from '@/database/Database'
import Model from '@/model/Model'
describe('Unit – Database', () => {
- it('registers itself to the store instance', () => {
- const database = new Database()
-
- const store = createStoreFromDatabase(database)
-
- expect(store.$db()).toBe(database)
- })
-
- it('binds the store instance to the registered models.', () => {
- class User extends Model { static entity = 'users' }
-
- const database1 = new Database()
- const database2 = new Database()
-
- database1.register(User)
- database2.register(User)
-
- const store1 = createStoreFromDatabase(database1)
- const store2 = createStoreFromDatabase(database2)
-
- expect(store1.$db().model('users').database()).toBe(database1)
- expect(store2.$db().model('users').database()).toBe(database2)
- })
-
it('can fetch all models', () => {
class User extends Model { static entity = 'users' }
class Post extends Model { static entity = 'posts' }
@@ -38,8 +14,8 @@ describe('Unit – Database', () => {
const models = database.models()
- expect(models.users.prototype).toBeInstanceOf(User)
- expect(models.posts.prototype).toBeInstanceOf(Post)
+ expect(models.users).toBe(User)
+ expect(models.posts).toBe(Post)
})
it('can fetch a model by string', () => {
@@ -53,7 +29,7 @@ describe('Unit – Database', () => {
const model = database.model('users')
- expect(model.prototype).toBeInstanceOf(User)
+ expect(model).toBe(User)
})
it('can fetch a model by type', () => {
@@ -67,7 +43,7 @@ describe('Unit – Database', () => {
const model = database.model(User)
- expect(model.prototype).toBeInstanceOf(User)
+ expect(model).toBe(User)
})
it('throws when a model is not found', () => {
@@ -96,9 +72,9 @@ describe('Unit – Database', () => {
const models = database.baseModels()
- expect(models.users.prototype).toBeInstanceOf(User)
- expect(models.guests.prototype).toBeInstanceOf(User)
- expect(models.admins.prototype).toBeInstanceOf(User)
+ expect(models.users).toBe(User)
+ expect(models.guests).toBe(User)
+ expect(models.admins).toBe(User)
})
it('can fetch a base model by string', () => {
@@ -115,7 +91,7 @@ describe('Unit – Database', () => {
const model = database.baseModel('guests')
- expect(model.prototype).toBeInstanceOf(User)
+ expect(model).toBe(User)
})
it('can fetch a base model by type', () => {
@@ -132,7 +108,7 @@ describe('Unit – Database', () => {
const model = database.baseModel(Guest)
- expect(model.prototype).toBeInstanceOf(User)
+ expect(model).toBe(User)
})
it('throws when a base model is not found', () => {
@@ -196,4 +172,34 @@ describe('Unit – Database', () => {
expect(() => database.module('posts')).toThrowError('[Vuex ORM]')
})
+
+ it('binds the store instance to the registered models.', () => {
+ jest.spyOn(global.console, 'warn').mockImplementation()
+
+ class User extends Model { static entity = 'users' }
+
+ const database1 = new Database()
+ const database2 = new Database()
+
+ database1.register(User)
+ database2.register(User)
+
+ const store1 = createStoreFromDatabase(database1)
+ const store2 = createStoreFromDatabase(database2)
+
+ expect(store1.$db().model('users').database()).toBe(database1)
+ expect(store2.$db().model('users').database()).toBe(database2)
+ })
+
+ it('warns when using the deprecated `$db` method', () => {
+ const warn = jest.spyOn(global.console, 'warn').mockImplementation()
+
+ const database = new Database()
+
+ const store = createStoreFromDatabase(database)
+
+ store.$db()
+
+ expect(warn).toBeCalled()
+ })
})
diff --git a/test/unit/query/Query.spec.ts b/test/unit/query/Query.spec.ts
index f8e83a7b..591ba930 100644
--- a/test/unit/query/Query.spec.ts
+++ b/test/unit/query/Query.spec.ts
@@ -16,8 +16,8 @@ describe('Unit – Query', () => {
const models = (new Query(store, 'users')).getModels()
- expect(models.users.prototype).toBeInstanceOf(User)
- expect(models.posts.prototype).toBeInstanceOf(Post)
+ expect(models.users).toBe(User)
+ expect(models.posts).toBe(Post)
})
it('can retrieve a specific model from the database instance', () => {
@@ -25,7 +25,7 @@ describe('Unit – Query', () => {
const model = (new Query(store, 'users')).getModel('posts')
- expect(model.prototype).toBeInstanceOf(Post)
+ expect(model).toBe(Post)
})
it('retrieves the model corresponds to the entity of Query if the name is not specified', () => {
@@ -33,6 +33,6 @@ describe('Unit – Query', () => {
const model = (new Query(store, 'users')).getModel()
- expect(model.prototype).toBeInstanceOf(User)
+ expect(model).toBe(User)
})
})
diff --git a/test/unit/support/Utils.spec.ts b/test/unit/support/Utils.spec.ts
index 85ca822b..1faa6906 100644
--- a/test/unit/support/Utils.spec.ts
+++ b/test/unit/support/Utils.spec.ts
@@ -124,82 +124,37 @@ describe('Unit - Utils', () => {
})
describe('#cloneDeep', () => {
- it('should clone arrays', async () => {
- const a = [{ a: 0 }, { b: 1 }]
-
- expect(Utils.cloneDeep(a)).toEqual(a)
-
- const b = [1, 2, 3]
-
- expect(b).toEqual(b)
-
- const c = [{ a: 0 }, { b: 1 }]
- const d = Utils.cloneDeep(c)
-
- expect(d).toEqual(c)
- expect(d[0]).toEqual(c[0])
-
- const e = [0, 'a', {}, [{}]]
-
- expect(Utils.cloneDeep(e)).toEqual(e)
- })
-
- it('should deeply clone an array', async () => {
- const a = [[{ a: 'b' }], [{ a: 'b' }]]
- const b = Utils.cloneDeep(a)
-
- expect(b).not.toBe(a)
- expect(b[0]).not.toBe(a[0])
- expect(b[1]).not.toBe(a[1])
- expect(b).toEqual(a)
- })
-
- it('should deeply clone arrays by reference', async () => {
- const a: any = { a: 'b' }
- const b = [a]
- const c = Utils.cloneDeep(b)
-
- a.c = 'd'
-
- expect(c).not.toEqual(b)
- })
-
- it('should clone objects', () => {
- const a = { a: 1, b: 2, c: 3 }
-
- expect(Utils.cloneDeep(a)).toEqual(a)
- expect(Utils.cloneDeep(a)).not.toBe(a)
- })
-
- it('should deeply clone objects', async () => {
- const a = {
- a: { a: 1, b: 2, c: 3 },
- b: { a: 1, b: 2, c: 3 },
- c: { a: 1, b: 2, c: 3 }
+ it('can create a deep clone of an object', () => {
+ const data = {
+ id: 1,
+ nested: [
+ {
+ id: 1,
+ deep: [
+ {
+ id: 1,
+ deeper: {
+ id: 2
+ }
+ },
+ {
+ id: 2,
+ deeper: {
+ id: 3
+ }
+ }
+ ]
+ }
+ ]
}
- expect(Utils.cloneDeep(a)).toEqual(a)
- expect(Utils.cloneDeep(a)).not.toBe(a)
- expect(Utils.cloneDeep(a).a).toEqual(a.a)
- expect(Utils.cloneDeep(a).a).not.toBe(a.a)
- expect(Utils.cloneDeep(a).b).toEqual(a.b)
- expect(Utils.cloneDeep(a).b).not.toBe(a.b)
- expect(Utils.cloneDeep(a).c).toEqual(a.c)
- expect(Utils.cloneDeep(a).c).not.toBe(a.c)
- })
+ const clone = Utils.cloneDeep(data)
- it('should deeply clone objects by reference', async () => {
- const a: Record = { a: 'b' }
- const b = Utils.cloneDeep(a)
+ expect(clone).toStrictEqual(data)
- b.c = 'd'
-
- expect(b).not.toEqual(a)
- })
+ delete data.nested[0].deep[0].deeper.id
- it('should return primitives', async () => {
- expect(Utils.cloneDeep('foo')).toEqual('foo')
- expect(Utils.cloneDeep(0)).toEqual(0)
+ expect(clone).not.toStrictEqual(data)
})
})
})
diff --git a/tslint.json b/tslint.json
index 88877985..7b861221 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,3 +1,6 @@
{
- "extends": "tslint-config-standard"
+ "extends": "tslint-config-standard",
+ "rules": {
+ "deprecation": false
+ }
}
From 4b31ac3b7c3f36c6e878613c5bd5e6ccc7b5fbf0 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Tue, 31 Mar 2020 18:29:36 +0100
Subject: [PATCH 02/56] feat(model): enable passing data to persistent methods
(#554)
close #554
---
src/model/Model.ts | 56 +--
src/modules/Actions.ts | 28 +-
src/modules/options/Actions.ts | 13 +
src/modules/payloads/Actions.ts | 21 +-
src/modules/support/PayloadBuilder.ts | 44 +++
test/feature/aggregates/Aggregates.spec.ts | 54 ++-
test/feature/attributes/Boolean.spec.ts | 66 ++--
test/feature/attributes/Number.spec.ts | 58 ++-
test/feature/attributes/String.spec.ts | 48 ++-
test/feature/attributes/Uid.spec.ts | 13 +-
test/feature/basics/Create.spec.ts | 16 +-
test/feature/basics/Delete.spec.ts | 66 ++--
.../basics/Delete_Composite_Key.spec.ts | 17 +-
test/feature/basics/Exists.spec.ts | 12 +-
test/feature/basics/Insert.spec.ts | 6 +-
test/feature/basics/PersistOptions.spec.ts | 78 ++---
test/feature/basics/Retrieve.spec.ts | 20 +-
test/feature/basics/Update.spec.ts | 16 +-
test/feature/hooks/Global.spec.ts | 9 +-
test/feature/hooks/Global_Create.spec.ts | 16 +-
test/feature/hooks/Global_Delete.spec.ts | 12 +-
test/feature/hooks/Global_Update.spec.ts | 24 +-
test/feature/hooks/Local_Binding.spec.ts | 4 +-
test/feature/hooks/Local_Create.spec.ts | 22 +-
test/feature/hooks/Local_Delete.spec.ts | 24 +-
test/feature/hooks/Local_Insert.spec.ts | 12 +-
test/feature/hooks/Local_Update.spec.ts | 22 +-
test/feature/inheritance/Inheritance.spec.ts | 16 +-
.../inheritance/Inheritance_CRUD.spec.ts | 119 +++----
.../Inheritance_Discriminator.spec.ts | 36 +-
.../inheritance/Inheritance_Relations.spec.ts | 94 ++---
test/feature/models/All.spec.ts | 20 +-
test/feature/models/Create.spec.ts | 56 ++-
test/feature/models/Insert.spec.ts | 64 ++--
test/feature/models/InsertOrUpdate.spec.ts | 36 +-
test/feature/models/Query.spec.ts | 20 +-
test/feature/models/Update.spec.ts | 13 +-
.../relations/BelongsToMany_Retrieve.spec.ts | 101 ++----
test/feature/relations/HasMany.spec.ts | 159 ++++-----
test/feature/relations/HasManyBy.spec.ts | 46 +--
test/feature/relations/HasManyThrough.spec.ts | 170 ++++-----
test/feature/relations/HasOne.spec.ts | 58 ++-
.../relations/MorphMany_Persist.spec.ts | 132 +++----
.../relations/MorphMany_Retrieve.spec.ts | 78 ++---
.../relations/MorphOne_Persist.spec.ts | 96 +++--
.../relations/MorphOne_Retrieve.spec.ts | 82 ++---
test/feature/relations/MorphTo.spec.ts | 136 ++++++--
.../relations/MorphToMany_Persist.spec.ts | 121 ++++---
.../relations/MorphToMany_Retrieve.spec.ts | 126 +++----
.../relations/MorphedByMany_Persist.spec.ts | 50 ++-
.../relations/MorphedByMany_Retrieve.spec.ts | 92 ++---
.../relations/Persist_NestedMorph.spec.ts | 24 +-
.../relations/Retrieve_Constraint.spec.ts | 12 +-
.../relations/Retrieve_DeepLoad.spec.ts | 22 +-
test/feature/relations/Retrieve_Has.spec.ts | 171 +++++----
.../relations/Retrieve_SelfRelation.spec.ts | 9 +-
.../relations/Retrieve_StringDefine.spec.ts | 8 +-
test/feature/relations/Retrieve_With.spec.ts | 330 ++++++++----------
.../Retrieve_With_NestedConstraints.spec.ts | 16 +-
59 files changed, 1459 insertions(+), 1831 deletions(-)
create mode 100644 src/modules/options/Actions.ts
create mode 100644 src/modules/support/PayloadBuilder.ts
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 812184c9..d9998532 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -15,11 +15,13 @@ import Mutators from '../attributes/contracts/Mutators'
import Predicate from '../query/contracts/Predicate'
import Query from '../query/Query'
import * as Payloads from '../modules/payloads/Actions'
+import * as PersistOptions from '../modules/options/Actions'
import Fields from './contracts/Fields'
import FieldCache from './contracts/FieldCache'
import ModelState from './contracts/State'
import InheritanceTypes from './contracts/InheritanceTypes'
import { toAttributes, toJson } from './Serialize'
+import PayloadBuilder from '../modules/support/PayloadBuilder'
export default class Model {
/**
@@ -383,29 +385,29 @@ export default class Model {
* store. If you want to save data without replacing existing records,
* use the `insert` method instead.
*/
- static create (this: T, payload: Payloads.Create): Promise {
- return this.dispatch('create', payload)
+ static create (this: T, payload: Payloads.Create, options?: PersistOptions.Create): Promise {
+ return this.dispatch('create', PayloadBuilder.normalize(payload, options))
}
/**
* Insert records.
*/
- static insert (this: T, payload: Payloads.Insert): Promise {
- return this.dispatch('insert', payload)
+ static insert (this: T, payload: Payloads.Insert, options?: PersistOptions.Insert): Promise {
+ return this.dispatch('insert', PayloadBuilder.normalize(payload, options))
}
/**
* Update records.
*/
- static update (this: T, payload: Payloads.Update): Promise {
- return this.dispatch('update', payload)
+ static update (this: T, payload: Payloads.Update, options?: PersistOptions.Update): Promise {
+ return this.dispatch('update', PayloadBuilder.normalize(payload, options))
}
/**
* Insert or update records.
*/
- static insertOrUpdate (this: T, payload: Payloads.InsertOrUpdate): Promise {
- return this.dispatch('insertOrUpdate', payload)
+ static insertOrUpdate (this: T, payload: Payloads.InsertOrUpdate, options?: PersistOptions.InsertOrUpdate): Promise {
+ return this.dispatch('insertOrUpdate', PayloadBuilder.normalize(payload, options))
}
/**
@@ -686,7 +688,7 @@ export default class Model {
}
/**
- * Call Vuex Getetrs.
+ * Call Vuex Getters.
*/
$getters (method: string): any {
return this.$self().getters(method)
@@ -730,44 +732,48 @@ export default class Model {
/**
* Create records.
*/
- async $create (payload: Payloads.Create): Promise {
- return this.$dispatch('create', payload)
+ async $create (payload: Payloads.Create, options?: PersistOptions.Create): Promise {
+ return this.$dispatch('create', PayloadBuilder.normalize(payload, options))
}
/**
- * Create records.
+ * Insert records.
*/
- async $insert (payload: Payloads.Insert): Promise {
- return this.$dispatch('insert', payload)
+ async $insert (payload: Payloads.Insert, options?: PersistOptions.Insert): Promise {
+ return this.$dispatch('insert', PayloadBuilder.normalize(payload, options))
}
/**
* Update records.
*/
- async $update (payload: Payloads.Update): Promise {
+ async $update (payload: Payloads.Update, options?: PersistOptions.Update): Promise {
if (Utils.isArray(payload)) {
- return this.$dispatch('update', payload)
+ return this.$dispatch('update', PayloadBuilder.normalize(payload, options))
}
- if (payload.where !== undefined) {
- return this.$dispatch('update', payload)
+ if (payload.where !== undefined || (options && options.where !== undefined)) {
+ return this.$dispatch('update', PayloadBuilder.normalize(payload, options))
}
if (this.$self().getIndexIdFromRecord(payload) === null) {
- return this.$dispatch('update', {
- where: this.$self().getIdFromRecord(this),
- data: payload
- })
+ /* istanbul ignore else */
+ if (!options) {
+ options = {}
+ }
+
+ options.where = this.$self().getIdFromRecord(this)
+
+ return this.$dispatch('update', PayloadBuilder.normalize(payload, options))
}
- return this.$dispatch('update', payload)
+ return this.$dispatch('update', PayloadBuilder.normalize(payload, options))
}
/**
* Insert or update records.
*/
- async $insertOrUpdate (payload: Payloads.InsertOrUpdate): Promise {
- return this.$dispatch('insertOrUpdate', payload)
+ async $insertOrUpdate (payload: Payloads.InsertOrUpdate, options?: PersistOptions.InsertOrUpdate): Promise {
+ return this.$dispatch('insertOrUpdate', PayloadBuilder.normalize(payload, options))
}
/**
diff --git a/src/modules/Actions.ts b/src/modules/Actions.ts
index c43f083d..a44e0947 100644
--- a/src/modules/Actions.ts
+++ b/src/modules/Actions.ts
@@ -1,4 +1,3 @@
-import { isArray } from '../support/Utils'
import Item from '../data/Item'
import Collection from '../data/Collection'
import Collections from '../data/Collections'
@@ -6,6 +5,7 @@ import Model from '../model/Model'
import ActionsContract from './contracts/Actions'
import ActionContext from './contracts/ActionContext'
import * as Payloads from './payloads/Actions'
+import PayloadBuilder from './support/PayloadBuilder'
/**
* Create new data with all fields filled by default values.
@@ -25,8 +25,9 @@ async function newRecord (context: ActionContext): Promise {
async function create (context: ActionContext, payload: Payloads.Create): Promise {
const state = context.state
const entity = state.$name
+ const data = PayloadBuilder.createPersistPayload(payload)
- return context.dispatch(`${state.$connection}/create`, { ...payload, entity }, { root: true })
+ return context.dispatch(`${state.$connection}/create`, { entity, ...data }, { root: true })
}
/**
@@ -37,8 +38,9 @@ async function create (context: ActionContext, payload: Payloads.Create): Promis
async function insert (context: ActionContext, payload: Payloads.Insert): Promise {
const state = context.state
const entity = state.$name
+ const data = PayloadBuilder.createPersistPayload(payload)
- return context.dispatch(`${state.$connection}/insert`, { ...payload, entity }, { root: true })
+ return context.dispatch(`${state.$connection}/insert`, { entity, ...data }, { root: true })
}
/**
@@ -47,22 +49,9 @@ async function insert (context: ActionContext, payload: Payloads.Insert): Promis
async function update (context: ActionContext, payload: Payloads.Update): Promise- {
const state = context.state
const entity = state.$name
+ const data = PayloadBuilder.createPersistPayload(payload)
- // If the payload is an array, then the payload should be an array of
- // data so let's pass the whole payload as data.
- if (isArray(payload)) {
- return context.dispatch(`${state.$connection}/update`, { entity, data: payload }, { root: true })
- }
-
- // If the payload doesn't have `data` property, we'll assume that
- // the user has passed the object as the payload so let's define
- // the whole payload as a data.
- if (payload.data === undefined) {
- return context.dispatch(`${state.$connection}/update`, { entity, data: payload }, { root: true })
- }
-
- // Else destructure the payload and let root action handle it.
- return context.dispatch(`${state.$connection}/update`, { entity, ...payload }, { root: true })
+ return context.dispatch(`${state.$connection}/update`, { entity, ...data }, { root: true })
}
/**
@@ -73,8 +62,9 @@ async function update (context: ActionContext, payload: Payloads.Update): Promis
async function insertOrUpdate (context: ActionContext, payload: Payloads.InsertOrUpdate): Promise {
const state = context.state
const entity = state.$name
+ const data = PayloadBuilder.createPersistPayload(payload)
- return context.dispatch(`${state.$connection}/insertOrUpdate`, { entity, ...payload }, { root: true })
+ return context.dispatch(`${state.$connection}/insertOrUpdate`, { entity, ...data }, { root: true })
}
/**
diff --git a/src/modules/options/Actions.ts b/src/modules/options/Actions.ts
new file mode 100644
index 00000000..4629e0db
--- /dev/null
+++ b/src/modules/options/Actions.ts
@@ -0,0 +1,13 @@
+import { Condition } from '../payloads/Actions'
+import PrimaryKey from '../../query/options/PrimaryKey'
+import PersistOptions from '../../query/options/PersistOptions'
+
+export type Create = PersistOptions
+
+export type Insert = PersistOptions
+
+export interface Update extends PersistOptions {
+ where?: PrimaryKey | Condition | null
+}
+
+export type InsertOrUpdate = PersistOptions
diff --git a/src/modules/payloads/Actions.ts b/src/modules/payloads/Actions.ts
index 11be4e4f..5cc0e997 100644
--- a/src/modules/payloads/Actions.ts
+++ b/src/modules/payloads/Actions.ts
@@ -4,12 +4,18 @@ import PersistOptions from '../../query/options/PersistOptions'
export type Condition = (record: Record) => boolean
-export interface Create extends PersistOptions {
- data: Record | Record[]
+export type Create = CreateObject | Record[]
+
+export interface CreateObject extends PersistOptions {
+ data?: Record | Record[]
+ [key: string]: any
}
-export interface Insert extends PersistOptions {
- data: Record | Record[]
+export type Insert = InsertObject | Record[]
+
+export interface InsertObject extends PersistOptions {
+ data?: Record | Record[]
+ [key: string]: any
}
export type Update = UpdateObject | Record[]
@@ -20,8 +26,11 @@ export interface UpdateObject extends PersistOptions {
[key: string]: any
}
-export interface InsertOrUpdate extends PersistOptions {
- data: Record | Record[]
+export type InsertOrUpdate = InsertOrUpdateObject | Record[]
+
+export interface InsertOrUpdateObject extends PersistOptions {
+ data?: Record | Record[]
+ [key: string]: any
}
export type DeleteById = string | number | (number | string)[]
diff --git a/src/modules/support/PayloadBuilder.ts b/src/modules/support/PayloadBuilder.ts
new file mode 100644
index 00000000..985f83da
--- /dev/null
+++ b/src/modules/support/PayloadBuilder.ts
@@ -0,0 +1,44 @@
+import { Create, Insert, Update, InsertOrUpdate } from '../payloads/Actions'
+import OptionsBuilder from './OptionsBuilder'
+
+export type PersistPayload = Create | Insert | Update | InsertOrUpdate
+
+export default class PayloadBuilder {
+ /**
+ * Create downstream payload from input data to determine the style of data
+ * being provided for downward compatibility.
+ */
+ static createPersistPayload (payload: PersistPayload): PersistPayload {
+ // If the payload is an array, then the payload should be an array of
+ // data therefore the whole payload should be declared as `data`.
+ if (Array.isArray(payload)) {
+ return { data: payload }
+ }
+
+ // If the payload doesn't have a `data` property, it can be assumed that
+ // the user has passed an object as the payload therefore the entire
+ // payload should be declared as `data`
+ if (payload.data === undefined) {
+ return { data: payload }
+ }
+
+ // It can safely be assumed the user is providing payload with `data` intact.
+ return payload
+ }
+
+ /**
+ * Normalize persist payload by converting the new style of persisting data
+ * through method arguments, while maintaining existing style (data key),
+ * to pass on to the module API.
+ */
+ static normalize (payload?: any, options?: any): PersistPayload {
+ const persistPayload = this.createPersistPayload(payload)
+ const persistOptions = OptionsBuilder.createPersistOptions(payload)
+
+ return {
+ ...persistPayload,
+ ...persistOptions,
+ ...options
+ }
+ }
+}
diff --git a/test/feature/aggregates/Aggregates.spec.ts b/test/feature/aggregates/Aggregates.spec.ts
index f5d6a11a..1c6f77f9 100644
--- a/test/feature/aggregates/Aggregates.spec.ts
+++ b/test/feature/aggregates/Aggregates.spec.ts
@@ -24,27 +24,23 @@ describe('Feature – Aggregates', () => {
})
it('can get count of the data', async () => {
- await User.create({
- data: [
- { id: 1, role: 'admin' },
- { id: 2, role: 'user' },
- { id: 3, role: 'admin' }
- ]
- })
+ await User.create([
+ { id: 1, role: 'admin' },
+ { id: 2, role: 'user' },
+ { id: 3, role: 'admin' }
+ ])
expect(User.query().count()).toBe(3)
expect(User.query().where('role', 'admin').count()).toBe(2)
})
it('can get max value of the specified field', async () => {
- await User.create({
- data: [
- { id: 8, role: 'admin' },
- { id: 12, role: 'user' },
- { id: 11, role: 'admin' },
- { id: 'A', role: 'admin' }
- ]
- })
+ await User.create([
+ { id: 8, role: 'admin' },
+ { id: 12, role: 'user' },
+ { id: 11, role: 'admin' },
+ { id: 'A', role: 'admin' }
+ ])
expect(User.query().max('id')).toBe(12)
expect(User.query().max('role')).toBe(0)
@@ -52,14 +48,12 @@ describe('Feature – Aggregates', () => {
})
it('can get min value of the specified field', async () => {
- await User.create({
- data: [
- { id: 8, role: 'admin' },
- { id: 12, role: 'user' },
- { id: 11, role: 'admin' },
- { id: 'A', role: 'admin' }
- ]
- })
+ await User.create([
+ { id: 8, role: 'admin' },
+ { id: 12, role: 'user' },
+ { id: 11, role: 'admin' },
+ { id: 'A', role: 'admin' }
+ ])
expect(User.query().min('id')).toBe(8)
expect(User.query().min('role')).toBe(0)
@@ -67,14 +61,12 @@ describe('Feature – Aggregates', () => {
})
it('can get sum value of the specified field', async () => {
- await User.create({
- data: [
- { id: 8, role: 'admin' },
- { id: 12, role: 'user' },
- { id: 11, role: 'admin' },
- { id: 'A', role: 'admin' }
- ]
- })
+ await User.create([
+ { id: 8, role: 'admin' },
+ { id: 12, role: 'user' },
+ { id: 11, role: 'admin' },
+ { id: 'A', role: 'admin' }
+ ])
expect(User.query().sum('id')).toBe(31)
expect(User.query().where('role', 'admin').sum('id')).toBe(19)
diff --git a/test/feature/attributes/Boolean.spec.ts b/test/feature/attributes/Boolean.spec.ts
index b249142c..a7caab4d 100644
--- a/test/feature/attributes/Boolean.spec.ts
+++ b/test/feature/attributes/Boolean.spec.ts
@@ -22,18 +22,16 @@ describe('Feature – Attributes – Boolean', () => {
it('casts the value to `Boolean` when creating data', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, bool: '' },
- { id: 3, bool: 'string' },
- { id: 4, bool: '0' },
- { id: 5, bool: 0 },
- { id: 6, bool: 1 },
- { id: 7, bool: true },
- { id: 8, bool: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, bool: '' },
+ { id: 3, bool: 'string' },
+ { id: 4, bool: '0' },
+ { id: 5, bool: 0 },
+ { id: 6, bool: 1 },
+ { id: 7, bool: true },
+ { id: 8, bool: null }
+ ])
const expected = createState({
users: {
@@ -54,18 +52,16 @@ describe('Feature – Attributes – Boolean', () => {
it('casts the value to `Boolean` when retrieving data', async () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, bool: '' },
- { id: 3, bool: 'string' },
- { id: 4, bool: '0' },
- { id: 5, bool: 0 },
- { id: 6, bool: 1 },
- { id: 7, bool: true },
- { id: 8, bool: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, bool: '' },
+ { id: 3, bool: 'string' },
+ { id: 4, bool: '0' },
+ { id: 5, bool: 0 },
+ { id: 6, bool: 1 },
+ { id: 7, bool: true },
+ { id: 8, bool: null }
+ ])
const users = User.all()
@@ -99,18 +95,16 @@ describe('Feature – Attributes – Boolean', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, bool: '' },
- { id: 3, bool: 'string' },
- { id: 4, bool: '0' },
- { id: 5, bool: 0 },
- { id: 6, bool: 1 },
- { id: 7, bool: true },
- { id: 8, bool: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, bool: '' },
+ { id: 3, bool: 'string' },
+ { id: 4, bool: '0' },
+ { id: 5, bool: 0 },
+ { id: 6, bool: 1 },
+ { id: 7, bool: true },
+ { id: 8, bool: null }
+ ])
const users = User.all()
diff --git a/test/feature/attributes/Number.spec.ts b/test/feature/attributes/Number.spec.ts
index 27063aeb..6c3fe19d 100644
--- a/test/feature/attributes/Number.spec.ts
+++ b/test/feature/attributes/Number.spec.ts
@@ -22,18 +22,16 @@ describe('Feature – Attributes – Number', () => {
it('casts the value to `Number` when creating data', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, num: 1 },
- { id: 3, num: 1.5 },
- { id: 4, num: '2' },
- { id: 5, num: '2.5' },
- { id: 6, num: true },
- { id: 7, num: false },
- { id: 8, num: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, num: 1 },
+ { id: 3, num: 1.5 },
+ { id: 4, num: '2' },
+ { id: 5, num: '2.5' },
+ { id: 6, num: true },
+ { id: 7, num: false },
+ { id: 8, num: null }
+ ])
const expected = createState({
users: {
@@ -54,16 +52,14 @@ describe('Feature – Attributes – Number', () => {
it('casts the value to `Number` when retrieving data', async () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, num: 1 },
- { id: 3, num: '2' },
- { id: 4, num: true },
- { id: 5, num: false },
- { id: 6, num: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, num: 1 },
+ { id: 3, num: '2' },
+ { id: 4, num: true },
+ { id: 5, num: false },
+ { id: 6, num: null }
+ ])
const users = User.all()
@@ -95,16 +91,14 @@ describe('Feature – Attributes – Number', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, num: 1 },
- { id: 3, num: '2' },
- { id: 4, num: true },
- { id: 5, num: false },
- { id: 6, num: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, num: 1 },
+ { id: 3, num: '2' },
+ { id: 4, num: true },
+ { id: 5, num: false },
+ { id: 6, num: null }
+ ])
const users = User.all()
diff --git a/test/feature/attributes/String.spec.ts b/test/feature/attributes/String.spec.ts
index 06675cdc..1bfaf744 100644
--- a/test/feature/attributes/String.spec.ts
+++ b/test/feature/attributes/String.spec.ts
@@ -22,15 +22,13 @@ describe('Feature – Attributes – String', () => {
it('casts the value to `String` when creating data', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, str: 'value' },
- { id: 3, str: 1 },
- { id: 4, str: true },
- { id: 5, str: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, str: 'value' },
+ { id: 3, str: 1 },
+ { id: 4, str: true },
+ { id: 5, str: null }
+ ])
const expected = createState({
users: {
@@ -48,15 +46,13 @@ describe('Feature – Attributes – String', () => {
it('casts the value to `String` when retrieving data', async () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, str: 'value' },
- { id: 3, str: 1 },
- { id: 4, str: true },
- { id: 5, str: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, str: 'value' },
+ { id: 3, str: 1 },
+ { id: 4, str: true },
+ { id: 5, str: null }
+ ])
const users = User.all()
@@ -87,15 +83,13 @@ describe('Feature – Attributes – String', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1 },
- { id: 2, str: 'value' },
- { id: 3, str: 1 },
- { id: 4, str: true },
- { id: 5, str: null }
- ]
- })
+ await User.create([
+ { id: 1 },
+ { id: 2, str: 'value' },
+ { id: 3, str: 1 },
+ { id: 4, str: true },
+ { id: 5, str: null }
+ ])
const users = User.all()
diff --git a/test/feature/attributes/Uid.spec.ts b/test/feature/attributes/Uid.spec.ts
index ddbc855c..1e752a6f 100644
--- a/test/feature/attributes/Uid.spec.ts
+++ b/test/feature/attributes/Uid.spec.ts
@@ -28,9 +28,7 @@ describe('Feature – Attributes – Uid', () => {
it('generates uid as a default value', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [{}, {}, {}]
- })
+ await User.create([{}, {}, {}])
const expected = createState({
users: {
@@ -46,9 +44,10 @@ describe('Feature – Attributes – Uid', () => {
it('will do nothing if the value exists', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [{ id: 1, id2: 'id1' }, { id: 2, id2: 'id2' }]
- })
+ await User.create([
+ { id: 1, id2: 'id1' },
+ { id: 2, id2: 'id2' }
+ ])
const expected = createState({
users: {
@@ -82,7 +81,7 @@ describe('Feature – Attributes – Uid', () => {
it('generates user provided uid as a default value', async () => {
const store = createStore([{ model: User }])
- await User.create({ data: [{}] })
+ await User.create([{}])
const expected = createState({
users: {
diff --git a/test/feature/basics/Create.spec.ts b/test/feature/basics/Create.spec.ts
index b2f7c1c3..35c05156 100644
--- a/test/feature/basics/Create.spec.ts
+++ b/test/feature/basics/Create.spec.ts
@@ -13,10 +13,10 @@ describe('Feature – Basics – Create', () => {
}
}
- it('can create a data', async () => {
+ it('can create a record', async () => {
const store = createStore([{ model: User }])
- await User.create({
+ await store.dispatch('entities/users/create', {
data: { id: 1, name: 'John Doe' }
})
@@ -28,7 +28,7 @@ describe('Feature – Basics – Create', () => {
expect(store.state.entities.users.data).toEqual(expected)
})
- it('can create list of data', async () => {
+ it('can create a list of records', async () => {
const store = createStore([{ model: User }])
await store.dispatch('entities/users/create', {
@@ -110,7 +110,7 @@ describe('Feature – Basics – Create', () => {
expect(store.state.entities.users.data).toEqual(expected)
})
- it('returns a newly created data', async () => {
+ it('returns a newly created record', async () => {
const store = createStore([{ model: User }])
const collection = await store.dispatch('entities/users/create', {
@@ -124,7 +124,7 @@ describe('Feature – Basics – Create', () => {
expect(collection).toEqual(expected)
})
- it('returns list of newly created data', async () => {
+ it('returns list of newly created record', async () => {
const store = createStore([{ model: User }])
const collection = await store.dispatch('entities/users/create', {
@@ -144,10 +144,12 @@ describe('Feature – Basics – Create', () => {
expect(collection).toEqual(expected)
})
- it('returns null when creating empty data', async () => {
+ it('returns null when creating an empty record', async () => {
const store = createStore([{ model: User }])
- const collection = await store.dispatch('entities/users/create', { data: {} })
+ const collection = await store.dispatch('entities/users/create', {
+ data: {}
+ })
expect(collection).toEqual({})
})
diff --git a/test/feature/basics/Delete.spec.ts b/test/feature/basics/Delete.spec.ts
index b31d21cb..82f786b2 100644
--- a/test/feature/basics/Delete.spec.ts
+++ b/test/feature/basics/Delete.spec.ts
@@ -37,9 +37,7 @@ describe('Feature – Basics – Delete', () => {
it('can delete a record by specifying the id', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
await User.delete(1)
@@ -56,9 +54,7 @@ describe('Feature – Basics – Delete', () => {
it('can delete a record by specifying id as a string', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 'string_id_1' }, { id: 'string_id_2' }]
- })
+ await User.create([{ id: 'string_id_1' }, { id: 'string_id_2' }])
await User.delete('string_id_2')
@@ -75,13 +71,11 @@ describe('Feature – Basics – Delete', () => {
it('can delete records by specifying a closure', async () => {
const store = getStore()
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' },
- { id: 3, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' },
+ { id: 3, name: 'Jane Doe' }
+ ])
await User.delete(user => user.name === 'Jane Doe')
@@ -98,9 +92,7 @@ describe('Feature – Basics – Delete', () => {
it('does nothing if the specified id does not exist', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
await User.delete(3)
@@ -118,9 +110,7 @@ describe('Feature – Basics – Delete', () => {
it('returns deleted item', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
const user = await User.delete(1)
@@ -140,13 +130,11 @@ describe('Feature – Basics – Delete', () => {
it('returns all deleted records as a collection when specifying a closure', async () => {
const store = getStore()
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' },
- { id: 3, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' },
+ { id: 3, name: 'Jane Doe' }
+ ])
const users = await User.delete(user => user.name === 'Jane Doe')
@@ -169,12 +157,10 @@ describe('Feature – Basics – Delete', () => {
it('deletes itself by instance method', async () => {
const store = getStore()
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const user = User.find(2) as User
@@ -193,9 +179,7 @@ describe('Feature – Basics – Delete', () => {
it('can delete all records in the entity', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
await User.deleteAll()
@@ -210,9 +194,7 @@ describe('Feature – Basics – Delete', () => {
it('can delete all records in the entity by the instance method', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
await (new User()).$deleteAll()
@@ -227,13 +209,9 @@ describe('Feature – Basics – Delete', () => {
it('can delete all records in the entire entities', async () => {
const store = getStore()
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
- await Post.create({
- data: [{ id: 3 }, { id: 4 }]
- })
+ await Post.create([{ id: 3 }, { id: 4 }])
await store.dispatch('entities/deleteAll')
diff --git a/test/feature/basics/Delete_Composite_Key.spec.ts b/test/feature/basics/Delete_Composite_Key.spec.ts
index 8ffb6f08..2cfd4596 100644
--- a/test/feature/basics/Delete_Composite_Key.spec.ts
+++ b/test/feature/basics/Delete_Composite_Key.spec.ts
@@ -20,9 +20,10 @@ describe('Feature – Basics – Delete Composite Key', () => {
it('can delete a record by specifying the composite id as an array', async () => {
const store = getStore()
- await User.create({
- data: [{ first_id: 1, second_id: 1 }, { first_id: 1, second_id: 2 }]
- })
+ await User.create([
+ { first_id: 1, second_id: 1 },
+ { first_id: 1, second_id: 2 }
+ ])
await User.delete([1, 1])
@@ -38,12 +39,10 @@ describe('Feature – Basics – Delete Composite Key', () => {
it('deletes itself by instance method even when model has composite primary key', async () => {
const store = getStore()
- await User.create({
- data: [
- { first_id: 1, second_id: 2 },
- { first_id: 3, second_id: 4 }
- ]
- })
+ await User.create([
+ { first_id: 1, second_id: 2 },
+ { first_id: 3, second_id: 4 }
+ ])
const user = User.find([1, 2]) as User
diff --git a/test/feature/basics/Exists.spec.ts b/test/feature/basics/Exists.spec.ts
index 3d43fd60..ac9c7bf9 100644
--- a/test/feature/basics/Exists.spec.ts
+++ b/test/feature/basics/Exists.spec.ts
@@ -19,21 +19,17 @@ describe('Feature – Exists', () => {
})
it('can check if a database contains data by exists method', async () => {
- const store = createStore([{ model: User }])
+ createStore([{ model: User }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
expect(User.exists()).toBe(true)
})
it('can check if a query chain would return data', async () => {
- const store = createStore([{ model: User }])
+ createStore([{ model: User }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
expect(User.query().where('id', 3).exists()).toBe(false)
expect(User.query().where('id', 1).exists()).toBe(true)
diff --git a/test/feature/basics/Insert.spec.ts b/test/feature/basics/Insert.spec.ts
index f3ef7e10..b9fb26d0 100644
--- a/test/feature/basics/Insert.spec.ts
+++ b/test/feature/basics/Insert.spec.ts
@@ -18,7 +18,7 @@ describe('Feature – Basics – Insert', () => {
it('can insert a record', async () => {
const store = getStore()
- await User.insert({
+ await store.dispatch('entities/users/insert', {
data: { id: 1, name: 'John Doe' }
})
@@ -34,7 +34,7 @@ describe('Feature – Basics – Insert', () => {
it('does nothing if an empty object is passed', async () => {
const store = getStore()
- await User.insert({
+ await store.dispatch('entities/users/insert', {
data: {}
})
@@ -48,7 +48,7 @@ describe('Feature – Basics – Insert', () => {
it('can insert record with primary key value of `null`', async () => {
const store = getStore()
- await User.insert({
+ await store.dispatch('entities/users/insert', {
data: { id: null, name: 'John Doe' }
})
diff --git a/test/feature/basics/PersistOptions.spec.ts b/test/feature/basics/PersistOptions.spec.ts
index cc0fb2be..ac5a51bc 100644
--- a/test/feature/basics/PersistOptions.spec.ts
+++ b/test/feature/basics/PersistOptions.spec.ts
@@ -1,7 +1,7 @@
import { createStore } from 'test/support/Helpers'
import Model from '@/model/Model'
-describe('Feature – Basics – Create', () => {
+describe('Feature – Basics – Persist Options', () => {
class User extends Model {
static entity = 'users'
@@ -28,21 +28,17 @@ describe('Feature – Basics – Create', () => {
it('can `create` related records', async () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Post.create({
- data: { id: 1 }
- })
+ await Post.create({ id: 1 })
- await User.insert({
- data: {
+ await User.insert(
+ {
id: 2,
posts: [{ id: 2 }, { id: 3 }]
},
- create: ['posts']
- })
+ { create: ['posts'] }
+ )
expect(store.state.entities.users.data['1'].id).toBe(1)
expect(store.state.entities.users.data['2'].id).toBe(2)
@@ -54,21 +50,17 @@ describe('Feature – Basics – Create', () => {
it('can `insert` related records', async () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Post.create({
- data: { id: 1 }
- })
+ await Post.create({ id: 1 })
- await User.create({
- data: {
+ await User.create(
+ {
id: 2,
posts: [{ id: 2 }, { id: 3 }]
},
- insert: ['posts']
- })
+ { insert: ['posts'] }
+ )
expect(store.state.entities.users.data['1']).toBe(undefined)
expect(store.state.entities.users.data['2'].id).toBe(2)
@@ -80,27 +72,23 @@ describe('Feature – Basics – Create', () => {
it('can `update` related records', async () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Post.create({
- data: [
- { id: 1, title: 'Title 01' },
- { id: 2, title: 'Title 02' }
- ]
- })
+ await Post.create([
+ { id: 1, title: 'Title 01' },
+ { id: 2, title: 'Title 02' }
+ ])
- await User.create({
- data: {
+ await User.create(
+ {
id: 2,
posts: [
{ id: 1, title: 'Title 01-Edit' },
{ id: 2, title: 'Title 02-Edit' }
]
},
- update: ['posts']
- })
+ { update: ['posts'] }
+ )
expect(store.state.entities.users.data['1']).toBe(undefined)
expect(store.state.entities.users.data['2'].id).toBe(2)
@@ -113,27 +101,23 @@ describe('Feature – Basics – Create', () => {
it('can `insertOrUpdate` related records', async () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Post.create({
- data: [
- { id: 1, title: 'Title 01' },
- { id: 2, title: 'Title 02' }
- ]
- })
+ await Post.create([
+ { id: 1, title: 'Title 01' },
+ { id: 2, title: 'Title 02' }
+ ])
- await User.create({
- data: {
+ await User.create(
+ {
id: 2,
posts: [
{ id: 2, title: 'Title 02-Edit' },
{ id: 3, title: 'Title 03' }
]
},
- insertOrUpdate: ['posts']
- })
+ { insertOrUpdate: ['posts'] }
+ )
expect(store.state.entities.users.data['1']).toBe(undefined)
expect(store.state.entities.users.data['2'].id).toBe(2)
diff --git a/test/feature/basics/Retrieve.spec.ts b/test/feature/basics/Retrieve.spec.ts
index 191f719d..b1448d4c 100644
--- a/test/feature/basics/Retrieve.spec.ts
+++ b/test/feature/basics/Retrieve.spec.ts
@@ -124,23 +124,23 @@ describe('Feature – Retrieve', () => {
describe('#first', () => {
it('can retrieve the first item from the store', async () => {
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- await User.insert({
+ await store.dispatch('entities/users/insert', {
data: [{ id: 1 }, { id: 2 }]
})
const expected = { $id: '1', id: 1 }
- const user = User.query().first()
+ const user = store.getters['entities/users/query']().first()
expect(user).toEqual(expected)
})
it('returns `null` if it can not find any record', () => {
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- const user = User.query().first()
+ const user = store.getters['entities/users/query']().first()
expect(user).toBe(null)
})
@@ -148,23 +148,23 @@ describe('Feature – Retrieve', () => {
describe('#last', () => {
it('can retrieve the last item from the store', async () => {
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- await User.insert({
+ await store.dispatch('entities/users/insert', {
data: [{ id: 1 }, { id: 2 }]
})
const expected = { $id: '2', id: 2 }
- const user = User.query().last()
+ const user = store.getters['entities/users/query']().last()
expect(user).toEqual(expected)
})
it('returns `null` if it can not find any record', () => {
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- const user = User.query().last()
+ const user = store.getters['entities/users/query']().last()
expect(user).toBe(null)
})
diff --git a/test/feature/basics/Update.spec.ts b/test/feature/basics/Update.spec.ts
index d6c2c76a..30525120 100644
--- a/test/feature/basics/Update.spec.ts
+++ b/test/feature/basics/Update.spec.ts
@@ -24,15 +24,17 @@ describe('Feature – Basics – Update', () => {
}
}
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- await User.create({
+ await store.dispatch('entities/users/create', {
data: { id: 0, name: 'John Doe', age: 30 }
})
- await User.update({ id: 0, age: 24 })
+ await store.dispatch('entities/users/update', {
+ data: { id: 0, age: 24 }
+ })
- const user = User.find(0) as User
+ const user = store.getters['entities/users/find'](0)
expect(user.name).toBe('John Doe')
expect(user.age).toBe(24)
@@ -606,13 +608,13 @@ describe('Feature – Basics – Update', () => {
}
}
- createStore([{ model: User }])
+ const store = createStore([{ model: User }])
- await User.create({
+ await store.dispatch('entities/users/create', {
data: { id: 1, name: 'John Doe' }
})
- await User.update({
+ await store.dispatch('entities/users/update', {
where: 1,
data: { id: 2 }
})
diff --git a/test/feature/hooks/Global.spec.ts b/test/feature/hooks/Global.spec.ts
index 729d9f12..6b14fa88 100644
--- a/test/feature/hooks/Global.spec.ts
+++ b/test/feature/hooks/Global.spec.ts
@@ -28,9 +28,11 @@ describe('Feature – Hooks – Global', () => {
createStore([{ model: User }])
- await User.create({
- data: [{ id: 1, role: 'admin' }, { id: 2, role: 'admin' }, { id: 3, role: 'user' }]
- })
+ await User.create([
+ { id: 1, role: 'admin' },
+ { id: 2, role: 'admin' },
+ { id: 3, role: 'user' }
+ ])
const expected = [{ $id: '1', id: 1, role: 'admin' }]
@@ -82,6 +84,7 @@ describe('Feature – Hooks – Global', () => {
const persistedHookId1 = Query.on('afterWhere', callbackFunction)
expect(Query.hooks.afterWhere.length).toBe(1)
+
User.all()
expect(Query.hooks.afterWhere.length).toBe(1)
diff --git a/test/feature/hooks/Global_Create.spec.ts b/test/feature/hooks/Global_Create.spec.ts
index 5a7de672..bca8ef21 100644
--- a/test/feature/hooks/Global_Create.spec.ts
+++ b/test/feature/hooks/Global_Create.spec.ts
@@ -32,9 +32,7 @@ describe('Feature – Hooks – Global Create', () => {
model.role = 'admin'
})
- await User.create({
- data: [{ id: 1, role: 'admin' }, { id: 2, role: 'user' }]
- })
+ await User.create([{ id: 1, role: 'admin' }, { id: 2, role: 'user' }])
const users = User.all()
@@ -46,9 +44,7 @@ describe('Feature – Hooks – Global Create', () => {
Query.on('beforeCreate', (model: any, _entity: any) => { model.role = 'admin' })
Query.on('beforeCreate', (model: any, _entity: any) => { model.role = 'not admin' })
- await User.create({
- data: [{ id: 1, role: 'admin' }, { id: 2, role: 'user' }]
- })
+ await User.create([{ id: 1, role: 'admin' }, { id: 2, role: 'user' }])
const users = User.all()
@@ -63,9 +59,7 @@ describe('Feature – Hooks – Global Create', () => {
}
})
- await User.create({
- data: [{ id: 1, role: 'admin' }, { id: 2, role: 'user' }]
- })
+ await User.create([{ id: 1, role: 'admin' }, { id: 2, role: 'user' }])
const users = User.all()
@@ -80,9 +74,7 @@ describe('Feature – Hooks – Global Create', () => {
hit = true
})
- await User.create({
- data: { id: 1, role: 'admin' }
- })
+ await User.create({ id: 1, role: 'admin' })
expect(hit).toBe(true)
})
diff --git a/test/feature/hooks/Global_Delete.spec.ts b/test/feature/hooks/Global_Delete.spec.ts
index 47cc77b4..167d72c1 100644
--- a/test/feature/hooks/Global_Delete.spec.ts
+++ b/test/feature/hooks/Global_Delete.spec.ts
@@ -34,9 +34,7 @@ describe('Feature – Hooks – Global Delete', () => {
hit = true
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
await User.delete(1)
@@ -51,9 +49,7 @@ describe('Feature – Hooks – Global Delete', () => {
return false
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
await User.delete(1)
@@ -69,9 +65,7 @@ describe('Feature – Hooks – Global Delete', () => {
hit = true
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
await User.delete(1)
diff --git a/test/feature/hooks/Global_Update.spec.ts b/test/feature/hooks/Global_Update.spec.ts
index 157c9491..9cf99358 100644
--- a/test/feature/hooks/Global_Update.spec.ts
+++ b/test/feature/hooks/Global_Update.spec.ts
@@ -32,13 +32,9 @@ describe('Feature – Hooks – Global Update', () => {
model.role = 'admin'
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
- await User.update({
- data: { id: 1, role: 'guest' }
- })
+ await User.update({ id: 1, role: 'guest' })
const user = User.find(1)
@@ -52,13 +48,9 @@ describe('Feature – Hooks – Global Update', () => {
}
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
- await User.update({
- data: { id: 1, role: 'admin' }
- })
+ await User.update({ id: 1, role: 'admin' })
const user = User.find(1)
@@ -72,13 +64,9 @@ describe('Feature – Hooks – Global Update', () => {
hit = true
})
- await User.create({
- data: { id: 1, role: 'user' }
- })
+ await User.create({ id: 1, role: 'user' })
- await User.update({
- data: { id: 1, role: 'admin' }
- })
+ await User.update({ id: 1, role: 'admin' })
expect(hit).toBe(true)
})
diff --git a/test/feature/hooks/Local_Binding.spec.ts b/test/feature/hooks/Local_Binding.spec.ts
index 3db1e0e3..e0bb8f11 100644
--- a/test/feature/hooks/Local_Binding.spec.ts
+++ b/test/feature/hooks/Local_Binding.spec.ts
@@ -34,9 +34,7 @@ describe('Hooks – Local Binding', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
const expected = { $id: '1', id: 1, name: 'John Doe', age: 30 }
diff --git a/test/feature/hooks/Local_Create.spec.ts b/test/feature/hooks/Local_Create.spec.ts
index aa636902..56a8c79d 100644
--- a/test/feature/hooks/Local_Create.spec.ts
+++ b/test/feature/hooks/Local_Create.spec.ts
@@ -30,9 +30,7 @@ describe('Hooks – Local Create', () => {
createStore([{ model: User }])
- await User.create({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.create({ id: 1, name: 'John Doe', age: 20 })
const expected = { $id: '1', id: 1, name: 'John Doe', age: 30 }
@@ -67,9 +65,7 @@ describe('Hooks – Local Create', () => {
createStore([{ model: User }])
- await User.create({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.create({ id: 1, name: 'John Doe', age: 20 })
const expected = { $id: '1', id: 1, name: 'John Doe', age: 20 }
@@ -106,12 +102,10 @@ describe('Hooks – Local Create', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1, name: 'John Doe', age: 20 },
- { id: 2, name: 'Jane Doe', age: 24 }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe', age: 20 },
+ { id: 2, name: 'Jane Doe', age: 24 }
+ ])
const users = User.all()
@@ -148,8 +142,6 @@ describe('Hooks – Local Create', () => {
createStore([{ model: User }])
- await User.create({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.create({ id: 1, name: 'John Doe', age: 20 })
})
})
diff --git a/test/feature/hooks/Local_Delete.spec.ts b/test/feature/hooks/Local_Delete.spec.ts
index c5f463c0..b20a143c 100644
--- a/test/feature/hooks/Local_Delete.spec.ts
+++ b/test/feature/hooks/Local_Delete.spec.ts
@@ -28,9 +28,7 @@ describe('Hooks – Local Delete', () => {
createStore([{ model: User }])
- await User.create({
- data: { id: 1, name: 'John Doe' }
- })
+ await User.create({ id: 1, name: 'John Doe' })
await User.delete(1)
@@ -65,12 +63,10 @@ describe('Hooks – Local Delete', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
await User.delete(2)
@@ -109,12 +105,10 @@ describe('Hooks – Local Delete', () => {
createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
await User.delete(2)
diff --git a/test/feature/hooks/Local_Insert.spec.ts b/test/feature/hooks/Local_Insert.spec.ts
index 4467729b..895e7de7 100644
--- a/test/feature/hooks/Local_Insert.spec.ts
+++ b/test/feature/hooks/Local_Insert.spec.ts
@@ -30,9 +30,7 @@ describe('Hooks – Local Insert', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
const expected = { $id: '1', id: 1, name: 'John Doe', age: 30 }
@@ -67,9 +65,7 @@ describe('Hooks – Local Insert', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
const expected = { $id: '1', id: 1, name: 'John Doe', age: 20 }
@@ -148,8 +144,6 @@ describe('Hooks – Local Insert', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
})
})
diff --git a/test/feature/hooks/Local_Update.spec.ts b/test/feature/hooks/Local_Update.spec.ts
index 0c62e228..130bbde0 100644
--- a/test/feature/hooks/Local_Update.spec.ts
+++ b/test/feature/hooks/Local_Update.spec.ts
@@ -30,9 +30,7 @@ describe('Hooks – Local Update', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
await User.update({ id: 1, name: 'Jane Doe' })
@@ -69,9 +67,7 @@ describe('Hooks – Local Update', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
await User.update({ id: 1, name: 'Jane Doe', age: 30 })
@@ -108,12 +104,10 @@ describe('Hooks – Local Update', () => {
createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe', age: 20 },
- { id: 2, name: 'Jane Doe', age: 24 }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe', age: 20 },
+ { id: 2, name: 'Jane Doe', age: 24 }
+ ])
await User.update({ id: 1, name: 'Johnny Doe' })
@@ -158,9 +152,7 @@ describe('Hooks – Local Update', () => {
createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe', age: 20 }
- })
+ await User.insert({ id: 1, name: 'John Doe', age: 20 })
await User.update({ id: 1, age: 30 })
diff --git a/test/feature/inheritance/Inheritance.spec.ts b/test/feature/inheritance/Inheritance.spec.ts
index 483a936c..bb5bafee 100644
--- a/test/feature/inheritance/Inheritance.spec.ts
+++ b/test/feature/inheritance/Inheritance.spec.ts
@@ -63,9 +63,7 @@ describe('Feature – Inheritance', () => {
it('sets right class for derived entity', async () => {
createStore([Person, Adult])
- await Adult.insert({
- data: { id: 1, name: 'John Doe' }
- })
+ await Adult.insert({ id: 1, name: 'John Doe' })
expect(Adult.find(1)).toBeInstanceOf(Adult)
})
@@ -73,9 +71,7 @@ describe('Feature – Inheritance', () => {
it('should inherit fields from root entity', async () => {
createStore([Person, Adult])
- await Adult.insert({
- data: { id: 2, name: 'John Doe' }
- })
+ await Adult.insert({ id: 2, name: 'John Doe' })
const adult = Adult.find(2) as Adult
@@ -86,13 +82,9 @@ describe('Feature – Inheritance', () => {
it('should have own fields only on derived entity', async () => {
createStore([Person, Adult])
- await Person.insert({
- data: { id: 1, name: 'John' }
- })
+ await Person.insert({ id: 1, name: 'John' })
- await Adult.insert({
- data: { id: 2, name: 'Jane', job: 'Software Engineer' }
- })
+ await Adult.insert({ id: 2, name: 'Jane', job: 'Software Engineer' })
const person = Person.find(1) as any
expect(person.job).toBe(undefined)
diff --git a/test/feature/inheritance/Inheritance_CRUD.spec.ts b/test/feature/inheritance/Inheritance_CRUD.spec.ts
index 9eb8d653..80898f5a 100644
--- a/test/feature/inheritance/Inheritance_CRUD.spec.ts
+++ b/test/feature/inheritance/Inheritance_CRUD.spec.ts
@@ -56,13 +56,9 @@ describe('Feature - Inheritance - CRUD', () => {
it('can get mixed results when calling getter of root entity', async () => {
createStore([Person, Adult])
- await Person.insert({
- data: { id: 1, name: 'John' }
- })
+ await Person.insert({ id: 1, name: 'John' })
- await Adult.insert({
- data: { id: 2, name: 'Jane', job: 'Software Engineer' }
- })
+ await Adult.insert({ id: 2, name: 'Jane', job: 'Software Engineer' })
const people = Person.query().orderBy('id').get()
@@ -79,13 +75,9 @@ describe('Feature - Inheritance - CRUD', () => {
it('can get only derived results when calling getter of derived entity', async () => {
createStore([Person, Adult])
- await Person.insert({
- data: { id: 1, name: 'John' }
- })
+ await Person.insert({ id: 1, name: 'John' })
- await Adult.insert({
- data: { id: 2, name: 'Jane', job: 'Software Engineer' }
- })
+ await Adult.insert({ id: 2, name: 'Jane', job: 'Software Engineer' })
const adults = Adult.all()
@@ -98,19 +90,15 @@ describe('Feature - Inheritance - CRUD', () => {
it('should clean only corresponding entities (and derived ones) when calling create', async () => {
createStore([Person, Adult, Child ])
- await Person.insert({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', type: 'ADULT' },
- { id: 3, name: 'D', type: 'CHILD' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', type: 'ADULT' },
+ { id: 3, name: 'D', type: 'CHILD' }
+ ])
expect(Person.all().length).toBe(3)
- await Adult.create({
- data: { id: 4, name: 'E' }
- })
+ await Adult.create({ id: 4, name: 'E' })
expect(Person.all().length).toBe(3)
@@ -123,19 +111,14 @@ describe('Feature - Inheritance - CRUD', () => {
it('should update derived data without changing its class when calling base update', async () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', type: 'ADULT' }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', type: 'ADULT' }
+ ])
expect((Person.find(2) as Adult).name).toBe('B')
- await Person.update({
- where: 2,
- data: { name: 'C' }
- })
+ await Person.update({ name: 'C' }, { where: 2 })
const adult = Person.find(2) as Adult
@@ -146,17 +129,15 @@ describe('Feature - Inheritance - CRUD', () => {
it('should update data with a closure using instanceof', async () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', type: 'ADULT' }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', type: 'ADULT' }
+ ])
- await Person.update({
- where: (record) => record instanceof Adult,
- data: { name: 'C' }
- })
+ await Person.update(
+ { name: 'C' },
+ { where: (record) => record instanceof Adult }
+ )
const adult = Person.find(2) as Adult
@@ -167,17 +148,13 @@ describe('Feature - Inheritance - CRUD', () => {
it('should update or insert mixed data', async () => {
const store = createStore([Person, Adult])
- await Person.create({
- data: { id: 1, name: 'John Doe', job: 'Software Engineer', type: 'ADULT' }
- })
+ await Person.create({ id: 1, name: 'John Doe', job: 'Software Engineer', type: 'ADULT' })
- await Person.insertOrUpdate({
- data: [
- { id: 1, name: 'John Doe', job: 'Writer', type: 'ADULT' },
- { id: 2, name: 'Jane Doe', job: 'QA', type: 'ADULT' },
- { id: 3, name: 'Jane Doe', type: 'PERSON' }
- ]
- })
+ await Person.insertOrUpdate([
+ { id: 1, name: 'John Doe', job: 'Writer', type: 'ADULT' },
+ { id: 2, name: 'Jane Doe', job: 'QA', type: 'ADULT' },
+ { id: 3, name: 'Jane Doe', type: 'PERSON' }
+ ])
const expected = createState({
person: {
@@ -194,17 +171,15 @@ describe('Feature - Inheritance - CRUD', () => {
it('should update only derived data when field is a derived entity field', async () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', job: 'Software Engineer', type: 'ADULT' }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', job: 'Software Engineer', type: 'ADULT' }
+ ])
- await Person.update({
- where: (record) => record instanceof Person,
- data: { job: 'Writer' }
- })
+ await Person.update(
+ { job: 'Writer' },
+ { where: (record) => record instanceof Person }
+ )
const person = Person.find(1) as any
expect(person.job).toBe(undefined)
@@ -216,12 +191,10 @@ describe('Feature - Inheritance - CRUD', () => {
it('should delete record correctly when manipulating a derived entity', async () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', type: 'ADULT' }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', type: 'ADULT' }
+ ])
expect(Person.all().length).toBe(2)
@@ -236,12 +209,10 @@ describe('Feature - Inheritance - CRUD', () => {
it('should delete only derived records when calling deleteAll on derived entity', async () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'A', type: 'PERSON' },
- { id: 2, name: 'B', type: 'ADULT' }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'A', type: 'PERSON' },
+ { id: 2, name: 'B', type: 'ADULT' }
+ ])
expect(Person.all().length).toBe(2)
diff --git a/test/feature/inheritance/Inheritance_Discriminator.spec.ts b/test/feature/inheritance/Inheritance_Discriminator.spec.ts
index 80cff44f..d23f931e 100644
--- a/test/feature/inheritance/Inheritance_Discriminator.spec.ts
+++ b/test/feature/inheritance/Inheritance_Discriminator.spec.ts
@@ -28,9 +28,7 @@ describe('Feature - Inheritance - Discriminator field', () => {
createStore([Person, Adult])
- await Person.insert({
- data: { id: 1, name: 'John Doe', type: 'ADULT' }
- })
+ await Person.insert({ id: 1, name: 'John Doe', type: 'ADULT' })
expect(Adult.find(1)).toBeInstanceOf(Adult)
})
@@ -64,9 +62,7 @@ describe('Feature - Inheritance - Discriminator field', () => {
createStore([Person, Adult])
- await Person.insert({
- data: { id: 1, name: 'John Doe', the_key: 'ADULT' }
- })
+ await Person.insert({ id: 1, name: 'John Doe', the_key: 'ADULT' })
expect(Adult.find(1)).toBeInstanceOf(Adult)
})
@@ -104,14 +100,12 @@ describe('Feature - Inheritance - Discriminator field', () => {
createStore([Person, Adult, Child ])
- await Person.insert({
- data: [
- { id: 1, name: 'John Doe', type: 'ADULT' },
- { id: 2, name: 'John Doe Jr', type: 'CHILD' },
- { id: 3, name: 'Doe', type: 'PERSON' },
- { id: 4, name: 'Jane Doe', type: 'ADULT' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John Doe', type: 'ADULT' },
+ { id: 2, name: 'John Doe Jr', type: 'CHILD' },
+ { id: 3, name: 'Doe', type: 'PERSON' },
+ { id: 4, name: 'Jane Doe', type: 'ADULT' }
+ ])
const adults = Adult.all()
expect(adults.length).toBe(2)
@@ -155,9 +149,7 @@ describe('Feature - Inheritance - Discriminator field', () => {
createStore([Person, Adult])
// Inserting through "adult" model.
- await Adult.create({
- data: { id: 1, name: 'John Doe' }
- })
+ await Adult.create({ id: 1, name: 'John Doe' })
const adult = Adult.find(1) as Adult
expect(adult.type).toBe('ADULT')
@@ -193,12 +185,10 @@ describe('Feature - Inheritance - Discriminator field', () => {
createStore([Person, Adult])
- await Person.create({
- data: [
- { id: 1, name: 'John Doe', type: 1 },
- { id: 2, name: 'Person Doe', type: 0 }
- ]
- })
+ await Person.create([
+ { id: 1, name: 'John Doe', type: 1 },
+ { id: 2, name: 'Person Doe', type: 0 }
+ ])
const person = Person.find(2) as Person
expect(person.name).toBe('Person Doe')
diff --git a/test/feature/inheritance/Inheritance_Relations.spec.ts b/test/feature/inheritance/Inheritance_Relations.spec.ts
index 9c6d23ed..ffb44154 100644
--- a/test/feature/inheritance/Inheritance_Relations.spec.ts
+++ b/test/feature/inheritance/Inheritance_Relations.spec.ts
@@ -54,16 +54,12 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Job])
- await Job.insert({
- data: { id: 1, title: 'Software Engineer', adult_id: 2 }
- })
+ await Job.insert({ id: 1, title: 'Software Engineer', adult_id: 2 })
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'PERSON' },
- { id: 2, name: 'Jane', type: 'ADULT' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'PERSON' },
+ { id: 2, name: 'Jane', type: 'ADULT' }
+ ])
const adult = Adult.query().with('jobs').all()
@@ -126,16 +122,12 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Job])
- await Job.insert({
- data: { id: 1, title: 'Software Engineer', adult_id: 2 }
- })
+ await Job.insert({ id: 1, title: 'Software Engineer', adult_id: 2 })
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'PERSON' },
- { id: 2, name: 'Jane', type: 'ADULT' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'PERSON' },
+ { id: 2, name: 'Jane', type: 'ADULT' }
+ ])
const job = Job.query().with('adult').all()
@@ -196,19 +188,15 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Role])
- await Role.insert({
- data: [
- { id: 1, roleName: 'Role 1' },
- { id: 2, roleName: 'Role 2' }
- ]
- })
+ await Role.insert([
+ { id: 1, roleName: 'Role 1' },
+ { id: 2, roleName: 'Role 2' }
+ ])
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'PERSON', role_id: 1 },
- { id: 2, name: 'Jane', type: 'ADULT', role_id: 1 }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'PERSON', role_id: 1 },
+ { id: 2, name: 'Jane', type: 'ADULT', role_id: 1 }
+ ])
const roles = Role.query().with('people').all()
expect(roles.length).toBe(2)
@@ -269,19 +257,15 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Role])
- await Role.insert({
- data: [
- { id: 1, roleName: 'Role 1' },
- { id: 2, roleName: 'Role 2' }
- ]
- })
+ await Role.insert([
+ { id: 1, roleName: 'Role 1' },
+ { id: 2, roleName: 'Role 2' }
+ ])
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'PERSON', role_id: 1 },
- { id: 2, name: 'Jane', type: 'ADULT', role_id: 2 }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'PERSON', role_id: 1 },
+ { id: 2, name: 'Jane', type: 'ADULT', role_id: 2 }
+ ])
// Reverse check: getting all people and their associated role.
const people = Person.query().with('role').all()
@@ -352,13 +336,11 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Child])
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'ADULT', child_id: 3 },
- { id: 2, name: 'Jane', type: 'ADULT', child_id: 3 },
- { id: 3, name: 'Jane', type: 'CHILD' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'ADULT', child_id: 3 },
+ { id: 2, name: 'Jane', type: 'ADULT', child_id: 3 },
+ { id: 3, name: 'Jane', type: 'CHILD' }
+ ])
const adults = Adult.query().with('child').all()
expect(adults.length).toBe(2)
@@ -421,16 +403,12 @@ describe('Feature - Inheritance - Relations', () => {
createStore([Person, Adult, Job])
- await Job.insert({
- data: { id: 1, title: 'Software Engineer', adult_id: 2 }
- })
+ await Job.insert({ id: 1, title: 'Software Engineer', adult_id: 2 })
- await Person.insert({
- data: [
- { id: 1, name: 'John', type: 'PERSON' },
- { id: 2, name: 'Jane', type: 'ADULT' }
- ]
- })
+ await Person.insert([
+ { id: 1, name: 'John', type: 'PERSON' },
+ { id: 2, name: 'Jane', type: 'ADULT' }
+ ])
const persons = Person.query().with(['jobs', 'dummy']).all()
expect(persons.length).toBe(2)
diff --git a/test/feature/models/All.spec.ts b/test/feature/models/All.spec.ts
index 7af71a3c..4868933b 100644
--- a/test/feature/models/All.spec.ts
+++ b/test/feature/models/All.spec.ts
@@ -16,12 +16,10 @@ describe('Feature – Models – All', () => {
it('can fetch all records via static method', async () => {
createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const users = User.all()
@@ -37,12 +35,10 @@ describe('Feature – Models – All', () => {
it('can fetch all records via instance method', async () => {
createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const user = new User()
diff --git a/test/feature/models/Create.spec.ts b/test/feature/models/Create.spec.ts
index 31153d28..69b9e32c 100644
--- a/test/feature/models/Create.spec.ts
+++ b/test/feature/models/Create.spec.ts
@@ -17,9 +17,7 @@ describe('Feature – Models – Create', () => {
it('can create a record via static method', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: { id: 1, name: 'John Doe' }
- })
+ await User.create({ id: 1, name: 'John Doe' })
const expected = createState({
users: {
@@ -30,15 +28,13 @@ describe('Feature – Models – Create', () => {
expect(store.state.entities).toEqual(expected)
})
- it('can create list of record via static method', async () => {
+ it('can create a list of record via static method', async () => {
const store = createStore([{ model: User }])
- await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const expected = createState({
users: {
@@ -53,12 +49,10 @@ describe('Feature – Models – Create', () => {
it('returns created records via static method', async () => {
createStore([{ model: User }])
- const data = await User.create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ const data = await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
expect(data.users.length).toBe(2)
expect(data.users[0]).toBeInstanceOf(User)
@@ -69,9 +63,7 @@ describe('Feature – Models – Create', () => {
const user = new User()
- await user.$create({
- data: { id: 1, name: 'John Doe' }
- })
+ await user.$create({ id: 1, name: 'John Doe' })
const expected = createState({
users: {
@@ -82,17 +74,15 @@ describe('Feature – Models – Create', () => {
expect(store.state.entities).toEqual(expected)
})
- it('can create list of record via instance method', async () => {
+ it('can create a list of record via instance method', async () => {
const store = createStore([{ model: User }])
const user = new User()
- await user.$create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await user.$create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const expected = createState({
users: {
@@ -109,12 +99,10 @@ describe('Feature – Models – Create', () => {
const user = new User()
- const data = await user.$create({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ const data = await user.$create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
expect(data.users.length).toBe(2)
expect(data.users[0]).toBeInstanceOf(User)
@@ -204,9 +192,7 @@ describe('Feature – Models – Create', () => {
expect(data).toEqual(dataBefore)
- await Author.create({
- data
- })
+ await Author.create(data)
const expected = createState({
authors: {
diff --git a/test/feature/models/Insert.spec.ts b/test/feature/models/Insert.spec.ts
index cd2993be..3a084139 100644
--- a/test/feature/models/Insert.spec.ts
+++ b/test/feature/models/Insert.spec.ts
@@ -17,13 +17,9 @@ describe('Feature – Models – Insert', () => {
it('can insert a record via static method', async () => {
const store = createStore([{ model: User }])
- await User.insert({
- data: { id: 1, name: 'John Doe' }
- })
+ await User.insert({ id: 1, name: 'John Doe' })
- await User.insert({
- data: { id: 2, name: 'Jane Doe' }
- })
+ await User.insert({ id: 2, name: 'Jane Doe' })
const expected = createState({
users: {
@@ -35,15 +31,13 @@ describe('Feature – Models – Insert', () => {
expect(store.state.entities).toEqual(expected)
})
- it('can insert list of record via static method', async () => {
+ it('can insert a list of records via static method', async () => {
const store = createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const expected = createState({
users: {
@@ -58,12 +52,10 @@ describe('Feature – Models – Insert', () => {
it('returns inserted records via static method', async () => {
createStore([{ model: User }])
- const data = await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ const data = await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
expect(data.users.length).toBe(2)
expect(data.users[0]).toBeInstanceOf(User)
@@ -74,13 +66,9 @@ describe('Feature – Models – Insert', () => {
const user = new User()
- await user.$insert({
- data: { id: 1, name: 'John Doe' }
- })
+ await user.$insert({ id: 1, name: 'John Doe' })
- await user.$insert({
- data: { id: 2, name: 'Jane Doe' }
- })
+ await user.$insert({ id: 2, name: 'Jane Doe' })
const expected = createState({
users: {
@@ -92,17 +80,15 @@ describe('Feature – Models – Insert', () => {
expect(store.state.entities).toEqual(expected)
})
- it('can insert list of record via instance method', async () => {
+ it('can insert a list of records via instance method', async () => {
const store = createStore([{ model: User }])
const user = new User()
- await user.$insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await user.$insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const expected = createState({
users: {
@@ -119,12 +105,10 @@ describe('Feature – Models – Insert', () => {
const user = new User()
- const data = await user.$insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ const data = await user.$insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
expect(data.users.length).toBe(2)
expect(data.users[0]).toBeInstanceOf(User)
@@ -214,9 +198,7 @@ describe('Feature – Models – Insert', () => {
expect(data).toEqual(dataBefore)
- await Author.insert({
- data
- })
+ await Author.insert(data)
const expected = createState({
authors: {
diff --git a/test/feature/models/InsertOrUpdate.spec.ts b/test/feature/models/InsertOrUpdate.spec.ts
index bc699369..0af6b498 100644
--- a/test/feature/models/InsertOrUpdate.spec.ts
+++ b/test/feature/models/InsertOrUpdate.spec.ts
@@ -17,18 +17,14 @@ describe('Feature – Models – Insert Or Update', () => {
it('can insert or update records via static method', async () => {
const store = createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' }
+ ])
- await User.insertOrUpdate({
- data: [
- { id: 1, name: 'Jane Doe' },
- { id: 2, name: 'Johnny Doe' }
- ]
- })
+ await User.insertOrUpdate([
+ { id: 1, name: 'Jane Doe' },
+ { id: 2, name: 'Johnny Doe' }
+ ])
const expected = createState({
users: {
@@ -45,18 +41,14 @@ describe('Feature – Models – Insert Or Update', () => {
const user = new User()
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' }
+ ])
- await user.$insertOrUpdate({
- data: [
- { id: 1, name: 'Jane Doe' },
- { id: 2, name: 'Johnny Doe' }
- ]
- })
+ await user.$insertOrUpdate([
+ { id: 1, name: 'Jane Doe' },
+ { id: 2, name: 'Johnny Doe' }
+ ])
const expected = createState({
users: {
diff --git a/test/feature/models/Query.spec.ts b/test/feature/models/Query.spec.ts
index 575dd3a5..a758d5f3 100644
--- a/test/feature/models/Query.spec.ts
+++ b/test/feature/models/Query.spec.ts
@@ -16,12 +16,10 @@ describe('Feature – Models – Query', () => {
it('can begin query chain via static method', async () => {
createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const users = User.query().get()
@@ -37,12 +35,10 @@ describe('Feature – Models – Query', () => {
it('can begin query chain via instance method', async () => {
createStore([{ model: User }])
- await User.insert({
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
const u = new User()
diff --git a/test/feature/models/Update.spec.ts b/test/feature/models/Update.spec.ts
index 123f83e5..bb6ebab0 100644
--- a/test/feature/models/Update.spec.ts
+++ b/test/feature/models/Update.spec.ts
@@ -178,13 +178,11 @@ describe('Feature – Models – Update', () => {
const store = createStore([{ model: Role }])
- await Role.insert({
- data: { key_1: 1, key_2: 2, name: 'John Doe' }
- })
+ await Role.insert({ key_1: 1, key_2: 2, name: 'John Doe' })
- const user = Role.find([1, 2])
+ const user = Role.find([1, 2]) as Role
- await user?.$update({ name: 'Jane Doe' })
+ await user.$update({ name: 'Jane Doe' })
const expected = createState({
roles: {
@@ -231,10 +229,7 @@ describe('Feature – Models – Update', () => {
data: { id: 1, name: 'John Doe' }
})
- await user.$update({
- where: 1,
- data: { name: 'Jane Doe' }
- })
+ await user.$update({ name: 'Jane Doe' }, { where: 1 })
const expected = createState({
users: {
diff --git a/test/feature/relations/BelongsToMany_Retrieve.spec.ts b/test/feature/relations/BelongsToMany_Retrieve.spec.ts
index 691c6ddb..bb6ddda9 100644
--- a/test/feature/relations/BelongsToMany_Retrieve.spec.ts
+++ b/test/feature/relations/BelongsToMany_Retrieve.spec.ts
@@ -66,20 +66,14 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('can resolve belongs to many relation', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: [{ id: 1 }, { id: 2 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }])
- await Role.create({
- data: [{ id: 2 }, { id: 3 }]
- })
+ await Role.create([{ id: 2 }, { id: 3 }])
- await RoleUser.create({
- data: [
- { user_id: 1, role_id: 2 },
- { user_id: 1, role_id: 3 }
- ]
- })
+ await RoleUser.create([
+ { user_id: 1, role_id: 2 },
+ { user_id: 1, role_id: 3 }
+ ])
const user = User.query().with('roles').find(1) as User
@@ -94,9 +88,16 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('can resolve belongs to many relation with pivot data', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: [{ id: 1, roles: [{ id: 2, pivot: { level: 1 } }, { id: 3, pivot: { level: 2 } }] }, { id: 2 }]
- })
+ await User.create([
+ {
+ id: 1,
+ roles: [
+ { id: 2, pivot: { level: 1 } },
+ { id: 3, pivot: { level: 2 } }
+ ]
+ },
+ { id: 2 }
+ ])
const user = User.query().with('roles').find(1) as User
@@ -113,20 +114,14 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('can resolve inverse belongs to many relation', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Role.create({
- data: [{ id: 2 }, { id: 3 }]
- })
+ await Role.create([{ id: 2 }, { id: 3 }])
- await RoleUser.create({
- data: [
- { user_id: 1, role_id: 2 },
- { user_id: 1, role_id: 3 }
- ]
- })
+ await RoleUser.create([
+ { user_id: 1, role_id: 2 },
+ { user_id: 1, role_id: 3 }
+ ])
const role = Role.query().with('users').find(2) as Role
@@ -137,9 +132,7 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('returns empty collection if the relation is not found', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
const user = User.query().with('roles').first() as User
@@ -149,13 +142,9 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('returns empty collection if the Role relation from RoleUser is not found', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await RoleUser.create({
- data: [{ user_id: 1 }]
- })
+ await RoleUser.create([{ user_id: 1 }])
const user = User.query().with('roles').first() as User
@@ -165,21 +154,15 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
it('can resolve belongs to many relation with has constraint', async () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Role.create({
- data: [{ id: 2 }, { id: 3 }]
- })
+ await Role.create([{ id: 2 }, { id: 3 }])
- await RoleUser.create({
- data: [
- { user_id: 1, role_id: 2 },
- { user_id: 1, role_id: 3 },
- { user_id: 2, role_id: 4 }
- ]
- })
+ await RoleUser.create([
+ { user_id: 1, role_id: 2 },
+ { user_id: 1, role_id: 3 },
+ { user_id: 2, role_id: 4 }
+ ])
const roles = Role.query().has('users').get()
@@ -313,7 +296,7 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
}
]
- await User.create({ data })
+ await User.create(data)
const users = User.query().with('roles.permissions').get() as User[]
@@ -390,17 +373,11 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
- await User.create({
- data: [{ id: 1 }]
- })
+ await User.create([{ id: 1 }])
- await Role.create({
- data: { id: 1 }
- })
+ await Role.create({ id: 1 })
- await RoleUser.create({
- data: { id: 1, user_id: 1, role_id: 1 }
- })
+ await RoleUser.create({ id: 1, user_id: 1, role_id: 1 })
const users = User.query().with('roles').get()
@@ -413,10 +390,8 @@ describe('Feature – Relations – Belongs To Many – Retrieve', () => {
createStore([{ model: User }, { model: Role }, { model: RoleUser }])
await User.create({
- data: {
- id: 1,
- roles: [{ id: 1 }, { id: 3 }, { id: 2 }]
- }
+ id: 1,
+ roles: [{ id: 1 }, { id: 3 }, { id: 2 }]
})
const ascending = User.query()
diff --git a/test/feature/relations/HasMany.spec.ts b/test/feature/relations/HasMany.spec.ts
index c01f15b2..4d33851f 100644
--- a/test/feature/relations/HasMany.spec.ts
+++ b/test/feature/relations/HasMany.spec.ts
@@ -1,4 +1,4 @@
-import { createStore, createState } from 'test/support/Helpers'
+import { createStore } from 'test/support/Helpers'
import Model from '@/model/Model'
describe('Features – Relations – Has Many', () => {
@@ -25,80 +25,78 @@ describe('Features – Relations – Has Many', () => {
}
it('can create data containing the has many relation', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
+ await User.create({
+ id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
})
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, posts: [] }
- },
- posts: {
- 1: { $id: '1', id: 1, user_id: 1 },
- 2: { $id: '2', id: 2, user_id: 1 }
- }
- })
+ const expectedUsers = [
+ { $id: '1', id: 1, posts: [] }
+ ]
+
+ expect(User.all()).toEqual(expectedUsers)
+
+ const expectedPosts = [
+ { $id: '1', id: 1, user_id: 1 },
+ { $id: '2', id: 2, user_id: 1 }
+ ]
- expect(store.state.entities).toEqual(expected)
+ expect(Post.all()).toEqual(expectedPosts)
})
it('can update data and insert has many relation', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await store.dispatch('entities/users/update', {
- insert: ['posts'],
- data: {
+ await User.update(
+ {
id: 1,
posts: [
{ id: 1 },
{ id: 2 }
]
- }
- })
-
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, posts: [] }
},
- posts: {
- 1: { $id: '1', id: 1, user_id: 1 },
- 2: { $id: '2', id: 2, user_id: 1 }
+ {
+ insert: ['posts']
}
- })
+ )
- expect(store.state.entities).toEqual(expected)
+ const expectedUsers = [
+ { $id: '1', id: 1, posts: [] }
+ ]
+
+ expect(User.all()).toEqual(expectedUsers)
+
+ const expectedPosts = [
+ { $id: '1', id: 1, user_id: 1 },
+ { $id: '2', id: 2, user_id: 1 }
+ ]
+
+ expect(Post.all()).toEqual(expectedPosts)
})
it('can resolve the has many relation', async () => {
- const store = createStore([{ model: User }, { model: Post }])
-
- await store.dispatch('entities/users/create', {
- data: [
- {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- },
- {
- id: 2,
- posts: null
- }
- ]
- })
+ createStore([{ model: User }, { model: Post }])
+
+ await User.create([
+ {
+ id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
+ },
+ {
+ id: 2,
+ posts: null
+ }
+ ])
const expected = [
{
@@ -116,7 +114,7 @@ describe('Features – Relations – Has Many', () => {
}
]
- const user = store.getters['entities/users/query']().with('posts').all()
+ const user = User.query().with('posts').all()
expect(user).toEqual(expected)
})
@@ -135,16 +133,14 @@ describe('Features – Relations – Has Many', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: {
- user_id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
+ await User.create({
+ user_id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
})
const expected = {
@@ -156,7 +152,7 @@ describe('Features – Relations – Has Many', () => {
]
}
- const user = store.getters['entities/users/query']().with('posts').find(1)
+ const user = User.query().with('posts').find(1)
expect(user).toEqual(expected)
})
@@ -185,27 +181,24 @@ describe('Features – Relations – Has Many', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
await User.create({
- data: {
- id: 1,
- local_key: 'local_key',
- posts: [
- { id: 1 }
- ]
- }
+ id: 1,
+ local_key: 'local_key',
+ posts: [{ id: 1 }]
})
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, local_key: 'local_key', posts: [] }
- },
- posts: {
- 1: { $id: '1', id: 1, user_id: 'local_key' }
- }
- })
+ const expectedUsers = [
+ { $id: '1', id: 1, local_key: 'local_key', posts: [] }
+ ]
+
+ expect(User.all()).toEqual(expectedUsers)
+
+ const expectedPosts = [
+ { $id: '1', id: 1, user_id: 'local_key' }
+ ]
- expect(store.state.entities).toEqual(expected)
+ expect(Post.all()).toEqual(expectedPosts)
})
})
diff --git a/test/feature/relations/HasManyBy.spec.ts b/test/feature/relations/HasManyBy.spec.ts
index 99ab8620..c31c35b0 100644
--- a/test/feature/relations/HasManyBy.spec.ts
+++ b/test/feature/relations/HasManyBy.spec.ts
@@ -29,13 +29,11 @@ describe('Features – Relations – Has Many By', () => {
const store = createStore([{ model: User }, { model: Post }])
await User.insert({
- data: {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
+ id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
})
const expected = createState({
@@ -76,9 +74,7 @@ describe('Features – Relations – Has Many By', () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.insert({
- data: { id: 1, posts: [] }
- })
+ await User.insert({ id: 1, posts: [] })
const expected = createState({
users: {
@@ -115,9 +111,7 @@ describe('Features – Relations – Has Many By', () => {
const store = createStore([{ model: User }, { model: Post }])
- await User.insert({
- data: { id: 1, posts: null }
- })
+ await User.insert({ id: 1, posts: null })
const expected = createState({
users: {
@@ -155,13 +149,11 @@ describe('Features – Relations – Has Many By', () => {
createStore([{ model: User }, { model: Post }])
await User.insert({
- data: {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
+ id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
})
const user = User.query().with('posts').find(1)
@@ -204,12 +196,10 @@ describe('Features – Relations – Has Many By', () => {
createStore([{ model: User }, { model: Post }])
- await User.insert({
- data: [
- { id: 1, posts: [{ id: 1 }, { id: 2 }] },
- { id: 2, post_ids: [], posts: [] }
- ]
- })
+ await User.insert([
+ { id: 1, posts: [{ id: 1 }, { id: 2 }] },
+ { id: 2, post_ids: [], posts: [] }
+ ])
const users = User.query().with('posts').get()
@@ -271,9 +261,7 @@ describe('Features – Relations – Has Many By', () => {
createStore([{ model: User }, { model: Post }])
- await User.insert({
- data: { id: 1, posts: [{ id: 1 }, { id: 3 }, { id: 2 }] }
- })
+ await User.insert({ id: 1, posts: [{ id: 1 }, { id: 3 }, { id: 2 }] })
const ascending = User.query()
.with('posts', query => { query.orderBy('id', 'asc') })
diff --git a/test/feature/relations/HasManyThrough.spec.ts b/test/feature/relations/HasManyThrough.spec.ts
index 0042fec0..ca857129 100644
--- a/test/feature/relations/HasManyThrough.spec.ts
+++ b/test/feature/relations/HasManyThrough.spec.ts
@@ -58,13 +58,11 @@ describe('Features – Relations – Has Many Through', () => {
const store = createStore([{ model: Country }, { model: User }, { model: Post }])
await Country.insert({
- data: {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
+ id: 1,
+ posts: [
+ { id: 1 },
+ { id: 2 }
+ ]
})
const expected = createState({
@@ -135,29 +133,23 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
- await User.insert({
- data: [
- { id: 1, country_id: 1 },
- { id: 2, country_id: 1 },
- { id: 3, country_id: 2 }
- ]
- })
+ await User.insert([
+ { id: 1, country_id: 1 },
+ { id: 2, country_id: 1 },
+ { id: 3, country_id: 2 }
+ ])
- await Post.insert({
- data: [
- { id: 1, user_id: 1 },
- { id: 2, user_id: 2 },
- { id: 3, user_id: 3 },
- { id: 4, user_id: 1 }
- ]
- })
+ await Post.insert([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 3 },
+ { id: 4, user_id: 1 }
+ ])
- await Country.insert({
- data: [
- { id: 1 },
- { id: 2 }
- ]
- })
+ await Country.insert([
+ { id: 1 },
+ { id: 2 }
+ ])
const country = Country.query().with('posts').find(1) as Country
@@ -230,29 +222,23 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
- await User.insert({
- data: [
- { id: 'string-id-1', country_id: 'string-id-1' },
- { id: 'string-id-2', country_id: 'string-id-1' },
- { id: 'string-id-3', country_id: 'string-id-2' }
- ]
- })
+ await User.insert([
+ { id: 'string-id-1', country_id: 'string-id-1' },
+ { id: 'string-id-2', country_id: 'string-id-1' },
+ { id: 'string-id-3', country_id: 'string-id-2' }
+ ])
- await Post.insert({
- data: [
- { id: 'string-id-1', user_id: 'string-id-1' },
- { id: 'string-id-2', user_id: 'string-id-2' },
- { id: 'string-id-3', user_id: 'string-id-3' },
- { id: 'string-id-4', user_id: 'string-id-1' }
- ]
- })
+ await Post.insert([
+ { id: 'string-id-1', user_id: 'string-id-1' },
+ { id: 'string-id-2', user_id: 'string-id-2' },
+ { id: 'string-id-3', user_id: 'string-id-3' },
+ { id: 'string-id-4', user_id: 'string-id-1' }
+ ])
- await Country.insert({
- data: [
- { id: 'string-id-1' },
- { id: 'string-id-2' }
- ]
- })
+ await Country.insert([
+ { id: 'string-id-1' },
+ { id: 'string-id-2' }
+ ])
const country = Country.query().with('posts').find('string-id-1') as Country
@@ -322,9 +308,7 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
- await Country.insert({
- data: [{ id: 1 }]
- })
+ await Country.insert([{ id: 1 }])
const country = Country.query().with('posts').find(1) as Country
@@ -386,15 +370,11 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
await User.insert({
- data: {
- id: 1,
- country_id: 1
- }
+ id: 1,
+ country_id: 1
})
- await Country.insert({
- data: [{ id: 1 }]
- })
+ await Country.insert([{ id: 1 }])
const country = Country.query().with('posts').find(1) as Country
@@ -461,28 +441,22 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
- await User.insert({
- data: [
- { u_id: 1, country_id: 1 },
- { u_id: 2, country_id: 1 },
- { u_id: 3, country_id: 2 }
- ]
- })
+ await User.insert([
+ { u_id: 1, country_id: 1 },
+ { u_id: 2, country_id: 1 },
+ { u_id: 3, country_id: 2 }
+ ])
- await Post.insert({
- data: [
- { p_id: 1, user_id: 1 },
- { p_id: 2, user_id: 2 },
- { p_id: 3, user_id: 3 }
- ]
- })
+ await Post.insert([
+ { p_id: 1, user_id: 1 },
+ { p_id: 2, user_id: 2 },
+ { p_id: 3, user_id: 3 }
+ ])
- await Country.insert({
- data: [
- { c_id: 1 },
- { c_id: 2 }
- ]
- })
+ await Country.insert([
+ { c_id: 1 },
+ { c_id: 2 }
+ ])
const country = Country.query().with('posts').find(1) as Country
@@ -559,28 +533,22 @@ describe('Features – Relations – Has Many Through', () => {
createStore([{ model: Country }, { model: User }, { model: Post }])
- await User.insert({
- data: [
- { id: 11, u_id: 1, country_id: 1 },
- { id: 12, u_id: 2, country_id: 1 },
- { id: 13, u_id: 3, country_id: 2 }
- ]
- })
-
- await Post.insert({
- data: [
- { id: 11, p_id: 1, user_id: 1 },
- { id: 12, p_id: 2, user_id: 2 },
- { id: 13, p_id: 3, user_id: 3 }
- ]
- })
-
- await Country.insert({
- data: [
- { id: 11, c_id: 1 },
- { id: 12, c_id: 2 }
- ]
- })
+ await User.insert([
+ { id: 11, u_id: 1, country_id: 1 },
+ { id: 12, u_id: 2, country_id: 1 },
+ { id: 13, u_id: 3, country_id: 2 }
+ ])
+
+ await Post.insert([
+ { id: 11, p_id: 1, user_id: 1 },
+ { id: 12, p_id: 2, user_id: 2 },
+ { id: 13, p_id: 3, user_id: 3 }
+ ])
+
+ await Country.insert([
+ { id: 11, c_id: 1 },
+ { id: 12, c_id: 2 }
+ ])
const country = Country.query().with('posts').find(11) as Country
diff --git a/test/feature/relations/HasOne.spec.ts b/test/feature/relations/HasOne.spec.ts
index fec05151..c28e2c62 100644
--- a/test/feature/relations/HasOne.spec.ts
+++ b/test/feature/relations/HasOne.spec.ts
@@ -28,10 +28,8 @@ describe('Features – Relations – Has One', () => {
const store = createStore([{ model: User }, { model: Phone }])
await User.insert({
- data: {
- id: 1,
- phone: { id: 1, user_id: 1 }
- }
+ id: 1,
+ phone: { id: 1, user_id: 1 }
})
const expected = createState({
@@ -49,9 +47,7 @@ describe('Features – Relations – Has One', () => {
it('can create data when the has one relation is empty', async () => {
const store = createStore([{ model: User }, { model: Phone }])
- await User.insert({
- data: { $id: '1', id: 1 }
- })
+ await User.insert({ $id: '1', id: 1 })
const expected = createState({
users: {
@@ -67,10 +63,8 @@ describe('Features – Relations – Has One', () => {
const store = createStore([{ model: User }, { model: Phone }])
await User.insert({
- data: {
- id: 1,
- phone: null
- }
+ id: 1,
+ phone: null
})
const expected = createState({
@@ -86,9 +80,7 @@ describe('Features – Relations – Has One', () => {
it('can create data when the has one relation is set to primitive value', async () => {
const store = createStore([{ model: User }, { model: Phone }])
- await User.insert({
- data: { id: 1, phone: 1 }
- })
+ await User.insert({ id: 1, phone: 1 })
const expected = createState({
users: {
@@ -103,18 +95,16 @@ describe('Features – Relations – Has One', () => {
it('it can create data containing mixed fields value', async () => {
const store = createStore([{ model: User }, { model: Phone }])
- await User.insert({
- data: [
- {
- id: 1,
- phone: { id: 1, user_id: 1 }
- },
- {
- id: 2,
- phone: null
- }
- ]
- })
+ await User.insert([
+ {
+ id: 1,
+ phone: { id: 1, user_id: 1 }
+ },
+ {
+ id: 2,
+ phone: null
+ }
+ ])
const expected = createState({
users: {
@@ -145,10 +135,8 @@ describe('Features – Relations – Has One', () => {
const store = createStore([{ model: User }, { model: Phone }])
await User.insert({
- data: {
- id: 1,
- phone: { id: 1 }
- }
+ id: 1,
+ phone: { id: 1 }
})
const expected = createState({
@@ -167,10 +155,8 @@ describe('Features – Relations – Has One', () => {
createStore([{ model: User }, { model: Phone }])
await User.insert({
- data: {
- id: 1,
- phone: { id: 1 }
- }
+ id: 1,
+ phone: { id: 1 }
})
const expected = {
@@ -192,9 +178,7 @@ describe('Features – Relations – Has One', () => {
it('can resolve the empty has one relation', async () => {
const store = createStore([{ model: User }, { model: Phone }])
- await User.insert({
- data: { id: 1 }
- })
+ await User.insert({ id: 1 })
const expected = { $id: '1', id: 1, phone: null }
diff --git a/test/feature/relations/MorphMany_Persist.spec.ts b/test/feature/relations/MorphMany_Persist.spec.ts
index e5b0358c..5d5680b2 100644
--- a/test/feature/relations/MorphMany_Persist.spec.ts
+++ b/test/feature/relations/MorphMany_Persist.spec.ts
@@ -41,13 +41,11 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
await Post.create({
- data: {
- id: 1,
- comments: [
- { id: 2, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { id: 3, body: 'comment2', commentable_id: 1, commentable_type: 'posts' }
- ]
- }
+ id: 1,
+ comments: [
+ { id: 2, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { id: 3, body: 'comment2', commentable_id: 1, commentable_type: 'posts' }
+ ]
})
createState({
@@ -106,23 +104,21 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [
- {
- id: 1,
- comments: [
- { id: 2, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { id: 3, body: 'comment2', commentable_id: 1, commentable_type: 'posts' }
- ]
- },
- {
- id: 2,
- comments: [
- { id: 4, body: 'comment3', commentable_id: 2, commentable_type: 'posts' }
- ]
- }
- ]
- })
+ await Post.create([
+ {
+ id: 1,
+ comments: [
+ { id: 2, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { id: 3, body: 'comment2', commentable_id: 1, commentable_type: 'posts' }
+ ]
+ },
+ {
+ id: 2,
+ comments: [
+ { id: 4, body: 'comment3', commentable_id: 2, commentable_type: 'posts' }
+ ]
+ }
+ ])
expect(store.state.entities.posts.data['1'].id).toBe(1)
expect(store.state.entities.posts.data['2'].id).toBe(2)
@@ -173,13 +169,11 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
await Post.create({
- data: {
- id: 1,
- comments: [
- { id: 2, body: 'comment1' },
- { id: 3, body: 'comment2' }
- ]
- }
+ id: 1,
+ comments: [
+ { id: 2, body: 'comment1' },
+ { id: 3, body: 'comment2' }
+ ]
})
createState({
@@ -239,13 +233,11 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
await Post.create({
- data: {
- id: 1,
- comments: [
- { id: 2, body: 'comment1', commentable_id: 1 },
- { id: 3, body: 'comment2', commentable_id: 2 }
- ]
- }
+ id: 1,
+ comments: [
+ { id: 2, body: 'comment1', commentable_id: 1 },
+ { id: 3, body: 'comment2', commentable_id: 2 }
+ ]
})
expect(store.state.entities.posts.data['1'].id).toBe(1)
@@ -293,12 +285,10 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Comment.create({
- data: [
- { id: 2, body: 'comment1' },
- { id: 3, body: 'comment2' }
- ]
- })
+ await Comment.create([
+ { id: 2, body: 'comment1' },
+ { id: 3, body: 'comment2' }
+ ])
createState({
posts: {},
@@ -368,17 +358,15 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: User }, { model: Post }, { model: Video }, { model: Comment }])
await User.create({
- data: {
- id: 1,
- posts: [{
- id: 5,
- user_id: 1,
- comments: [
- { id: 2, body: 'comment1', commentable_id: 1 },
- { id: 3, body: 'comment2', commentable_id: 2 }
- ]
- }]
- }
+ id: 1,
+ posts: [{
+ id: 5,
+ user_id: 1,
+ comments: [
+ { id: 2, body: 'comment1', commentable_id: 1 },
+ { id: 3, body: 'comment2', commentable_id: 2 }
+ ]
+ }]
})
createState({
@@ -432,9 +420,7 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: { id: 1, comments: null }
- })
+ await Post.create({ id: 1, comments: null })
const expected = createState({
posts: {
@@ -484,14 +470,12 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
- id: 1,
- comments: [
- { id: 1, body: 'comment1', commentabe_id: 1, commentable_type: 'posts' },
- { id: 2, body: 'comment2', commentabe_id: 1, commentable_type: 'posts' }
- ]
- }
+ await Post.create({
+ id: 1,
+ comments: [
+ { id: 1, body: 'comment1', commentabe_id: 1, commentable_type: 'posts' },
+ { id: 2, body: 'comment2', commentabe_id: 1, commentable_type: 'posts' }
+ ]
})
const post = store.getters['entities/posts/query']().with('comments').find(1)
@@ -502,7 +486,7 @@ describe('Feature – Relations – Morph Many – Persist', () => {
expect(post.comments[1]).toBeInstanceOf(Comment)
})
- it('generates id or type for the moprh relation', async () => {
+ it('generates id or type for the morph relation', async () => {
class Post extends Model {
static entity = 'posts'
@@ -540,14 +524,12 @@ describe('Feature – Relations – Morph Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
- id: 1,
- comments: [
- { id: 1, body: 'comment1' },
- { id: 2, body: 'comment2' }
- ]
- }
+ await Post.create({
+ id: 1,
+ comments: [
+ { id: 1, body: 'comment1' },
+ { id: 2, body: 'comment2' }
+ ]
})
const post = store.getters['entities/posts/query']().with('comments').find(1)
diff --git a/test/feature/relations/MorphMany_Retrieve.spec.ts b/test/feature/relations/MorphMany_Retrieve.spec.ts
index 021c9f97..5cf58eb7 100644
--- a/test/feature/relations/MorphMany_Retrieve.spec.ts
+++ b/test/feature/relations/MorphMany_Retrieve.spec.ts
@@ -65,22 +65,16 @@ describe('Feature – Relations – Morph Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ id: 1 }, { id: 5 }, { id: 6 }]
- })
-
- await Video.create({
- data: { id: 3 }
- })
-
- await Comment.create({
- data: [
- { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
- { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Post.create([{ id: 1 }, { id: 5 }, { id: 6 }])
+
+ await Video.create({ id: 3 })
+
+ await Comment.create([
+ { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
+ { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comments').find(1) as Post
@@ -157,22 +151,16 @@ describe('Feature – Relations – Morph Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ post_id: 1 }, { post_id: 5 }]
- })
+ await Post.create([{ post_id: 1 }, { post_id: 5 }])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Comment.create({
- data: [
- { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
- { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Comment.create([
+ { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
+ { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comments').find(1) as Post
@@ -247,22 +235,16 @@ describe('Feature – Relations – Morph Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ id: 2, post_id: 1 }, { id: 3, post_id: 5 }]
- })
+ await Post.create([{ id: 2, post_id: 1 }, { id: 3, post_id: 5 }])
- await Video.create({
- data: [{ id: 3 }, { id: 4 }]
- })
+ await Video.create([{ id: 3 }, { id: 4 }])
- await Comment.create({
- data: [
- { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
- { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Comment.create([
+ { id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { id: '3', body: 'comment3', commentable_id: 1, commentable_type: 'posts' },
+ { id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comments').find(2) as Post
@@ -333,13 +315,9 @@ describe('Feature – Relations – Morph Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.insert({
- data: { id: 1, comments: [{ id: 1 }, { id: 3 }, { id: 2 }] }
- })
+ await Post.insert({ id: 1, comments: [{ id: 1 }, { id: 3 }, { id: 2 }] })
- await Video.insert({
- data: { id: 1, comments: [{ id: 4 }, { id: 6 }, { id: 5 }] }
- })
+ await Video.insert({ id: 1, comments: [{ id: 4 }, { id: 6 }, { id: 5 }] })
const post = Post.query().with('comments', query => { query.orderBy('id', 'asc') }).find(1) as Post
diff --git a/test/feature/relations/MorphOne_Persist.spec.ts b/test/feature/relations/MorphOne_Persist.spec.ts
index 9aa13dab..a8848a47 100644
--- a/test/feature/relations/MorphOne_Persist.spec.ts
+++ b/test/feature/relations/MorphOne_Persist.spec.ts
@@ -30,15 +30,13 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
+ await Post.create({
+ id: 1,
+ comment: {
id: 1,
- comment: {
- id: 1,
- body: 'The Body',
- commentable_type: 'posts',
- commentable_id: 1
- }
+ body: 'The Body',
+ commentable_type: 'posts',
+ commentable_id: 1
}
})
@@ -93,10 +91,8 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
await Post.create({
- data: {
- id: 1,
- comment: { id: 2, body: 'comment1' }
- }
+ id: 1,
+ comment: { id: 2, body: 'comment1' }
})
expect(store.state.entities.posts.data['1'].id).toBe(1)
@@ -144,10 +140,8 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
await Post.create({
- data: {
- id: 1,
- comment: { id: 2, body: 'comment1', commentable_id: 1 }
- }
+ id: 1,
+ comment: { id: 2, body: 'comment1', commentable_id: 1 }
})
createState({
@@ -204,12 +198,10 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Comment.create({
- data: [
- { id: 2, body: 'comment1' },
- { id: 3, body: 'comment2' }
- ]
- })
+ await Comment.create([
+ { id: 2, body: 'comment1' },
+ { id: 3, body: 'comment2' }
+ ])
expect(store.state.entities.comments.data['2'].id).toBe(2)
expect(store.state.entities.comments.data['2'].commentable_id).toBe(null)
@@ -270,14 +262,12 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: User }, { model: Post }, { model: Video }, { model: Comment }])
await User.create({
- data: {
- id: 1,
- posts: [{
- id: 5,
- user_id: 1,
- comment: { id: 2, body: 'comment1', commentable_id: 1 }
- }]
- }
+ id: 1,
+ posts: [{
+ id: 5,
+ user_id: 1,
+ comment: { id: 2, body: 'comment1', commentable_id: 1 }
+ }]
})
createState({
@@ -328,23 +318,21 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: [
- {
+ await Post.create([
+ {
+ id: 1,
+ comment: {
id: 1,
- comment: {
- id: 1,
- body: 'The Body',
- commentable_type: 'posts',
- commentable_id: 1
- }
- },
- {
- id: 2,
- comment: null
+ body: 'The Body',
+ commentable_type: 'posts',
+ commentable_id: 1
}
- ]
- })
+ },
+ {
+ id: 2,
+ comment: null
+ }
+ ])
const expected = createState({
posts: {
@@ -397,11 +385,9 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
- id: 1,
- comment: { id: 1, body: 'comment1', commentabe_id: 1, commentable_type: 'posts' }
- }
+ await Post.create({
+ id: 1,
+ comment: { id: 1, body: 'comment1', commentabe_id: 1, commentable_type: 'posts' }
})
const post = store.getters['entities/posts/query']().with('comment').find(1)
@@ -410,7 +396,7 @@ describe('Features – Relations – Morph One – Persist', () => {
expect(post.comment).toBeInstanceOf(Comment)
})
- it('generates id or type for the moprh relation', async () => {
+ it('generates id or type for the morph relation', async () => {
class Post extends Model {
static entity = 'posts'
@@ -448,11 +434,9 @@ describe('Features – Relations – Morph One – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
- id: 1,
- comment: { id: 1, body: 'comment1' }
- }
+ await Post.create({
+ id: 1,
+ comment: { id: 1, body: 'comment1' }
})
const post = store.getters['entities/posts/query']().with('comment').find(1)
diff --git a/test/feature/relations/MorphOne_Retrieve.spec.ts b/test/feature/relations/MorphOne_Retrieve.spec.ts
index c447f5d6..72718775 100644
--- a/test/feature/relations/MorphOne_Retrieve.spec.ts
+++ b/test/feature/relations/MorphOne_Retrieve.spec.ts
@@ -65,22 +65,16 @@ describe('Feature – Relations – Morph One – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ id: 1 }, { id: 5 }]
- })
-
- await Video.create({
- data: { id: 3 }
- })
-
- await Comment.create({
- data: [
- { $id: '1', id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { $id: '2', id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { $id: '3', id: '3', body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
- { $id: '4', id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Post.create([{ id: 1 }, { id: 5 }])
+
+ await Video.create({ id: 3 })
+
+ await Comment.create([
+ { $id: '1', id: 1, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { $id: '2', id: 2, body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { $id: '3', id: 3, body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
+ { $id: '4', id: 4, body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comment').find(1) as Post
@@ -149,13 +143,9 @@ describe('Feature – Relations – Morph One – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ id: 1 }, { id: 5 }]
- })
+ await Post.create([{ id: 1 }, { id: 5 }])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
const post = Post.query().with('comments').find(1) as Post
@@ -226,22 +216,16 @@ describe('Feature – Relations – Morph One – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ post_id: 1 }, { post_id: 5 }]
- })
+ await Post.create([{ post_id: 1 }, { post_id: 5 }])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Comment.create({
- data: [
- { $id: '1', id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { $id: '2', id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { $id: '3', id: '3', body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
- { $id: '4', id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Comment.create([
+ { $id: '1', id: 1, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { $id: '2', id: 2, body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { $id: '3', id: 3, body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
+ { $id: '4', id: 4, body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comment').find(1) as Post
@@ -314,22 +298,16 @@ describe('Feature – Relations – Morph One – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await Post.create({
- data: [{ id: 2, post_id: 1 }, { id: 3, post_id: 5 }]
- })
-
- await Video.create({
- data: { id: 3 }
- })
-
- await Comment.create({
- data: [
- { $id: '1', id: '1', body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
- { $id: '2', id: '2', body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
- { $id: '3', id: '3', body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
- { $id: '4', id: '4', body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
- ]
- })
+ await Post.create([{ id: 2, post_id: 1 }, { id: 3, post_id: 5 }])
+
+ await Video.create({ id: 3 })
+
+ await Comment.create([
+ { $id: '1', id: 1, body: 'comment1', commentable_id: 1, commentable_type: 'posts' },
+ { $id: '2', id: 2, body: 'comment2', commentable_id: 3, commentable_type: 'videos' },
+ { $id: '3', id: 3, body: 'comment3', commentable_id: 2, commentable_type: 'posts' },
+ { $id: '4', id: 4, body: 'comment4', commentable_id: 5, commentable_type: 'posts' }
+ ])
const post = Post.query().with('comment').find(2) as Post
diff --git a/test/feature/relations/MorphTo.spec.ts b/test/feature/relations/MorphTo.spec.ts
index acfca4a1..5f610421 100644
--- a/test/feature/relations/MorphTo.spec.ts
+++ b/test/feature/relations/MorphTo.spec.ts
@@ -1,3 +1,4 @@
+/* tslint:disable:variable-name */
import { createStore, createState } from 'test/support/Helpers'
import Model from '@/model/Model'
@@ -6,6 +7,12 @@ describe('Features – Relations – Morph To', () => {
class Post extends Model {
static entity = 'posts'
+ // @Attribute
+ id!: number
+
+ // @MorphOne(Comment, 'commentable_id', 'commentable_type')
+ comment!: Comment
+
static fields () {
return {
id: this.attr(null),
@@ -17,6 +24,21 @@ describe('Features – Relations – Morph To', () => {
class Comment extends Model {
static entity = 'comments'
+ // @Attribute
+ id!: number
+
+ // @Attribute('')
+ body!: string
+
+ // @Attribute
+ commentable_id!: number
+
+ // @Attribute
+ commentable_type!: string
+
+ // @MorphTo('commentable_id', 'commentable_type')
+ commentable!: Post
+
static fields () {
return {
id: this.attr(null),
@@ -30,14 +52,12 @@ describe('Features – Relations – Morph To', () => {
const store = createStore([{ model: Post }, { model: Comment }])
- await store.dispatch('entities/comments/create', {
- data: {
- id: 1,
- body: 'The Body',
- commentable_type: 'posts',
- commentable_id: 1,
- commentable: { id: 1 }
- }
+ await Comment.create({
+ id: 1,
+ body: 'The Body',
+ commentable_type: 'posts',
+ commentable_id: 1,
+ commentable: { id: 1 }
})
const expected = createState({
@@ -63,6 +83,12 @@ describe('Features – Relations – Morph To', () => {
class Post extends Model {
static entity = 'posts'
+ // @Attribute
+ id!: number
+
+ // @MorphMany(Comment, 'commentable_id', 'commentable_type')
+ comments!: Comment[]
+
static fields () {
return {
id: this.attr(null),
@@ -74,6 +100,12 @@ describe('Features – Relations – Morph To', () => {
class Video extends Model {
static entity = 'videos'
+ // @Attribute
+ id!: number
+
+ // @MorphMany(Comment, 'commentable_id', 'commentable_type')
+ comments!: Comment[]
+
static fields () {
return {
id: this.attr(null),
@@ -85,6 +117,21 @@ describe('Features – Relations – Morph To', () => {
class Comment extends Model {
static entity = 'comments'
+ // @Attribute
+ id!: number
+
+ // @Attribute('')
+ body!: string
+
+ // @Attribute
+ commentable_id!: number
+
+ // @Attribute
+ commentable_type!: string
+
+ // @MorphTo('commentable_id', 'commentable_type')
+ commentable!: Post | Video
+
static fields () {
return {
id: this.attr(null),
@@ -96,33 +143,31 @@ describe('Features – Relations – Morph To', () => {
}
}
- const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
+ createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/posts/insert', {
- data: {
- id: 1,
- comments: [
- { id: 1, body: 'comment1' },
- { id: 2, body: 'comment2' }
- ]
- }
+ await Post.insert({
+ id: 1,
+ comments: [
+ { id: 1, body: 'comment1' },
+ { id: 2, body: 'comment2' }
+ ]
})
- await store.dispatch('entities/videos/insert', {
- data: {
- id: 1,
- comments: [
- { id: 3, body: 'comment3' },
- { id: 4, body: 'comment4' }
- ]
- }
+ await Video.insert({
+ id: 1,
+ comments: [
+ { id: 3, body: 'comment3' },
+ { id: 4, body: 'comment4' }
+ ]
})
- const comments = store.getters['entities/comments/query']().with('commentable').get()
+ const comments = Comment.query().with('commentable').get()
expect(comments.length).toBe(4)
+
expect(comments[0]).toBeInstanceOf(Comment)
expect(comments[0].commentable).toBeInstanceOf(Post)
+
expect(comments[2]).toBeInstanceOf(Comment)
expect(comments[2].commentable).toBeInstanceOf(Video)
})
@@ -131,6 +176,12 @@ describe('Features – Relations – Morph To', () => {
class Post extends Model {
static entity = 'posts'
+ // @Attribute
+ id!: number
+
+ // @MorphMany(Comment, 'commentable_id', 'commentable_type')
+ comments!: Comment[]
+
static fields () {
return {
id: this.attr(null),
@@ -142,6 +193,12 @@ describe('Features – Relations – Morph To', () => {
class Video extends Model {
static entity = 'videos'
+ // @Attribute
+ id!: number
+
+ // @MorphMany(Comment, 'commentable_id', 'commentable_type')
+ comments!: Comment[]
+
static fields () {
return {
id: this.attr(null),
@@ -153,6 +210,21 @@ describe('Features – Relations – Morph To', () => {
class Comment extends Model {
static entity = 'comments'
+ // @Attribute
+ id!: number
+
+ // @Attribute('')
+ body!: string
+
+ // @Attribute
+ commentable_id!: number
+
+ // @Attribute
+ commentable_type!: string
+
+ // @MorphTo('commentable_id', 'commentable_type')
+ commentable!: Post | Video
+
static fields () {
return {
id: this.attr(null),
@@ -164,16 +236,14 @@ describe('Features – Relations – Morph To', () => {
}
}
- const store = createStore([{ model: Post }, { model: Video }, { model: Comment }])
+ createStore([{ model: Post }, { model: Video }, { model: Comment }])
- await store.dispatch('entities/comments/insert', {
- data: {
- id: 1,
- body: 'Body 01'
- }
+ await Comment.insert({
+ id: 1,
+ body: 'Body 01'
})
- const comment = store.getters['entities/comments/query']().with('commentable').find(1)
+ const comment = Comment.query().with('commentable').find(1) as Comment
expect(comment.commentable).toBe(null)
})
diff --git a/test/feature/relations/MorphToMany_Persist.spec.ts b/test/feature/relations/MorphToMany_Persist.spec.ts
index e6bcc6c8..26238d4d 100644
--- a/test/feature/relations/MorphToMany_Persist.spec.ts
+++ b/test/feature/relations/MorphToMany_Persist.spec.ts
@@ -1,3 +1,4 @@
+/* tslint:disable:variable-name */
import { createStore, createState } from 'test/support/Helpers'
import Model from '@/model/Model'
@@ -52,13 +53,11 @@ describe('Features – Relations – Morph To Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Post.create({
- data: {
- id: 1,
- tags: [
- { id: 2, name: 'news', pivot: { public: true } },
- { id: 3, name: 'cast' }
- ]
- }
+ id: 1,
+ tags: [
+ { id: 2, name: 'news', pivot: { public: true } },
+ { id: 3, name: 'cast' }
+ ]
})
expect(store.state.entities.posts.data['1'].id).toBe(1)
@@ -121,9 +120,7 @@ describe('Features – Relations – Morph To Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await store.dispatch('entities/posts/create', {
- data: { id: 1 }
- })
+ await Post.create({ id: 1 })
const expected = {
1: { $id: '1', id: 1, tags: [] }
@@ -181,13 +178,11 @@ describe('Features – Relations – Morph To Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Post.create({
- data: {
- id: 1,
- tags: [
- { id: 2, name: 'news' },
- { id: 3, name: 'cast' }
- ]
- }
+ id: 1,
+ tags: [
+ { id: 2, name: 'news' },
+ { id: 3, name: 'cast' }
+ ]
})
const expected = createState({
@@ -259,13 +254,11 @@ describe('Features – Relations – Morph To Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Post.create({
- data: {
- title: 'Post title.',
- tags: [
- { id: 2, name: 'news' },
- { id: 3, name: 'cast' }
- ]
- }
+ title: 'Post title.',
+ tags: [
+ { id: 2, name: 'news' },
+ { id: 3, name: 'cast' }
+ ]
})
const expected = createState({
@@ -336,13 +329,11 @@ describe('Features – Relations – Morph To Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Post.create({
- data: {
- id: 1,
- tags: [
- { id: 2, name: 'news', tag_pivot: { public: true } },
- { id: 3, name: 'cast' }
- ]
- }
+ id: 1,
+ tags: [
+ { id: 2, name: 'news', tag_pivot: { public: true } },
+ { id: 3, name: 'cast' }
+ ]
})
expect(store.state.entities.taggables.data['1_2_posts'].public).toBe(true)
@@ -353,6 +344,12 @@ describe('Features – Relations – Morph To Many – Persist', () => {
class Post extends Model {
static entity = 'posts'
+ // @Attribute
+ id!: number
+
+ // @MorphToMany(Tag, Taggable, 'tag_id', 'taggable_id', 'taggable_type')
+ tags!: Tag[]
+
static fields () {
return {
id: this.attr(null),
@@ -364,6 +361,12 @@ describe('Features – Relations – Morph To Many – Persist', () => {
class Video extends Model {
static entity = 'videos'
+ // @Attribute
+ id!: number
+
+ // @MorphToMany(Tag, Taggable, 'tag_id', 'taggable_id', 'taggable_type')
+ tags!: Tag[]
+
static fields () {
return {
id: this.attr(null),
@@ -375,6 +378,12 @@ describe('Features – Relations – Morph To Many – Persist', () => {
class Tag extends Model {
static entity = 'tag'
+ // @Attribute
+ id!: number
+
+ // @Attribute('')
+ name!: string
+
static fields () {
return {
id: this.attr(null),
@@ -386,6 +395,18 @@ describe('Features – Relations – Morph To Many – Persist', () => {
class Taggable extends Model {
static entity = 'taggables'
+ // @Attribute
+ id!: number
+
+ // @Attribute
+ tag_id!: number
+
+ // @Attribute
+ taggable_id!: number
+
+ // @Attribute
+ taggable_type!: string
+
static fields () {
return {
id: this.attr(null),
@@ -396,28 +417,26 @@ describe('Features – Relations – Morph To Many – Persist', () => {
}
}
- const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
+ createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await store.dispatch('entities/posts/create', {
- data: [
- {
- id: 1,
- tags: [
- { id: 1, name: 'news' },
- { id: 2, name: 'cast' }
- ]
- },
- {
- id: 2,
- tags: [
- { id: 1, name: 'news' },
- { id: 2, name: 'cast' }
- ]
- }
- ]
- })
+ await Post.create([
+ {
+ id: 1,
+ tags: [
+ { id: 1, name: 'news' },
+ { id: 2, name: 'cast' }
+ ]
+ },
+ {
+ id: 2,
+ tags: [
+ { id: 1, name: 'news' },
+ { id: 2, name: 'cast' }
+ ]
+ }
+ ])
- const post = store.getters['entities/posts/query']().with('tags').find(1)
+ const post = Post.query().with('tags').find(1) as Post
expect(post).toBeInstanceOf(Post)
expect(post.tags.length).toBe(2)
diff --git a/test/feature/relations/MorphToMany_Retrieve.spec.ts b/test/feature/relations/MorphToMany_Retrieve.spec.ts
index 575e5eda..e1293feb 100644
--- a/test/feature/relations/MorphToMany_Retrieve.spec.ts
+++ b/test/feature/relations/MorphToMany_Retrieve.spec.ts
@@ -89,25 +89,17 @@ describe('Feature – Relations – Morph To Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [{ id: 1 }, { id: 5 }, { id: 6 }]
- })
+ await Post.create([{ id: 1 }, { id: 5 }, { id: 6 }])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Tag.create({
- data: [{ id: 1, name: 'news' }, { id: 2, name: 'cast' }]
- })
+ await Tag.create([{ id: 1, name: 'news' }, { id: 2, name: 'cast' }])
- await Taggable.create({
- data: [
- { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts', is_public: true },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos', is_public: true },
- { id: 3, tag_id: 2, taggable_id: 1, taggable_type: 'posts', is_public: false }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts', is_public: true },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos', is_public: true },
+ { id: 3, tag_id: 2, taggable_id: 1, taggable_type: 'posts', is_public: false }
+ ])
const post = Post.query().with('tags').find(1) as Post
@@ -203,25 +195,17 @@ describe('Feature – Relations – Morph To Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [{ post_id: 1 }, { post_id: 5 }]
- })
+ await Post.create([{ post_id: 1 }, { post_id: 5 }])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Tag.create({
- data: [{ id: 1, name: 'news' }, { id: 2, name: 'cast' }]
- })
+ await Tag.create([{ id: 1, name: 'news' }, { id: 2, name: 'cast' }])
- await Taggable.create({
- data: [
- { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts' },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
- { id: 3, tag_id: 2, taggable_id: 1, taggable_type: 'posts' }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts' },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
+ { id: 3, tag_id: 2, taggable_id: 1, taggable_type: 'posts' }
+ ])
const post = Post.query().with('tags').find(1) as Post
@@ -313,28 +297,20 @@ describe('Feature – Relations – Morph To Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [
- { id: 1, post_id: 10 },
- { id: 5, post_id: 11 }
- ]
- })
+ await Post.create([
+ { id: 1, post_id: 10 },
+ { id: 5, post_id: 11 }
+ ])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Tag.create({
- data: [{ id: 1, name: 'news' }, { id: 2, name: 'cast' }]
- })
+ await Tag.create([{ id: 1, name: 'news' }, { id: 2, name: 'cast' }])
- await Taggable.create({
- data: [
- { id: 1, tag_id: 1, taggable_id: 10, taggable_type: 'posts' },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
- { id: 3, tag_id: 2, taggable_id: 10, taggable_type: 'posts' }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 1, taggable_id: 10, taggable_type: 'posts' },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
+ { id: 3, tag_id: 2, taggable_id: 10, taggable_type: 'posts' }
+ ])
const post = Post.query().with('tags').find(1) as Post
@@ -430,31 +406,23 @@ describe('Feature – Relations – Morph To Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [
- { id: 1, post_id: 10 },
- { id: 5, post_id: 11 }
- ]
- })
+ await Post.create([
+ { id: 1, post_id: 10 },
+ { id: 5, post_id: 11 }
+ ])
- await Video.create({
- data: { id: 3 }
- })
+ await Video.create({ id: 3 })
- await Tag.create({
- data: [
- { id: 1, tag_id: 100, name: 'news' },
- { id: 2, tag_id: 101, name: 'cast' }
- ]
- })
+ await Tag.create([
+ { id: 1, tag_id: 100, name: 'news' },
+ { id: 2, tag_id: 101, name: 'cast' }
+ ])
- await Taggable.create({
- data: [
- { id: 1, tag_id: 100, taggable_id: 10, taggable_type: 'posts' },
- { id: 2, tag_id: 100, taggable_id: 3, taggable_type: 'videos' },
- { id: 3, tag_id: 101, taggable_id: 10, taggable_type: 'posts' }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 100, taggable_id: 10, taggable_type: 'posts' },
+ { id: 2, tag_id: 100, taggable_id: 3, taggable_type: 'videos' },
+ { id: 3, tag_id: 101, taggable_id: 10, taggable_type: 'posts' }
+ ])
const post = Post.query().with('tags').find(1) as Post
@@ -539,17 +507,13 @@ describe('Feature – Relations – Morph To Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Post.insert({
- data: {
- id: 1,
- tags: [{ id: 1 }, { id: 3 }, { id: 2 }]
- }
+ id: 1,
+ tags: [{ id: 1 }, { id: 3 }, { id: 2 }]
})
await Video.insert({
- data: {
- id: 1,
- tags: [{ id: 1 }, { id: 3 }, { id: 2 }]
- }
+ id: 1,
+ tags: [{ id: 1 }, { id: 3 }, { id: 2 }]
})
const post = Post.query()
diff --git a/test/feature/relations/MorphedByMany_Persist.spec.ts b/test/feature/relations/MorphedByMany_Persist.spec.ts
index 1c9f1acc..18d888bf 100644
--- a/test/feature/relations/MorphedByMany_Persist.spec.ts
+++ b/test/feature/relations/MorphedByMany_Persist.spec.ts
@@ -53,12 +53,10 @@ describe('Feature – Relations – Morphed By Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Tag.create({
- data: {
- id: 1,
- name: 'news',
- posts: [{ id: 1, pivot: { public: true } }, { id: 2 }],
- videos: [{ id: 3, pivot: { public: true } }, { id: 4 }]
- }
+ id: 1,
+ name: 'news',
+ posts: [{ id: 1, pivot: { public: true } }, { id: 2 }],
+ videos: [{ id: 3, pivot: { public: true } }, { id: 4 }]
})
expect(store.state.entities.posts.data['1'].id).toBe(1)
@@ -128,22 +126,20 @@ describe('Feature – Relations – Morphed By Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Tag.create({
- data: [
- {
- id: 1,
- name: 'news',
- posts: [{ id: 1 }, { id: 2 }],
- videos: [{ id: 3 }, { id: 4 }]
- },
- {
- id: 2,
- name: 'cast',
- posts: [{ id: 2 }, { id: 3 }],
- videos: [{ id: 3 }, { id: 5 }]
- }
- ]
- })
+ await Tag.create([
+ {
+ id: 1,
+ name: 'news',
+ posts: [{ id: 1 }, { id: 2 }],
+ videos: [{ id: 3 }, { id: 4 }]
+ },
+ {
+ id: 2,
+ name: 'cast',
+ posts: [{ id: 2 }, { id: 3 }],
+ videos: [{ id: 3 }, { id: 5 }]
+ }
+ ])
expect(store.state.entities.posts.data['1'].id).toBe(1)
expect(store.state.entities.posts.data['2'].id).toBe(2)
@@ -232,12 +228,10 @@ describe('Feature – Relations – Morphed By Many – Persist', () => {
const store = createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Tag.create({
- data: {
- id: 1,
- name: 'news',
- posts: [{ id: 1, tag: { public: true } }, { id: 2 }],
- videos: [{ id: 3, tag: { public: true } }, { id: 4 }]
- }
+ id: 1,
+ name: 'news',
+ posts: [{ id: 1, tag: { public: true } }, { id: 2 }],
+ videos: [{ id: 3, tag: { public: true } }, { id: 4 }]
})
expect(store.state.entities.posts.data['1'].id).toBe(1)
diff --git a/test/feature/relations/MorphedByMany_Retrieve.spec.ts b/test/feature/relations/MorphedByMany_Retrieve.spec.ts
index c5179922..83cb6502 100644
--- a/test/feature/relations/MorphedByMany_Retrieve.spec.ts
+++ b/test/feature/relations/MorphedByMany_Retrieve.spec.ts
@@ -92,26 +92,18 @@ describe('Feature – Relations – Morphed By Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [{ id: 1 }, { id: 5 }]
- })
+ await Post.create([{ id: 1 }, { id: 5 }])
- await Video.create({
- data: [{ id: 3 }, { id: 4 }, { id: 5 }]
- })
+ await Video.create([{ id: 3 }, { id: 4 }, { id: 5 }])
- await Tag.create({
- data: [{ id: 1, name: 'news' }, { id: 3, name: 'without references' }]
- })
+ await Tag.create([{ id: 1, name: 'news' }, { id: 3, name: 'without references' }])
- await Taggable.create({
- data: [
- { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts', is_public: false },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos', is_public: true },
- { id: 3, tag_id: 1, taggable_id: 5, taggable_type: 'posts', is_public: true },
- { id: 4, tag_id: 1, taggable_id: 4, taggable_type: 'videos', is_public: false }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts', is_public: false },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos', is_public: true },
+ { id: 3, tag_id: 1, taggable_id: 5, taggable_type: 'posts', is_public: true },
+ { id: 4, tag_id: 1, taggable_id: 4, taggable_type: 'videos', is_public: false }
+ ])
const tag = Tag.query().with('posts').with('videos').find(1) as Tag
@@ -210,26 +202,18 @@ describe('Feature – Relations – Morphed By Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [{ post_id: 1 }, { post_id: 5 }]
- })
+ await Post.create([{ post_id: 1 }, { post_id: 5 }])
- await Video.create({
- data: [{ id: 3 }, { id: 4 }, { id: 5 }]
- })
+ await Video.create([{ id: 3 }, { id: 4 }, { id: 5 }])
- await Tag.create({
- data: { tag_id: 1, name: 'news' }
- })
+ await Tag.create({ tag_id: 1, name: 'news' })
- await Taggable.create({
- data: [
- { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts' },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
- { id: 3, tag_id: 1, taggable_id: 5, taggable_type: 'posts' },
- { id: 4, tag_id: 1, taggable_id: 4, taggable_type: 'videos' }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 1, taggable_id: 1, taggable_type: 'posts' },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
+ { id: 3, tag_id: 1, taggable_id: 5, taggable_type: 'posts' },
+ { id: 4, tag_id: 1, taggable_id: 4, taggable_type: 'videos' }
+ ])
const tag = Tag.query().with('posts').with('videos').find(1) as Tag
@@ -324,29 +308,21 @@ describe('Feature – Relations – Morphed By Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
- await Post.create({
- data: [
- { id: 1, post_id: 100 },
- { id: 5, post_id: 105 }
- ]
- })
+ await Post.create([
+ { id: 1, post_id: 100 },
+ { id: 5, post_id: 105 }
+ ])
- await Video.create({
- data: [{ id: 3 }, { id: 4 }, { id: 5 }]
- })
+ await Video.create([{ id: 3 }, { id: 4 }, { id: 5 }])
- await Tag.create({
- data: { id: 1, tag_id: 200, name: 'news' }
- })
+ await Tag.create({ id: 1, tag_id: 200, name: 'news' })
- await Taggable.create({
- data: [
- { id: 1, tag_id: 200, taggable_id: 100, taggable_type: 'posts' },
- { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
- { id: 3, tag_id: 200, taggable_id: 105, taggable_type: 'posts' },
- { id: 4, tag_id: 200, taggable_id: 4, taggable_type: 'videos' }
- ]
- })
+ await Taggable.create([
+ { id: 1, tag_id: 200, taggable_id: 100, taggable_type: 'posts' },
+ { id: 2, tag_id: 2, taggable_id: 3, taggable_type: 'videos' },
+ { id: 3, tag_id: 200, taggable_id: 105, taggable_type: 'posts' },
+ { id: 4, tag_id: 200, taggable_id: 4, taggable_type: 'videos' }
+ ])
const tag = Tag.query().with('posts').with('videos').find(1) as Tag
@@ -430,11 +406,9 @@ describe('Feature – Relations – Morphed By Many – Retrieve', () => {
createStore([{ model: Post }, { model: Video }, { model: Tag }, { model: Taggable }])
await Tag.create({
- data: {
- id: 1,
- posts: [{ id: 1 }, { id: 3 }, { id: 2 }],
- videos: [{ id: 1 }, { id: 3 }, { id: 2 }]
- }
+ id: 1,
+ posts: [{ id: 1 }, { id: 3 }, { id: 2 }],
+ videos: [{ id: 1 }, { id: 3 }, { id: 2 }]
})
const tag = Tag.query()
diff --git a/test/feature/relations/Persist_NestedMorph.spec.ts b/test/feature/relations/Persist_NestedMorph.spec.ts
index a3966e22..acfbd299 100644
--- a/test/feature/relations/Persist_NestedMorph.spec.ts
+++ b/test/feature/relations/Persist_NestedMorph.spec.ts
@@ -40,19 +40,17 @@ describe('Features – Relations – Persist – Nested Morph', () => {
const store = createStore([{ model: User }, { model: Post }, { model: Comment }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- comments: [
- {
- id: 1,
- user_id: 1,
- commentable_id: 1,
- commentable_type: 'posts',
- commentable: { id: 1 }
- }
- ]
- }
+ await User.create({
+ id: 1,
+ comments: [
+ {
+ id: 1,
+ user_id: 1,
+ commentable_id: 1,
+ commentable_type: 'posts',
+ commentable: { id: 1 }
+ }
+ ]
})
const expected = createState({
diff --git a/test/feature/relations/Retrieve_Constraint.spec.ts b/test/feature/relations/Retrieve_Constraint.spec.ts
index 6fc29675..230d6cfb 100644
--- a/test/feature/relations/Retrieve_Constraint.spec.ts
+++ b/test/feature/relations/Retrieve_Constraint.spec.ts
@@ -29,13 +29,13 @@ describe('Feature – Relations – Retrieve – Constraint', () => {
it('can resolve relation constraint', async () => {
const store = createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 1 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 1 },
+ { id: 3, user_id: 2 }
+ ])
const expected = {
$id: '1',
diff --git a/test/feature/relations/Retrieve_DeepLoad.spec.ts b/test/feature/relations/Retrieve_DeepLoad.spec.ts
index dbfb5235..1d3b9762 100644
--- a/test/feature/relations/Retrieve_DeepLoad.spec.ts
+++ b/test/feature/relations/Retrieve_DeepLoad.spec.ts
@@ -44,23 +44,21 @@ describe('Relations – Deep Load', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }])
- await store.dispatch('entities/posts/create', {
- data: {
+ await Post.create({
+ id: 1,
+ comments: [{
id: 1,
- comments: [{
+ user_id: 1,
+ user: {
id: 1,
- user_id: 1,
- user: {
- id: 1,
- name: 'John Doe'
- }
- }]
- }
+ name: 'John Doe'
+ }
+ }]
})
- const post = store.getters['entities/posts/query']().withAll().first()
+ const post = Post.query().withAll().first()
const expected = {
$id: '1',
diff --git a/test/feature/relations/Retrieve_Has.spec.ts b/test/feature/relations/Retrieve_Has.spec.ts
index 6ca688f0..f5ba9359 100644
--- a/test/feature/relations/Retrieve_Has.spec.ts
+++ b/test/feature/relations/Retrieve_Has.spec.ts
@@ -27,37 +27,40 @@ describe('Feature – Relations – Retrieve – Has', () => {
}
it('can query data depending on relationship existence', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
- const expected = [{ $id: '1', id: 1, posts: [] }, { $id: '2', id: 2, posts: [] }]
+ const expected = [
+ { $id: '1', id: 1, posts: [] },
+ { $id: '2', id: 2, posts: [] }
+ ]
- const users = store.getters['entities/users/query']().has('posts').get()
+ const users = User.query().has('posts').get()
expect(users).toEqual(expected)
})
it('can query data depending on relationship absence', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
const expected = [{ $id: '3', id: 3, posts: [] }]
- const users = store.getters['entities/users/query']().hasNot('posts').get()
+ const users = User.query().hasNot('posts').get()
expect(users).toEqual(expected)
})
@@ -86,29 +89,27 @@ describe('Feature – Relations – Retrieve – Has', () => {
}
}
- const store = createStore([{ model: User }, { model: Phone }, { model: Post }])
+ createStore([{ model: User }, { model: Phone }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
- await store.dispatch('entities/phones/create', {
- data: [{ id: 1, user_id: 2 }]
- })
+ await Phone.create([{ id: 1, user_id: 2 }])
const expected1 = [{ $id: '1', id: 1, phone: null, posts: [] }]
const expected2 = [{ $id: '2', id: 2, phone: null, posts: [] }]
- const users1 = store.getters['entities/users/query']()
- .whereHas('posts', (query: Query) => query.where('id', 1))
+ const users1 = User.query()
+ .whereHas('posts', (query: Query) => { query.where('id', 1) })
.get()
- const users2 = store.getters['entities/users/query']()
- .whereHas('phone', (query: Query) => query.where('id', 1))
+ const users2 = User.query()
+ .whereHas('phone', (query: Query) => { query.where('id', 1) })
.get()
expect(users1).toEqual(expected1)
@@ -116,57 +117,63 @@ describe('Feature – Relations – Retrieve – Has', () => {
})
it('can query data depending on relationship absence with constraint', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
- const expected = [{ $id: '2', id: 2, posts: [] }, { $id: '3', id: 3, posts: [] }]
+ const expected = [
+ { $id: '2', id: 2, posts: [] },
+ { $id: '3', id: 3, posts: [] }
+ ]
- const users = store.getters['entities/users/query']()
- .whereHasNot('posts', (query: Query) => query.where('id', 1))
+ const users = User.query()
+ .whereHasNot('posts', (query: Query) => { query.where('id', 1) })
.get()
expect(users).toEqual(expected)
})
it('can query data depending on relationship existence with number', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
const expected = [{ $id: '2', id: 2, posts: [] }]
- const users = store.getters['entities/users/query']().has('posts', 2).get()
+ const users = User.query().has('posts', 2).get()
expect(users).toEqual(expected)
})
it('can query data depending on relationship absence with number', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([
+ { id: 1, user_id: 1 },
+ { id: 2, user_id: 2 },
+ { id: 3, user_id: 2 }
+ ])
- const expected = [{ $id: '1', id: 1, posts: [] }, { $id: '3', id: 3, posts: [] }]
+ const expected = [
+ { $id: '1', id: 1, posts: [] },
+ { $id: '3', id: 3, posts: [] }
+ ]
- const users = store.getters['entities/users/query']().hasNot('posts', 2).get()
+ const users = User.query().hasNot('posts', 2).get()
expect(users).toEqual(expected)
})
@@ -195,45 +202,35 @@ describe('Feature – Relations – Retrieve – Has', () => {
}
}
- const store = createStore([{ model: User }, { model: Phone }, { model: Post }])
+ createStore([{ model: User }, { model: Phone }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }])
- await store.dispatch('entities/phones/create', {
- data: [{ id: 1, user_id: 1 }]
- })
+ await Phone.create([{ id: 1, user_id: 1 }])
- expect(store.getters['entities/users/query']().has('posts', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', '=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', '>', 1).get()).toEqual([{ $id: '2', id: 2, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', '>=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', '<', 2).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', '<=', 2).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('posts', 'unknown', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
+ expect(User.query().has('posts', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
+ expect(User.query().has('posts', '=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
+ expect(User.query().has('posts', '>', 1).get()).toEqual([{ $id: '2', id: 2, phone: null, posts: [] }])
+ expect(User.query().has('posts', '>=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
+ expect(User.query().has('posts', '<', 2).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
+ expect(User.query().has('posts', '<=', 2).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }, { $id: '2', id: 2, phone: null, posts: [] }])
+ expect(User.query().has('posts', 'unknown', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
- expect(store.getters['entities/users/query']().has('phone', '=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
+ expect(User.query().has('phone', '=', 1).get()).toEqual([{ $id: '1', id: 1, phone: null, posts: [] }])
})
it('can query data depending on relationship absence with string conditions', async () => {
- const store = createStore([{ model: User }, { model: Post }])
+ createStore([{ model: User }, { model: Post }])
- await store.dispatch('entities/users/create', {
- data: [{ id: 1 }, { id: 2 }, { id: 3 }]
- })
+ await User.create([{ id: 1 }, { id: 2 }, { id: 3 }])
- await store.dispatch('entities/posts/create', {
- data: [{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }]
- })
+ await Post.create([{ id: 1, user_id: 1 }, { id: 2, user_id: 2 }, { id: 3, user_id: 2 }])
- expect(store.getters['entities/users/query']().hasNot('posts', '>', 1).get()).toEqual([{ $id: '1', id: 1, posts: [] }, { $id: '3', id: 3, posts: [] }])
- expect(store.getters['entities/users/query']().hasNot('posts', '>=', 1).get()).toEqual([{ $id: '3', id: 3, posts: [] }])
- expect(store.getters['entities/users/query']().hasNot('posts', '<', 2).get()).toEqual([{ $id: '2', id: 2, posts: [] }, { $id: '3', id: 3, posts: [] }])
- expect(store.getters['entities/users/query']().hasNot('posts', '<=', 2).get()).toEqual([{ $id: '3', id: 3, posts: [] }])
+ expect(User.query().hasNot('posts', '>', 1).get()).toEqual([{ $id: '1', id: 1, posts: [] }, { $id: '3', id: 3, posts: [] }])
+ expect(User.query().hasNot('posts', '>=', 1).get()).toEqual([{ $id: '3', id: 3, posts: [] }])
+ expect(User.query().hasNot('posts', '<', 2).get()).toEqual([{ $id: '2', id: 2, posts: [] }, { $id: '3', id: 3, posts: [] }])
+ expect(User.query().hasNot('posts', '<=', 2).get()).toEqual([{ $id: '3', id: 3, posts: [] }])
})
})
diff --git a/test/feature/relations/Retrieve_SelfRelation.spec.ts b/test/feature/relations/Retrieve_SelfRelation.spec.ts
index 0c53a82a..9e7ecde6 100644
--- a/test/feature/relations/Retrieve_SelfRelation.spec.ts
+++ b/test/feature/relations/Retrieve_SelfRelation.spec.ts
@@ -27,13 +27,8 @@ describe('Feature – Relations – Retrieve – Self Relation', () => {
createStore([{ model: Post }])
- await Post.insert({
- data: { id: 1, parent_id: null }
- })
-
- await Post.insert({
- data: { id: 2, parent_id: 1 }
- })
+ await Post.insert({ id: 1, parent_id: null })
+ await Post.insert({ id: 2, parent_id: 1 })
const post = Post.query().with('parent').find(2) as Post
diff --git a/test/feature/relations/Retrieve_StringDefine.spec.ts b/test/feature/relations/Retrieve_StringDefine.spec.ts
index 4c51b839..2c039889 100644
--- a/test/feature/relations/Retrieve_StringDefine.spec.ts
+++ b/test/feature/relations/Retrieve_StringDefine.spec.ts
@@ -40,13 +40,9 @@ describe('Feature – Relations - String Define', () => {
createStore([{ model: User }, { model: Post }])
- await User.create({
- data: { id: 1 }
- })
+ await User.create({ id: 1 })
- await Post.create({
- data: { id: 2, user_id: 1 }
- })
+ await Post.create({ id: 2, user_id: 1 })
const user = User.query().with('posts').find(1) as User
diff --git a/test/feature/relations/Retrieve_With.spec.ts b/test/feature/relations/Retrieve_With.spec.ts
index 03507cd5..e2e4d8a5 100644
--- a/test/feature/relations/Retrieve_With.spec.ts
+++ b/test/feature/relations/Retrieve_With.spec.ts
@@ -62,14 +62,12 @@ describe('Feature – Relations – Retrieve – With', () => {
createStore([{ model: User }, { model: Phone }, { model: Post }])
await User.create({
- data: {
- id: 1,
- phone: { id: 2, user_id: 1 },
- posts: [
- { id: 3, user_id: 1 },
- { id: 4, user_id: 1 }
- ]
- }
+ id: 1,
+ phone: { id: 2, user_id: 1 },
+ posts: [
+ { id: 3, user_id: 1 },
+ { id: 4, user_id: 1 }
+ ]
})
const user1 = User.query().with('*').first() as User
@@ -148,22 +146,20 @@ describe('Feature – Relations – Retrieve – With', () => {
createStore([{ model: User }, { model: Phone }, { model: Post }])
await User.create({
- data: {
- id: 1,
- phone: { id: 2, user_id: 1 },
- posts: [
- {
- id: 3,
- user_id: 1,
- user: { id: 1 }
- },
- {
- id: 4,
- user_id: 1,
- user: { id: 1 }
- }
- ]
- }
+ id: 1,
+ phone: { id: 2, user_id: 1 },
+ posts: [
+ {
+ id: 3,
+ user_id: 1,
+ user: { id: 1 }
+ },
+ {
+ id: 4,
+ user_id: 1,
+ user: { id: 1 }
+ }
+ ]
})
const user1 = User.query().withAllRecursive().first() as User
@@ -239,30 +235,28 @@ describe('Feature – Relations – Retrieve – With', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- posts: [
- {
- id: 1,
- user_id: 1,
- comments: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ]
- },
- {
- id: 2,
- user_id: 1,
- comments: [
- { id: 3, post_id: 2 },
- { id: 4, post_id: 2 }
- ]
- }
- ]
- }
+ await User.create({
+ id: 1,
+ posts: [
+ {
+ id: 1,
+ user_id: 1,
+ comments: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ]
+ },
+ {
+ id: 2,
+ user_id: 1,
+ comments: [
+ { id: 3, post_id: 2 },
+ { id: 4, post_id: 2 }
+ ]
+ }
+ ]
})
const expected = {
@@ -351,28 +345,26 @@ describe('Feature – Relations – Retrieve – With', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }])
- await store.dispatch('entities/users/create', {
- data: [
- {
- id: 1,
- posts: [
- {
- id: 1,
- user_id: 1,
- comments: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ]
- }
- ]
- },
- {
- id: 2
- }
- ]
- })
+ await User.create([
+ {
+ id: 1,
+ posts: [
+ {
+ id: 1,
+ user_id: 1,
+ comments: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ]
+ }
+ ]
+ },
+ {
+ id: 2
+ }
+ ])
const expected = [
{
@@ -397,9 +389,7 @@ describe('Feature – Relations – Retrieve – With', () => {
}
]
- const users = await store.getters['entities/users/query']()
- .with('posts.comments')
- .findIn([1, 2]) as User[]
+ const users = User.query().with('posts.comments').findIn([1, 2])
expect(users).toEqual(expected)
})
@@ -481,30 +471,28 @@ describe('Feature – Relations – Retrieve – With', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- posts: [
- {
- id: 1,
- user_id: 1,
- comments: [
- { id: 1, post_id: 1, likes: [{ id: 1, comment_id: 1 }] },
- { id: 2, post_id: 1, likes: [{ id: 2, comment_id: 2 }] }
- ]
- },
- {
- id: 2,
- user_id: 1,
- comments: [
- { id: 3, post_id: 2, likes: [{ id: 3, comment_id: 3 }] },
- { id: 4, post_id: 2, likes: [{ id: 4, comment_id: 4 }] }
- ]
- }
- ]
- }
+ await User.create({
+ id: 1,
+ posts: [
+ {
+ id: 1,
+ user_id: 1,
+ comments: [
+ { id: 1, post_id: 1, likes: [{ id: 1, comment_id: 1 }] },
+ { id: 2, post_id: 1, likes: [{ id: 2, comment_id: 2 }] }
+ ]
+ },
+ {
+ id: 2,
+ user_id: 1,
+ comments: [
+ { id: 3, post_id: 2, likes: [{ id: 3, comment_id: 3 }] },
+ { id: 4, post_id: 2, likes: [{ id: 4, comment_id: 4 }] }
+ ]
+ }
+ ]
})
const expected = {
@@ -532,7 +520,7 @@ describe('Feature – Relations – Retrieve – With', () => {
]
}
- const users = store.getters['entities/users/query']().with('posts.comments.likes').find(1) as User[]
+ const users = User.query().with('posts.comments.likes').find(1)
expect(users).toEqual(expected)
})
@@ -614,38 +602,36 @@ describe('Feature – Relations – Retrieve – With', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- posts: [
- {
- id: 1,
- user_id: 1,
- comments: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ],
- likes: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ]
- },
- {
- id: 2,
- user_id: 1,
- comments: [
- { id: 3, post_id: 2 },
- { id: 4, post_id: 2 }
- ],
- likes: [
- { id: 3, post_id: 2 },
- { id: 4, post_id: 2 }
- ]
- }
- ]
- }
+ await User.create({
+ id: 1,
+ posts: [
+ {
+ id: 1,
+ user_id: 1,
+ comments: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ],
+ likes: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ]
+ },
+ {
+ id: 2,
+ user_id: 1,
+ comments: [
+ { id: 3, post_id: 2 },
+ { id: 4, post_id: 2 }
+ ],
+ likes: [
+ { id: 3, post_id: 2 },
+ { id: 4, post_id: 2 }
+ ]
+ }
+ ]
})
const expected = {
@@ -681,8 +667,8 @@ describe('Feature – Relations – Retrieve – With', () => {
]
}
- const user1 = User.query().with('posts.comments|likes').find(1) as User
- const user2 = User.query().with('posts.*').find(1) as User
+ const user1 = User.query().with('posts.comments|likes').find(1)
+ const user2 = User.query().with('posts.*').find(1)
expect(user1).toEqual(expected)
expect(user2).toEqual(expected)
@@ -735,38 +721,36 @@ describe('Feature – Relations – Retrieve – With', () => {
}
}
- const store = createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
+ createStore([{ model: User }, { model: Post }, { model: Comment }, { model: Like }])
- await store.dispatch('entities/users/create', {
- data: {
- id: 1,
- posts: [
- {
- id: 1,
- user_id: 1,
- comments: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ],
- likes: [
- { id: 1, post_id: 1 },
- { id: 2, post_id: 1 }
- ]
- },
- {
- id: 2,
- user_id: 1,
- comments: [
- { id: 3, post_id: 2 },
- { id: 4, post_id: 2 }
- ],
- likes: [
- { id: 3, post_id: 2 },
- { id: 4, post_id: 2 }
- ]
- }
- ]
- }
+ await User.create({
+ id: 1,
+ posts: [
+ {
+ id: 1,
+ user_id: 1,
+ comments: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ],
+ likes: [
+ { id: 1, post_id: 1 },
+ { id: 2, post_id: 1 }
+ ]
+ },
+ {
+ id: 2,
+ user_id: 1,
+ comments: [
+ { id: 3, post_id: 2 },
+ { id: 4, post_id: 2 }
+ ],
+ likes: [
+ { id: 3, post_id: 2 },
+ { id: 4, post_id: 2 }
+ ]
+ }
+ ]
})
const expected = {
@@ -802,8 +786,8 @@ describe('Feature – Relations – Retrieve – With', () => {
]
}
- const user1 = store.getters['entities/users/query']().with(['posts.comments', 'posts.likes']).find(1)
- const user2 = store.getters['entities/users/query']().with(['posts.*']).find(1)
+ const user1 = User.query().with(['posts.comments', 'posts.likes']).find(1)
+ const user2 = User.query().with(['posts.*']).find(1)
expect(user1).toEqual(expected)
expect(user2).toEqual(expected)
@@ -847,12 +831,10 @@ describe('Feature – Relations – Retrieve – With', () => {
createStore([{ model: User }, { model: Post }])
await User.create({
- data: {
- id: 1,
- posts: [
- { id: 1, user_id: 1 }
- ]
- }
+ id: 1,
+ posts: [
+ { id: 1, user_id: 1 }
+ ]
})
const user = User.query().with('unknown').first() as User
@@ -897,17 +879,9 @@ describe('Feature – Relations – Retrieve – With', () => {
createStore([{ model: User }, { model: Post }])
- await User.create({
- data: {
- id: 1
- }
- })
- await Post.create({
- data: {
- id: 1,
- user_id: null
- }
- })
+ await User.create({ id: 1 })
+
+ await Post.create({ id: 1, user_id: null })
const post = Post.query()
.with('*')
diff --git a/test/feature/relations/Retrieve_With_NestedConstraints.spec.ts b/test/feature/relations/Retrieve_With_NestedConstraints.spec.ts
index a760a87a..150f7b7d 100644
--- a/test/feature/relations/Retrieve_With_NestedConstraints.spec.ts
+++ b/test/feature/relations/Retrieve_With_NestedConstraints.spec.ts
@@ -67,17 +67,15 @@ describe('Feature – Relations – With – Nested Constraints', () => {
})
it('can apply `with` constraints to nested relations', async () => {
- await User.create({ data: { id: 1 } })
+ await User.create({ id: 1 })
- await Post.create({ data: { id: 1, user_id: 1 } })
+ await Post.create({ id: 1, user_id: 1 })
- await Comment.create({
- data: [
- { id: 1, post_id: 1, title: 'Title01' },
- { id: 2, post_id: 1, title: 'Title01' },
- { id: 3, post_id: 1, title: 'Title02' }
- ]
- })
+ await Comment.create([
+ { id: 1, post_id: 1, title: 'Title01' },
+ { id: 2, post_id: 1, title: 'Title01' },
+ { id: 3, post_id: 1, title: 'Title02' }
+ ])
const user = User.query().with('posts.comments', (query) => {
query.where('title', 'Title01')
From 3ba4c7dfd1a2b7e500731d2f8462dfa90d93aaa3 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Wed, 1 Apr 2020 09:44:18 +0100
Subject: [PATCH 03/56] docs: api reference revision (#610)
---
docs/.vuepress/config.js | 13 +-
docs/api/container/container.md | 12 +-
docs/api/database/database.md | 139 ++----
docs/api/deleting-data.md | 145 ------
docs/api/model/attributes.md | 294 +++++++++++
docs/api/model/lifecycle-hooks.md | 105 ++++
docs/api/model/model.md | 483 +++++++++++++++----
docs/api/query/query.md | 251 ++++++++++
docs/guide/digging-deeper/vuex-module.md | 2 +-
docs/guide/model/single-table-inheritance.md | 64 ++-
10 files changed, 1135 insertions(+), 373 deletions(-)
delete mode 100644 docs/api/deleting-data.md
create mode 100644 docs/api/model/attributes.md
create mode 100644 docs/api/model/lifecycle-hooks.md
create mode 100644 docs/api/query/query.md
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 62071bfb..fbfcf48b 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -69,7 +69,16 @@ const sidebars = {
title: 'Model',
collapsable: false,
children: [
- '/api/model/model'
+ '/api/model/model',
+ '/api/model/attributes',
+ '/api/model/lifecycle-hooks'
+ ]
+ },
+ {
+ title: 'Query',
+ collapsable: false,
+ children: [
+ '/api/query/query'
]
}
]
@@ -77,7 +86,7 @@ const sidebars = {
module.exports = {
title: 'Vuex ORM',
- description: 'The Vuex plugin to enable Object-Relational Mapping access to the Vuex Store.',
+ description: 'The Vuex plugin to enable Object-Relational Mapping (ORM) access to the Vuex Store.',
base: '/vuex-orm/',
diff --git a/docs/api/container/container.md b/docs/api/container/container.md
index 8688f58c..7d49ce42 100644
--- a/docs/api/container/container.md
+++ b/docs/api/container/container.md
@@ -4,13 +4,13 @@ sidebarDepth: 2
# Container
-The Container is the global object that holds Vuex Store instance. The only purpose of the Container is to hold store instance so that we can use it in other places. Please refer to [Database](/api/database/database) to see why we need this global object in the first place.
+The Container holds the Vuex Store instance. The only purpose of the Container is to hold store instance so that it can be used throughout the library. It is tightly coupled with the [Database](/api/database/database) instance.
## Static Properties
-### store
+### `store`
-- **`static store: Vuex.Store`**
+- **Type**: `Vuex.Store`
The store instance that Vuex ORM is being installed.
@@ -18,12 +18,12 @@ The Container is the global object that holds Vuex Store instance. The only purp
### register
-- **`static register(store: Vuex.Store): void`**
+- **Type**: `(store: Vuex.Store) => void`
Register a store instance to the Container.
```js
- Container.register(store)
+ Container.register(new Vuex.Store())
```
- This method is called during the Vuex plugin installation, so usually, you would never have to use this method.
+ This method is called during the Vuex plugin installation.
diff --git a/docs/api/database/database.md b/docs/api/database/database.md
index f26fa97c..a20e3126 100644
--- a/docs/api/database/database.md
+++ b/docs/api/database/database.md
@@ -4,45 +4,13 @@ sidebarDepth: 2
# Database
-The Database is the object that holds all Models and Modules that are registered to the Vuex ORM. It is also responsible for generating the whole database relational schema from registered models. This schema is used to "Normalize" data before persisting to the Vuex Store.
+The Database holds all models and modules registered to Vuex ORM. It is also responsible for generating the database relational schema from the registered models. This schema is used to "Normalize" data before persisting to the Vuex Store.
-When using Vuex ORM, you will unlikely need to use the Database class after it's registered to the Vuex Store. But for those who are curious, we'll describe why the Database object exists in the first place.
+In Vuex ORM, models may have relations with other models. To resolve those relations, models require some form of tracking in order to communicate with one another.
-In Vuex ORM, any Model can have any type of relationship with other Models. To resolve those relationships, we need to store all Models somewhere so that a Model can reference each other. That's where the Database comes in to play. You can get any registered Model like this.
+The Database is designed to track all registered models, build relational schema from those models, and register the database to the Vuex Store instance (contained in [Container](/api/container/container)).
-```js
-const database = new Database()
-
-database.register(User)
-
-const user = database.model('users')
-```
-
-You might wonder why do we need to store all Models in one place since the related Models are passed at Model when defining relationships like below.
-
-```js
-import { Model } from '@vuex-orm/core'
-import Post from './Post'
-
-class User extends Model {
- static entity = 'users'
-
- static fields () {
- return {
- id: this.attr(null),
- posts: this.hasMany(Post, 'user_id') // <- Passing related Model.
- }
- }
-}
-```
-
-So, can't we just resolve relationship directly from the Model? Unfortunately no, we can't. The primary reason is that Vuex ORM is built on top of Vuex, and Vuex ORM is calling Vuex Getters/Actions/Mutations to interact with the Vuex Store. In fact, you can call Vuex Actions directly to create or fetch data.
-
-Vuex Module doesn't have access to Model. It must resolve the Model from the entity name, which is a `string`. When a user calls actions like `store.dispatch('entities/users/insert', { ... })`, we must somehow get User Model by the namespace, which is `users` in `entities/users/insert`. Well, Vuex ORM actions are getting Models from the Database.
-
-Finally, the created Database instance is registered to the Vuex Store instance, then it's registered to the [Container](../container/container) so we have access to it from everywhere.
-
-You can access the database instance through the store instance, or Container.
+The database instance can be accessed through the store instance, or [Container](/api/container/container).
```js
// Through the store instance.
@@ -54,77 +22,69 @@ import { Container } from '@vuex-orm/core'
Container.store.$db()
```
+
## Instance Properties
-### store
+### `store`
-- **`store!: Vuex.Store`**
+- **Type**: `Vuex.Store`
The Vuex Store instance.
-### namespace
+### `namespace`
-- **`namespace!: string`**
+- **Type**: `string = 'entities'`
- The namespace of the Vuex Store Module where all entities are registered under. the default is `entities`.
+ The namespace of the Vuex Store module where all entities are registered under.
+
+ The default namespace is `entities` and can be configured during setup.
-### entities
+- **See also**: [Changing the Namespace](/guide/model/database-registration.md#changing-the-namespace)
-- **`entities: Entity[] = []`**
+### `entities`
- The list of entities registered to the Vuex Store. It contains models and modules with its name. The Entity interface looks like below.
+- **Type**: `Array
Big Love Sponsors
From 803462eae786278d4539d5980b7511f1acf487d2 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Wed, 1 Apr 2020 19:59:22 +0100
Subject: [PATCH 06/56] chore: remove code standard badge
---
README.md | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index 2f131ede..26970202 100644
--- a/README.md
+++ b/README.md
@@ -5,18 +5,15 @@
Vuex ORM
+
+
+
-
-
-
-
-
-
From aa9de263b57ca996fee598e9c58b9aaf7f9c7699 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Wed, 1 Apr 2020 22:05:05 +0100
Subject: [PATCH 07/56] docs: replace Standard JS with Prettier
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 26970202..d8fe6503 100644
--- a/README.md
+++ b/README.md
@@ -128,7 +128,7 @@ Compile files and generate bundles in `dist` directory.
$ yarn lint
```
-Lint files using a rule of Standard JS.
+Lint files using [Prettier](https://prettier.io/).
```bash
$ yarn test
From ca64d97be89a38dcd93812b2b894ad1740a91d68 Mon Sep 17 00:00:00 2001
From: Kia Ishii
Date: Sat, 4 Apr 2020 16:26:26 +0900
Subject: [PATCH 08/56] style(polyfills): clean the file a bit
---
src/polyfills/index.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/polyfills/index.ts b/src/polyfills/index.ts
index ff16b43f..b505cb3d 100644
--- a/src/polyfills/index.ts
+++ b/src/polyfills/index.ts
@@ -1,8 +1,6 @@
-/*eslint-disable */
-
+import 'core-js/fn/array/from'
import 'core-js/fn/array/includes'
import 'core-js/fn/object/assign'
import 'core-js/fn/object/entries'
import 'core-js/fn/object/values'
import 'core-js/fn/string/starts-with'
-import 'core-js/fn/array/from'
From 2270a8a36c4c829459ec6dbf5d2f9a12d26e67bf Mon Sep 17 00:00:00 2001
From: Kia King Ishii
Date: Sat, 4 Apr 2020 17:32:33 +0900
Subject: [PATCH 09/56] refactor: installation related structures (#615)
---
src/index.cjs.ts | 47 +--------------
src/index.ts | 45 +--------------
src/plugins/use.ts | 2 +-
src/store/{install.ts => index.ts} | 8 +--
test/feature/VuexORM.spec.ts | 86 ----------------------------
test/feature/modules/modules.spec.ts | 48 ++++++++++++++++
test/unit/VuexORM.spec.ts | 76 ++++++++++++++++++++++++
7 files changed, 134 insertions(+), 178 deletions(-)
rename src/store/{install.ts => index.ts} (92%)
delete mode 100644 test/feature/VuexORM.spec.ts
create mode 100644 test/feature/modules/modules.spec.ts
create mode 100644 test/unit/VuexORM.spec.ts
diff --git a/src/index.cjs.ts b/src/index.cjs.ts
index 32496d6f..66ebfe54 100644
--- a/src/index.cjs.ts
+++ b/src/index.cjs.ts
@@ -1,11 +1,10 @@
import './polyfills'
-import install, { Install } from './store/install'
-import use, { Use } from './plugins/use'
+import { install } from './store'
+import { use } from './plugins/use'
import Container from './container/Container'
import Database from './database/Database'
import Model from './model/Model'
-import Fields from './model/contracts/Fields'
import Query from './query/Query'
import Attribute from './attributes/Attribute'
import Type from './attributes/types/Type'
@@ -32,46 +31,6 @@ import Actions from './modules/Actions'
import RootGetters from './modules/RootGetters'
import RootActions from './modules/RootActions'
import RootMutations from './modules/RootMutations'
-import GettersContract from './modules/contracts/Getters'
-import ActionsContract from './modules/contracts/Actions'
-import RootGettersContract from './modules/contracts/RootGetters'
-import RootActionsContract from './modules/contracts/RootActions'
-import RootMutationsContract from './modules/contracts/RootMutations'
-
-export interface VuexORM {
- install: Install
- use: Use
- Container: typeof Container
- Database: typeof Database
- Model: typeof Model
- Fields: Fields
- Query: typeof Query
- Attribute: typeof Attribute
- Type: typeof Type
- Attr: typeof Attr
- String: typeof String
- Number: typeof Number
- Boolean: typeof Boolean
- Uid: typeof Uid
- Relation: typeof Relation
- HasOne: typeof HasOne
- BelongsTo: typeof BelongsTo
- HasMany: typeof HasMany
- HasManyBy: typeof HasManyBy
- BelongsToMany: typeof BelongsToMany
- HasManyThrough: typeof HasManyThrough
- MorphTo: typeof MorphTo
- MorphOne: typeof MorphOne
- MorphMany: typeof MorphMany
- MorphToMany: typeof MorphToMany
- MorphedByMany: typeof MorphedByMany
- Repository: typeof Repository
- Getters: GettersContract
- Actions: ActionsContract
- RootGetters: RootGettersContract
- RootActions: RootActionsContract
- RootMutations: RootMutationsContract
-}
export default {
install,
@@ -105,4 +64,4 @@ export default {
RootActions,
RootMutations,
Query
-} as VuexORM
+}
diff --git a/src/index.ts b/src/index.ts
index ead67a3e..953d7d8a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,8 +1,8 @@
import './types/vuex'
import './polyfills'
-import install, { Install } from './store/install'
-import use, { Use, PluginComponents } from './plugins/use'
+import { install } from './store'
+import { use, PluginComponents } from './plugins/use'
import Container from './container/Container'
import Database from './database/Database'
import Model from './model/Model'
@@ -32,11 +32,6 @@ import Actions from './modules/Actions'
import RootGetters from './modules/RootGetters'
import RootActions from './modules/RootActions'
import RootMutations from './modules/RootMutations'
-import GettersContract from './modules/contracts/Getters'
-import ActionsContract from './modules/contracts/Actions'
-import RootGettersContract from './modules/contracts/RootGetters'
-import RootActionsContract from './modules/contracts/RootActions'
-import RootMutationsContract from './modules/contracts/RootMutations'
import Query from './query/Query'
import Record from './data/Record'
import Records from './data/Records'
@@ -49,40 +44,6 @@ import Item from './data/Item'
import Collection from './data/Collection'
import Collections from './data/Collections'
-export interface VuexORM {
- install: Install
- use: Use
- Container: typeof Container
- Database: typeof Database
- Model: typeof Model
- Attribute: typeof Attribute
- Type: typeof Type
- Attr: typeof Attr
- String: typeof String
- Number: typeof Number
- Boolean: typeof Boolean
- Uid: typeof Uid
- Relation: typeof Relation
- HasOne: typeof HasOne
- BelongsTo: typeof BelongsTo
- HasMany: typeof HasMany
- HasManyBy: typeof HasManyBy
- BelongsToMany: typeof BelongsToMany
- HasManyThrough: typeof HasManyThrough
- MorphTo: typeof MorphTo
- MorphOne: typeof MorphOne
- MorphMany: typeof MorphMany
- MorphToMany: typeof MorphToMany
- MorphedByMany: typeof MorphedByMany
- Repository: typeof Repository
- Getters: GettersContract
- Actions: ActionsContract
- RootGetters: RootGettersContract
- RootActions: RootActionsContract
- RootMutations: RootMutationsContract
- Query: typeof Query
-}
-
export {
install,
use,
@@ -161,4 +122,4 @@ export default {
RootActions,
RootMutations,
Query
-} as VuexORM
+}
diff --git a/src/plugins/use.ts b/src/plugins/use.ts
index 222eb921..f8bbef26 100644
--- a/src/plugins/use.ts
+++ b/src/plugins/use.ts
@@ -73,7 +73,7 @@ export interface Plugin {
export type Use = (plugin: Plugin, options?: Options) => void
-export default function(plugin: Plugin, options: Options = {}): void {
+export function use(plugin: Plugin, options: Options = {}): void {
const components: PluginComponents = {
Repository,
Model,
diff --git a/src/store/install.ts b/src/store/index.ts
similarity index 92%
rename from src/store/install.ts
rename to src/store/index.ts
index 21183936..552b056f 100644
--- a/src/store/install.ts
+++ b/src/store/index.ts
@@ -4,8 +4,6 @@ import Database from '../database/Database'
import HackedDatabase from '../database/HackedDatabase'
import Repository from '../repository/Repository'
-export type Install = (database: Database, options?: Options) => Plugin
-
export interface Options {
namespace?: string
}
@@ -13,7 +11,7 @@ export interface Options {
/**
* Install Vuex ORM database to the store.
*/
-export default function install(
+export function install(
database: Database,
options: Options = {}
): Plugin {
@@ -55,8 +53,8 @@ function mixinRepoFunction(store: Store): void {
throw new Error(
'[Vuex ORM] The repository was instantiated without a model being ' +
'set. It happens when you forgot to register the model to the ' +
- 'custom repository. Please check if you have correctly set `model` ' +
- 'property at the repository class.'
+ 'custom repository. Please check if you have correctly set ' +
+ '`model` property at the repository class.'
)
}
diff --git a/test/feature/VuexORM.spec.ts b/test/feature/VuexORM.spec.ts
deleted file mode 100644
index f3763cc8..00000000
--- a/test/feature/VuexORM.spec.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import Vue from 'vue'
-import Vuex from 'vuex'
-import VuexORM from '@/index'
-
-describe('Feature – Vuex ORM', () => {
- Vue.use(Vuex)
-
- class User extends VuexORM.Model {
- static entity = 'users'
- }
-
- class Post extends VuexORM.Model {
- static entity = 'posts'
- }
-
- const users = {}
- const posts = {}
-
- it('can install Vuex ORM to the Vuex', () => {
- const database = new VuexORM.Database()
-
- database.register(User, users)
- database.register(Post, posts)
-
- const store = new Vuex.Store({
- plugins: [VuexORM.install(database)]
- })
-
- expect(store.state.entities.$name).toBe('entities')
- expect(store.state.entities.users.$name).toBe('users')
- expect(store.state.entities.posts.$name).toBe('posts')
- })
-
- it('can omit modules', () => {
- const database = new VuexORM.Database()
-
- database.register(User)
- database.register(Post)
-
- const store = new Vuex.Store({
- plugins: [VuexORM.install(database)]
- })
-
- expect(store.state.entities.$name).toBe('entities')
- expect(store.state.entities.users.$name).toBe('users')
- expect(store.state.entities.posts.$name).toBe('posts')
- })
-
- it('can install Vuex ORM to the Vuex under a custom namespace', () => {
- const database = new VuexORM.Database()
-
- database.register(User, users)
- database.register(Post, posts)
-
- const options = { namespace: 'my_entities' }
-
- const store = new Vuex.Store({
- plugins: [VuexORM.install(database, options)]
- })
-
- expect(store.state.my_entities.$name).toBe('my_entities')
- expect(store.state.my_entities.users.$name).toBe('users')
- expect(store.state.my_entities.posts.$name).toBe('posts')
- })
-
- it('can install Vuex ORM along with custom state as a function', () => {
- const database = new VuexORM.Database()
-
- const users = {
- state() {
- return {
- customState: 'Yes, it is custom'
- }
- }
- }
-
- database.register(User, users)
-
- const store = new Vuex.Store({
- plugins: [VuexORM.install(database)]
- })
-
- expect(store.state.entities.users.$name).toBe('users')
- expect(store.state.entities.users.customState).toBe('Yes, it is custom')
- })
-})
diff --git a/test/feature/modules/modules.spec.ts b/test/feature/modules/modules.spec.ts
new file mode 100644
index 00000000..85607d9d
--- /dev/null
+++ b/test/feature/modules/modules.spec.ts
@@ -0,0 +1,48 @@
+import Vue from 'vue'
+import Vuex, { Module } from 'vuex'
+import VuexORM, { Database, Model } from '@/index'
+
+describe('feature/modules/modules', () => {
+ Vue.use(Vuex)
+
+ it('can install a custom module along with the model', async () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const users: Module<{ count: number }, any> = {
+ state: () => ({
+ count: 1
+ }),
+ getters: {
+ double: (state) => state.count * 2
+ },
+ actions: {
+ increment({ commit }) {
+ commit('increment')
+ }
+ },
+ mutations: {
+ increment(state) {
+ state.count++
+ }
+ }
+ }
+
+ const database = new Database()
+
+ database.register(User, users)
+
+ const store = new Vuex.Store({
+ plugins: [VuexORM.install(database)]
+ })
+
+ expect(store.state.entities.users.count).toBe(1)
+ expect(store.getters['entities/users/double']).toBe(2)
+
+ await store.dispatch('entities/users/increment')
+
+ expect(store.state.entities.users.count).toBe(2)
+ expect(store.getters['entities/users/double']).toBe(4)
+ })
+})
diff --git a/test/unit/VuexORM.spec.ts b/test/unit/VuexORM.spec.ts
new file mode 100644
index 00000000..9df31009
--- /dev/null
+++ b/test/unit/VuexORM.spec.ts
@@ -0,0 +1,76 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import VuexORM from '@/index'
+import Database from '@/database/Database'
+import Model from '@/model/Model'
+
+describe('unit/VuexORM', () => {
+ Vue.use(Vuex)
+
+ it('installs Vuex ORM to the store', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+ class Post extends Model {
+ static entity = 'posts'
+ }
+
+ const database = new Database()
+
+ database.register(User)
+ database.register(Post)
+
+ const store = new Vuex.Store({
+ plugins: [VuexORM.install(database)]
+ })
+
+ const expected = {
+ entities: {
+ $name: 'entities',
+ users: {
+ $name: 'users',
+ $connection: 'entities',
+ data: {}
+ },
+ posts: {
+ $name: 'posts',
+ $connection: 'entities',
+ data: {}
+ }
+ }
+ }
+
+ expect(store.state).toEqual(expected)
+ })
+
+ it('can customize the namespace', () => {
+ class User extends Model {
+ static entity = 'users'
+ }
+
+ const database = new Database()
+
+ database.register(User)
+
+ const store = new Vuex.Store({
+ plugins: [
+ VuexORM.install(database, {
+ namespace: 'database'
+ })
+ ]
+ })
+
+ const expected = {
+ database: {
+ $name: 'database',
+ users: {
+ $name: 'users',
+ $connection: 'database',
+ data: {}
+ }
+ }
+ }
+
+ expect(store.state).toEqual(expected)
+ })
+})
From 5f0c7db0c4031a080a2b328d32b6db47b06025f1 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Sun, 5 Apr 2020 00:22:49 +0100
Subject: [PATCH 10/56] feat(Attribute): add `hasOneThrough` relation type
(#614)
---
docs/guide/data/inserting-and-updating.md | 47 +-
docs/guide/model/relationships.md | 66 ++-
src/attributes/index.ts | 2 +
src/attributes/relations/HasOneThrough.ts | 151 +++++
src/index.cjs.ts | 2 +
src/index.ts | 3 +
src/model/Model.ts | 22 +
src/plugins/use.ts | 3 +
test/feature/relations/HasOneThrough.spec.ts | 551 ++++++++++++++++++
.../Retrieve_HasOneThrough.spec.ts | 76 +++
10 files changed, 885 insertions(+), 38 deletions(-)
create mode 100644 src/attributes/relations/HasOneThrough.ts
create mode 100644 test/feature/relations/HasOneThrough.spec.ts
create mode 100644 test/performance/Retrieve_HasOneThrough.spec.ts
diff --git a/docs/guide/data/inserting-and-updating.md b/docs/guide/data/inserting-and-updating.md
index b043b4a7..8938f576 100644
--- a/docs/guide/data/inserting-and-updating.md
+++ b/docs/guide/data/inserting-and-updating.md
@@ -595,7 +595,11 @@ User.insert({
}
```
-However, note that there is a caveat with "Has Many Through" relationship. When creating data that contains "Has Many Through" relationship without intermediate pivot records, the intermediate record will not be generated. Let's say you have the following model definitions.
+### Generating Intermediate Records
+
+When creating data that contains [Has One Through](../model/relationships.md#has-one-through) or [Has Many Through](../model/relationships.md#has-many-through) relations, intermediate records will not be generated without specifying supporting relations that allows Vuex ORM to normalize the data before persisting to the store.
+
+For example, let's take a look at the following `hasManyThrough` relation. The `Country` model can access many `Post` records through a `User` with the support of `hasMany` relations defined on `Country` and `User`.
```js
class Country extends Model {
@@ -634,42 +638,7 @@ class Post extends Model {
}
```
-And then you try to save the following data.
-
-```js
-Country.create({
- data: {
- id: 1,
- posts: [
- { id: 1 },
- { id: 2 }
- ]
- }
-})
-```
-
-Vuex ORM will normalize the data and save them to the store as below.
-
-```js
-{
- countries: {
- data: {
- 1: { id: 1 }
- }
- },
- users: {
- data: {}
- },
- posts: {
- data: {
- 1: { id: 1, user_id: null },
- 2: { id: 2, user_id: null }
- }
- }
-}
-```
-
-See there is no users record, and `user_id` at `posts` becomes empty. This happens because Vuex ORM wouldn't have any idea how post data relate to the intermediate User. Hence if you create data like this, you wouldn't be able to retrieve them by getters anymore. In such cases, it is recommended to create data with the intermediate records.
+By adding the `hasMany` relation attribute on both `Country` and `User`, the following data structure can generate records for all the models required for the `hasManyThrough` relation.
```js
Country.create({
@@ -693,6 +662,10 @@ Country.create({
})
```
+The `users` property will populate `User` model through the `users` attribute defined on the `Country` model. Subsequently, nesting `posts` within a user record will populate the `Post` model through the `posts` attribute defined on the `User` model, thus creating `Post` records. This is all made possible by strategically placing the relevant relations as demonstrated.
+
+The same principle applies to the `hasOneThrough` relation, since it is a 1:1 version of `hasManyThrough`, by replacing `hasMany` with `hasOne` relations.
+
### Get Newly Inserted Data
Both `insert` and `create` return the inserted data as a Promise so that you can get them as a return value. The return value will contain all of the data that was created.
diff --git a/docs/guide/model/relationships.md b/docs/guide/model/relationships.md
index a644619b..e686cd6b 100644
--- a/docs/guide/model/relationships.md
+++ b/docs/guide/model/relationships.md
@@ -434,6 +434,66 @@ user.podcasts.forEach((podcast) => {
})
```
+## Has One Through
+
+The "has-one-through" relationship links models through a single intermediate relation. For example, if each `User` has one `Profile`, and each `Profile` is associated with one `Image`, then the `User` may access `Image` through `Profile`. Let's look at the models required to define this relationship:
+
+```js
+class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+}
+
+class Profile extends Model {
+ static entity = 'profiles'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+}
+
+class Image extends Model {
+ static entity = 'images'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+}
+```
+
+Though `Image` does not contain a `user_id` attribute, the `hasOneThrough` relation can provide access to the user's profile image to the `User` model. Vuex ORM can accomplish this by inspecting the `user_id` on the intermediary model, in this case `Profile`, which then goes on to matching it with `Image` models it is associated with.
+
+The `hasOneThrough` relation attribute accepts the following arguments:
+
+```js
+this.hasOneThrough(
+ Image, // The final model we wish to access.
+ Profile, // The intermediate "through" model.
+ 'user_id', // Foreign key on the intermediate "through" model.
+ 'profile_id', // Foreign key on the final model.
+ 'local_user_id', // Optional: custom key on the intermediate "through" model.
+ 'local_profile_id' // Optional: custom key on the final model.
+)
+```
+
+::: tip
+When creating data for models containing a `hasOneThrough` relation, you will need to define supporting relations in order to generate intermediate records.
+
+**Further reading**: [Generating Intermediate Records](../data/inserting-and-updating.html#generating-intermediate-records)
+:::
+
## Has Many Through
The "has-many-through" relationship provides a convenient shortcut for accessing distant relations via an intermediate relation. For example, a Country might have many Posts through an intermediate User. In this example, you could easily gather all posts for a given country. Let's look at the models required to define this relationship:
@@ -490,7 +550,11 @@ this.hasManyThrough(
)
```
-> **NOTE:** When creating data that contains `hasManyThrough` relationship without intermediate relation, the intermediate record will not be generated. [See here](../data/inserting-and-updating.html#generating-pivot-records) for more details.
+::: tip
+When creating data for models containing a `hasManyThrough` relation, you will need to define supporting relations in order to generate intermediate records.
+
+**Further reading**: [Generating Intermediate Records](../data/inserting-and-updating.html#generating-intermediate-records)
+:::
## One To One (Polymorphic)
diff --git a/src/attributes/index.ts b/src/attributes/index.ts
index 0bd7ed89..fc70103d 100644
--- a/src/attributes/index.ts
+++ b/src/attributes/index.ts
@@ -10,6 +10,7 @@ import HasOne from './relations/HasOne'
import BelongsTo from './relations/BelongsTo'
import HasMany from './relations/HasMany'
import HasManyBy from './relations/HasManyBy'
+import HasOneThrough from './relations/HasOneThrough'
import HasManyThrough from './relations/HasManyThrough'
import BelongsToMany from './relations/BelongsToMany'
import MorphTo from './relations/MorphTo'
@@ -31,6 +32,7 @@ export {
BelongsTo,
HasMany,
HasManyBy,
+ HasOneThrough,
HasManyThrough,
BelongsToMany,
MorphTo,
diff --git a/src/attributes/relations/HasOneThrough.ts b/src/attributes/relations/HasOneThrough.ts
new file mode 100644
index 00000000..17547306
--- /dev/null
+++ b/src/attributes/relations/HasOneThrough.ts
@@ -0,0 +1,151 @@
+import { Schema as NormalizrSchema } from 'normalizr'
+import Schema from '../../schema/Schema'
+import { Record, Records, NormalizedData, Collection } from '../../data'
+import Model from '../../model/Model'
+import Query from '../../query/Query'
+import Constraint from '../../query/contracts/RelationshipConstraint'
+import Relation from './Relation'
+
+export type Entity = typeof Model | string
+
+export default class HasOneThrough extends Relation {
+ /**
+ * The related model.
+ */
+ related: typeof Model
+
+ /**
+ * The "through" parent model.
+ */
+ through: typeof Model
+
+ /**
+ * The near key on the relation.
+ */
+ firstKey: string
+
+ /**
+ * The far key on the relation.
+ */
+ secondKey: string
+
+ /**
+ * The local key on the relation.
+ */
+ localKey: string
+
+ /**
+ * The local key on the intermediary model.
+ */
+ secondLocalKey: string
+
+ /**
+ * Create a new relation instance.
+ */
+ constructor(
+ model: typeof Model,
+ related: Entity,
+ through: Entity,
+ firstKey: string,
+ secondKey: string,
+ localKey: string,
+ secondLocalKey: string
+ ) {
+ super(model) /* istanbul ignore next */
+
+ this.related = this.model.relation(related)
+ this.through = this.model.relation(through)
+ this.firstKey = firstKey
+ this.secondKey = secondKey
+ this.localKey = localKey
+ this.secondLocalKey = secondLocalKey
+ }
+
+ /**
+ * Define the normalizr schema for the relation.
+ */
+ define(schema: Schema): NormalizrSchema {
+ return schema.one(this.related)
+ }
+
+ /**
+ * Since the relation doesn't have a foreign key, there is no relational key
+ * to attach to the given data.
+ */
+ attach(_key: any, _record: Record, _data: NormalizedData): void {
+ return
+ }
+
+ /**
+ * Convert given value to the appropriate value for the attribute.
+ */
+ make(value: any, _parent: Record, _key: string): Model | null {
+ return this.makeOneRelation(value, this.related)
+ }
+
+ /**
+ * Load the relation for the given collection.
+ */
+ load(
+ query: Query,
+ collection: Collection,
+ name: string,
+ constraints: Constraint[]
+ ): void {
+ const relatedQuery = this.getRelation(
+ query,
+ this.related.entity,
+ constraints
+ )
+
+ const throughQuery = query.newQuery(this.through.entity)
+
+ this.addEagerConstraintForThrough(throughQuery, collection)
+
+ const through = throughQuery.get()
+
+ this.addEagerConstraintForRelated(relatedQuery, through)
+
+ const related = this.mapThroughRelations(through, relatedQuery)
+
+ collection.forEach((item) => {
+ const relation = related[item[this.localKey]]
+
+ item[name] = relation || null
+ })
+ }
+
+ /**
+ * Set the constraints for the "through" relation.
+ */
+ addEagerConstraintForThrough(query: Query, collection: Collection): void {
+ query.where(this.firstKey, this.getKeys(collection, this.localKey))
+ }
+
+ /**
+ * Set the constraints for the "related" relation.
+ */
+ addEagerConstraintForRelated(query: Query, collection: Collection): void {
+ query.where(this.secondKey, this.getKeys(collection, this.secondLocalKey))
+ }
+
+ /**
+ * Create a new indexed map for the "through" relation.
+ */
+ mapThroughRelations(through: Collection, relatedQuery: Query): Records {
+ const relations = this.mapSingleRelations(
+ relatedQuery.get(),
+ this.secondKey
+ )
+
+ return through.reduce((records, record) => {
+ const id = record[this.firstKey]
+
+ const related = relations.get(record[this.secondLocalKey])
+
+ records[id] = related || null
+
+ return records
+ }, {})
+ }
+}
diff --git a/src/index.cjs.ts b/src/index.cjs.ts
index 66ebfe54..c0159d6c 100644
--- a/src/index.cjs.ts
+++ b/src/index.cjs.ts
@@ -19,6 +19,7 @@ import BelongsTo from './attributes/relations/BelongsTo'
import HasMany from './attributes/relations/HasMany'
import HasManyBy from './attributes/relations/HasManyBy'
import BelongsToMany from './attributes/relations/BelongsToMany'
+import HasOneThrough from './attributes/relations/HasOneThrough'
import HasManyThrough from './attributes/relations/HasManyThrough'
import MorphTo from './attributes/relations/MorphTo'
import MorphOne from './attributes/relations/MorphOne'
@@ -51,6 +52,7 @@ export default {
HasMany,
HasManyBy,
BelongsToMany,
+ HasOneThrough,
HasManyThrough,
MorphTo,
MorphOne,
diff --git a/src/index.ts b/src/index.ts
index 953d7d8a..bcc101f0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -20,6 +20,7 @@ import BelongsTo from './attributes/relations/BelongsTo'
import HasMany from './attributes/relations/HasMany'
import HasManyBy from './attributes/relations/HasManyBy'
import BelongsToMany from './attributes/relations/BelongsToMany'
+import HasOneThrough from './attributes/relations/HasOneThrough'
import HasManyThrough from './attributes/relations/HasManyThrough'
import MorphTo from './attributes/relations/MorphTo'
import MorphOne from './attributes/relations/MorphOne'
@@ -65,6 +66,7 @@ export {
HasMany,
HasManyBy,
BelongsToMany,
+ HasOneThrough,
HasManyThrough,
MorphTo,
MorphOne,
@@ -109,6 +111,7 @@ export default {
HasMany,
HasManyBy,
BelongsToMany,
+ HasOneThrough,
HasManyThrough,
MorphTo,
MorphOne,
diff --git a/src/model/Model.ts b/src/model/Model.ts
index c343c3d2..0385ebfb 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -195,6 +195,28 @@ export default class Model {
)
}
+ /**
+ * Create a has one through relationship.
+ */
+ static hasOneThrough(
+ related: typeof Model | string,
+ through: typeof Model | string,
+ firstKey: string,
+ secondKey: string,
+ localKey?: string,
+ secondLocalKey?: string
+ ): Attributes.HasOneThrough {
+ return new Attributes.HasOneThrough(
+ this,
+ related,
+ through,
+ firstKey,
+ secondKey,
+ this.localKey(localKey),
+ this.relation(through).localKey(secondLocalKey)
+ )
+ }
+
/**
* Create a has many through relationship.
*/
diff --git a/src/plugins/use.ts b/src/plugins/use.ts
index f8bbef26..8058c976 100644
--- a/src/plugins/use.ts
+++ b/src/plugins/use.ts
@@ -13,6 +13,7 @@ import BelongsTo from '../attributes/relations/BelongsTo'
import HasMany from '../attributes/relations/HasMany'
import HasManyBy from '../attributes/relations/HasManyBy'
import BelongsToMany from '../attributes/relations/BelongsToMany'
+import HasOneThrough from '../attributes/relations/HasOneThrough'
import HasManyThrough from '../attributes/relations/HasManyThrough'
import MorphTo from '../attributes/relations/MorphTo'
import MorphOne from '../attributes/relations/MorphOne'
@@ -48,6 +49,7 @@ export interface PluginComponents {
HasMany: typeof HasMany
HasManyBy: typeof HasManyBy
BelongsToMany: typeof BelongsToMany
+ HasOneThrough: typeof HasOneThrough
HasManyThrough: typeof HasManyThrough
MorphTo: typeof MorphTo
MorphOne: typeof MorphOne
@@ -90,6 +92,7 @@ export function use(plugin: Plugin, options: Options = {}): void {
HasMany,
HasManyBy,
BelongsToMany,
+ HasOneThrough,
HasManyThrough,
MorphTo,
MorphOne,
diff --git a/test/feature/relations/HasOneThrough.spec.ts b/test/feature/relations/HasOneThrough.spec.ts
new file mode 100644
index 00000000..89831179
--- /dev/null
+++ b/test/feature/relations/HasOneThrough.spec.ts
@@ -0,0 +1,551 @@
+import { createStore, createState } from 'test/support/Helpers'
+import Model from '@/model/Model'
+
+describe('Features – Relations – Has One Through', () => {
+ it('can create entities containing the relation', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute()
+ id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ const store = createStore([
+ { model: User },
+ { model: Profile },
+ { model: Image }
+ ])
+
+ await User.insert({
+ id: 1,
+ image: { id: 1 }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, image: null }
+ },
+ images: {
+ 1: { $id: '1', id: 1, profile_id: null }
+ },
+ profiles: {}
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can resolve the relation', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute()
+ id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert([{ id: 1 }, { id: 2 }])
+
+ await Profile.insert([
+ { id: 3, user_id: 1 },
+ { id: 4, user_id: 2 }
+ ])
+
+ await Image.insert([
+ { id: 5, profile_id: 3 },
+ { id: 6, profile_id: 4 }
+ ])
+
+ const user = User.query()
+ .with('image')
+ .find(1) as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.id).toBe(1)
+ expect(user.image).toBeInstanceOf(Image)
+ expect(user.image.profile_id).toBe(3)
+ expect(user.image.id).toBe(5)
+ })
+
+ it('can resolve the relation with string value id', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Str('')
+ id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.string(''),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Str('')
+ id!: number
+
+ // @Str('')
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.string(''),
+ user_id: this.string('')
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Str('')
+ id!: number
+
+ // @Str('')
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.string(''),
+ profile_id: this.string('')
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert([{ id: 'string-id-1' }, { id: 'string-id-2' }])
+
+ await Profile.insert([
+ { id: 'string-id-3', user_id: 'string-id-1' },
+ { id: 'string-id-4', user_id: 'string-id-2' }
+ ])
+
+ await Image.insert([
+ { id: 'string-id-5', profile_id: 'string-id-3' },
+ { id: 'string-id-6', profile_id: 'string-id-4' }
+ ])
+
+ const user = User.query()
+ .with('image')
+ .find('string-id-1') as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.id).toBe('string-id-1')
+ expect(user.image).toBeInstanceOf(Image)
+ expect(user.image.profile_id).toBe('string-id-3')
+ expect(user.image.id).toBe('string-id-5')
+ })
+
+ it('can resolve the relation when the intermediate entity is empty', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute()
+ id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert([{ id: 1 }])
+
+ const user = User.query()
+ .with('image')
+ .find(1) as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.id).toBe(1)
+ expect(user.image).toBeNull()
+ })
+
+ it('can resolve the relation when the target entity is empty', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute()
+ id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert({ id: 1 })
+
+ await Profile.insert({
+ id: 1,
+ user_id: 1
+ })
+
+ const user = User.query()
+ .with('image')
+ .find(1) as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.id).toBe(1)
+ expect(user.image).toBeNull()
+ })
+
+ it('can resolve the relation with custom primary keys', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static primaryKey = 'u_id'
+
+ // @Attribute()
+ u_id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ image!: Image
+
+ static fields() {
+ return {
+ u_id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ static primaryKey = 'p_id'
+
+ // @Attribute()
+ p_id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ p_id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ static primaryKey = 'i_id'
+
+ // @Attribute()
+ i_id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ i_id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert([{ u_id: 1 }, { u_id: 2 }])
+
+ await Profile.insert([
+ { p_id: 3, user_id: 1 },
+ { p_id: 4, user_id: 2 }
+ ])
+
+ await Image.insert([
+ { i_id: 5, profile_id: 3 },
+ { i_id: 6, profile_id: 4 }
+ ])
+
+ const user = User.query()
+ .with('image')
+ .find(1) as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.u_id).toBe(1)
+ expect(user.image).toBeInstanceOf(Image)
+ expect(user.image.profile_id).toBe(3)
+ expect(user.image.i_id).toBe(5)
+ })
+
+ it('can resolve the relation with custom local keys', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ u_id!: number
+
+ // @HasOneThrough(Image, Profile, 'user_id', 'profile_id', 'u_id', 'p_id')
+ image!: Image
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ u_id: this.attr(null),
+ image: this.hasOneThrough(
+ Image,
+ Profile,
+ 'user_id',
+ 'profile_id',
+ 'u_id',
+ 'p_id'
+ )
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ p_id!: number
+
+ // @Attribute()
+ user_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ p_id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ // @Attribute()
+ id!: number
+
+ // @Attribute()
+ i_id!: number
+
+ // @Attribute()
+ profile_id!: number
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ i_id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ createStore([{ model: User }, { model: Profile }, { model: Image }])
+
+ await User.insert([
+ { id: 11, u_id: 1 },
+ { id: 12, u_id: 2 }
+ ])
+
+ await Profile.insert([
+ { id: 13, p_id: 3, user_id: 1 },
+ { id: 14, p_id: 4, user_id: 2 }
+ ])
+
+ await Image.insert([
+ { id: 15, i_id: 5, profile_id: 3 },
+ { id: 16, i_id: 6, profile_id: 4 }
+ ])
+
+ const user = User.query()
+ .with('image')
+ .find(11) as User
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.id).toBe(11)
+ expect(user.image).toBeInstanceOf(Image)
+ expect(user.image.profile_id).toBe(3)
+ expect(user.image.id).toBe(15)
+ })
+})
diff --git a/test/performance/Retrieve_HasOneThrough.spec.ts b/test/performance/Retrieve_HasOneThrough.spec.ts
new file mode 100644
index 00000000..22879cad
--- /dev/null
+++ b/test/performance/Retrieve_HasOneThrough.spec.ts
@@ -0,0 +1,76 @@
+import { createStore } from 'test/support/Helpers'
+import Model from '@/model/Model'
+
+describe('Performance – Retrieve – Has One Through', () => {
+ it('should retrieve relation in time', async () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ image: this.hasOneThrough(Image, Profile, 'user_id', 'profile_id')
+ }
+ }
+ }
+
+ class Profile extends Model {
+ static entity = 'profiles'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ user_id: this.attr(null)
+ }
+ }
+ }
+
+ class Image extends Model {
+ static entity = 'images'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ profile_id: this.attr(null)
+ }
+ }
+ }
+
+ const users = []
+ const profiles = []
+ const images = []
+
+ for (let i = 1; i <= 1000; i++) {
+ users.push({ id: i })
+ }
+
+ for (let i = 1; i <= 1000; i++) {
+ profiles.push({ id: i, user_id: i })
+ }
+
+ for (let i = 1; i <= 1000; i++) {
+ images.push({ id: i, profile_id: i })
+ }
+
+ const store = createStore([
+ { model: User },
+ { model: Profile },
+ { model: Image }
+ ])
+
+ await store.dispatch('entities/users/create', { data: users })
+ await store.dispatch('entities/profiles/create', { data: profiles })
+ await store.dispatch('entities/images/create', { data: images })
+
+ const start = +new Date()
+
+ store.getters['entities/users/query']()
+ .with('image')
+ .get()
+
+ const end = +new Date()
+
+ expect(end - start).toBeLessThan(300)
+ console.info('\x1b[2m%s\x1b[0m', ` -- The test took ${end - start}ms`)
+ })
+})
From aeac77fbf2e283c7839d21771ddc83a37449061e Mon Sep 17 00:00:00 2001
From: Kia King Ishii
Date: Sun, 5 Apr 2020 14:26:22 +0900
Subject: [PATCH 11/56] test: add inserts new tests (#616)
---
src/model/Model.ts | 2 +-
test/feature/basics/New.spec.ts | 46 -----------------
.../feature/models/static_inserts_new.spec.ts | 50 +++++++++++++++++++
test/feature/modules/api_inserts_new.spec.ts | 50 +++++++++++++++++++
test/feature/query/inserts_new.spec.ts | 50 +++++++++++++++++++
test/feature/repositories/Crud_New.spec.ts | 29 -----------
6 files changed, 151 insertions(+), 76 deletions(-)
delete mode 100644 test/feature/basics/New.spec.ts
create mode 100644 test/feature/models/static_inserts_new.spec.ts
create mode 100644 test/feature/modules/api_inserts_new.spec.ts
create mode 100644 test/feature/query/inserts_new.spec.ts
delete mode 100644 test/feature/repositories/Crud_New.spec.ts
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 0385ebfb..ccfb2f84 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -473,7 +473,7 @@ export default class Model {
/**
* Create new data with all fields filled by default values.
*/
- static new(): Promise {
+ static new(this: T): Promise> {
return this.dispatch('new')
}
diff --git a/test/feature/basics/New.spec.ts b/test/feature/basics/New.spec.ts
deleted file mode 100644
index 843852a4..00000000
--- a/test/feature/basics/New.spec.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { createStore } from 'test/support/Helpers'
-import Model from '@/model/Model'
-
-describe('Feature – Basics – New', () => {
- class User extends Model {
- static entity = 'users'
-
- // @Uid
- id!: string
-
- // @Str('Default Doe')
- name!: string
-
- static fields() {
- return {
- id: this.uid(),
- name: this.attr('Default Doe')
- }
- }
- }
-
- it('can create new data with all fields filled by default values', async () => {
- const store = createStore([{ model: User }])
-
- await User.new()
- await User.new()
-
- expect(store.state.entities.users.data.$uid1.$id).toBe('$uid1')
- expect(store.state.entities.users.data.$uid1.id).toBe('$uid1')
- expect(store.state.entities.users.data.$uid1.name).toBe('Default Doe')
-
- expect(store.state.entities.users.data.$uid2.$id).toBe('$uid2')
- expect(store.state.entities.users.data.$uid2.id).toBe('$uid2')
- expect(store.state.entities.users.data.$uid2.name).toBe('Default Doe')
- })
-
- it('returns newly created instance', async () => {
- createStore([{ model: User }])
-
- const user = (await User.new()) as User
-
- expect(user.$id).toBe('$uid3')
- expect(user.id).toBe('$uid3')
- expect(user.name).toBe('Default Doe')
- })
-})
diff --git a/test/feature/models/static_inserts_new.spec.ts b/test/feature/models/static_inserts_new.spec.ts
new file mode 100644
index 00000000..1270857d
--- /dev/null
+++ b/test/feature/models/static_inserts_new.spec.ts
@@ -0,0 +1,50 @@
+import { createStore, createState } from 'test/support/Helpers'
+import Uid from '@/support/Uid'
+import { Model } from '@/index'
+
+describe('feature/query/inserts_new', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.uid(),
+ name: this.attr('John Doe')
+ }
+ }
+
+ id!: string
+ name!: string
+ }
+
+ beforeEach(() => {
+ Uid.reset()
+ })
+
+ it('can create new data with all fields filled by default values', async () => {
+ const store = createStore([User])
+
+ await User.new()
+ await User.new()
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' },
+ $uid2: { $id: '$uid2', id: '$uid2', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns a newly created model', async () => {
+ createStore([User])
+
+ const user = await User.new()
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.$id).toBe('$uid1')
+ expect(user.id).toBe('$uid1')
+ expect(user.name).toBe('John Doe')
+ })
+})
diff --git a/test/feature/modules/api_inserts_new.spec.ts b/test/feature/modules/api_inserts_new.spec.ts
new file mode 100644
index 00000000..fe91042a
--- /dev/null
+++ b/test/feature/modules/api_inserts_new.spec.ts
@@ -0,0 +1,50 @@
+import { createStore, createState } from 'test/support/Helpers'
+import Uid from '@/support/Uid'
+import { Model } from '@/index'
+
+describe('feature/modules/api_inserts_new', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.uid(),
+ name: this.attr('John Doe')
+ }
+ }
+
+ id!: string
+ name!: string
+ }
+
+ beforeEach(() => {
+ Uid.reset()
+ })
+
+ it('can create new data with all fields filled by default values', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/new')
+ await store.dispatch('entities/users/new')
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' },
+ $uid2: { $id: '$uid2', id: '$uid2', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns a newly created model', async () => {
+ const store = createStore([User])
+
+ const user = await store.dispatch('entities/users/new')
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.$id).toBe('$uid1')
+ expect(user.id).toBe('$uid1')
+ expect(user.name).toBe('John Doe')
+ })
+})
diff --git a/test/feature/query/inserts_new.spec.ts b/test/feature/query/inserts_new.spec.ts
new file mode 100644
index 00000000..6b88da7d
--- /dev/null
+++ b/test/feature/query/inserts_new.spec.ts
@@ -0,0 +1,50 @@
+import { createStore, createState } from 'test/support/Helpers'
+import Uid from '@/support/Uid'
+import { Model } from '@/index'
+
+describe('feature/models/static_inserts_new', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.uid(),
+ name: this.attr('John Doe')
+ }
+ }
+
+ id!: string
+ name!: string
+ }
+
+ beforeEach(() => {
+ Uid.reset()
+ })
+
+ it('can create new data with all fields filled by default values', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).new()
+ await store.$repo(User).new()
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' },
+ $uid2: { $id: '$uid2', id: '$uid2', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns a newly created model', async () => {
+ const store = createStore([User])
+
+ const user = await store.$repo(User).new()
+
+ expect(user).toBeInstanceOf(User)
+ expect(user.$id).toBe('$uid1')
+ expect(user.id).toBe('$uid1')
+ expect(user.name).toBe('John Doe')
+ })
+})
diff --git a/test/feature/repositories/Crud_New.spec.ts b/test/feature/repositories/Crud_New.spec.ts
deleted file mode 100644
index 2d86f5d3..00000000
--- a/test/feature/repositories/Crud_New.spec.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { createStore, createState } from 'test/support/Helpers'
-import { Model } from '@/index'
-
-describe('Feature - Repositories - CRUD New', () => {
- it('can insert a new record to the store', async () => {
- class User extends Model {
- static entity = 'users'
-
- static fields() {
- return {
- id: this.uid(),
- name: this.string('John Doe')
- }
- }
- }
-
- const store = createStore([User])
-
- await store.$repo(User).new()
-
- const expected = createState({
- users: {
- $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
- }
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-})
From baf2b473cd07a690dea57afd8b09981b4e333b5e Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Mon, 6 Apr 2020 15:57:40 +0100
Subject: [PATCH 12/56] feat(Repository): migrate new persist options syntax
(#617)
Co-authored-by: Kia Ishii
---
src/model/Model.ts | 30 ++--
src/model/support/Payloads.ts | 39 +++++
src/query/Query.ts | 31 ++--
src/repository/Repository.ts | 44 +++--
src/repository/support/Payloads.ts | 39 +++++
test/feature/basics/Create.spec.ts | 156 -----------------
test/feature/basics/Insert.spec.ts | 63 -------
.../models/static_inserts_create.spec.ts | 102 +++++++++++
.../models/static_inserts_insert.spec.ts | 103 +++++++++++
.../modules/api_inserts_create.spec.ts | 95 +++++++++++
.../modules/api_inserts_insert.spec.ts | 96 +++++++++++
test/feature/query/inserts_create.spec.ts | 160 ++++++++++++++++++
test/feature/query/inserts_insert.spec.ts | 160 ++++++++++++++++++
test/feature/repositories/Crud_Create.spec.ts | 31 ----
test/feature/repositories/Crud_Insert.spec.ts | 31 ----
test/support/Helpers.ts | 32 +++-
16 files changed, 888 insertions(+), 324 deletions(-)
create mode 100644 src/model/support/Payloads.ts
create mode 100644 src/repository/support/Payloads.ts
delete mode 100644 test/feature/basics/Create.spec.ts
delete mode 100644 test/feature/basics/Insert.spec.ts
create mode 100644 test/feature/models/static_inserts_create.spec.ts
create mode 100644 test/feature/models/static_inserts_insert.spec.ts
create mode 100644 test/feature/modules/api_inserts_create.spec.ts
create mode 100644 test/feature/modules/api_inserts_insert.spec.ts
create mode 100644 test/feature/query/inserts_create.spec.ts
create mode 100644 test/feature/query/inserts_insert.spec.ts
delete mode 100644 test/feature/repositories/Crud_Create.spec.ts
delete mode 100644 test/feature/repositories/Crud_Insert.spec.ts
diff --git a/src/model/Model.ts b/src/model/Model.ts
index ccfb2f84..71798d55 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -22,6 +22,8 @@ import ModelState from './contracts/State'
import InheritanceTypes from './contracts/InheritanceTypes'
import { toAttributes, toJson } from './Serialize'
import PayloadBuilder from '../modules/support/PayloadBuilder'
+import { PersistOptions as QueryPersistOptions } from '../query/options'
+import { InsertObject, normalizeInsertPayload } from './support/Payloads'
export default class Model {
/**
@@ -459,8 +461,8 @@ export default class Model {
/**
* Get query instance.
*/
- static query(this: T): Query> {
- return this.getters('query')()
+ static query(this: M): Query> {
+ return new Query(this.store(), this.entity)
}
/**
@@ -474,7 +476,7 @@ export default class Model {
* Create new data with all fields filled by default values.
*/
static new(this: T): Promise> {
- return this.dispatch('new')
+ return this.query().new()
}
/**
@@ -482,23 +484,25 @@ export default class Model {
* store. If you want to save data without replacing existing records,
* use the `insert` method instead.
*/
- static create(
- this: T,
- payload: Payloads.Create,
- options?: PersistOptions.Create
+ static create(
+ data: Record | Record[] | InsertObject,
+ options?: QueryPersistOptions
): Promise {
- return this.dispatch('create', PayloadBuilder.normalize(payload, options))
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().create(d, o)
}
/**
* Insert records.
*/
- static insert(
- this: T,
- payload: Payloads.Insert,
- options?: PersistOptions.Insert
+ static insert(
+ data: Record | Record[] | InsertObject,
+ options?: QueryPersistOptions
): Promise {
- return this.dispatch('insert', PayloadBuilder.normalize(payload, options))
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().insert(d, o)
}
/**
diff --git a/src/model/support/Payloads.ts b/src/model/support/Payloads.ts
new file mode 100644
index 00000000..69332c76
--- /dev/null
+++ b/src/model/support/Payloads.ts
@@ -0,0 +1,39 @@
+import { isArray } from '../../support/Utils'
+import { Record } from '../../data'
+import { PersistOptions } from '../../query/options'
+
+export interface InsertObject extends PersistOptions {
+ data: Record | Record[]
+}
+
+export interface InsertPayload {
+ data: Record | Record[]
+ options?: PersistOptions
+}
+
+/**
+ * Normalize the payload arguments for persist methods. It's required for
+ * backward compatibility for the new persist method argument structure.
+ * It may be deprecated and be removed in the future.
+ */
+export function normalizeInsertPayload(
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
+): InsertPayload {
+ // If the data is an array, then the data should be an array of data.
+ // Therefore the whole payload should be passed directly as `data`.
+ if (isArray(data)) {
+ return { data, options }
+ }
+
+ // If the data doesn't have a `data` property, it can be assumed that the
+ // user has passed an object as the payload. Therefore the entire payload
+ // should be declared as `data`.
+ if (data.data === undefined) {
+ return { data, options }
+ }
+
+ // If the data contains `data` property, we should extract it and pass that
+ // property as `data`.
+ return { data: data.data, options: data }
+}
diff --git a/src/query/Query.ts b/src/query/Query.ts
index e873f626..7add3be0 100644
--- a/src/query/Query.ts
+++ b/src/query/Query.ts
@@ -795,7 +795,7 @@ export default class Query {
/**
* Create new data with all fields filled by default values.
*/
- new(): T {
+ async new(): Promise {
const model = new this.model().$generateId() as T
this.commitInsert(model.$getAttributes())
@@ -810,8 +810,8 @@ export default class Query {
*/
create(
data: Data.Record | Data.Record[],
- options: Options.PersistOptions
- ): Data.Collections {
+ options?: Options.PersistOptions
+ ): Promise {
return this.persist('create', data, options)
}
@@ -831,8 +831,8 @@ export default class Query {
*/
insert(
data: Data.Record | Data.Record[],
- options: Options.PersistOptions
- ): Data.Collections {
+ options?: Options.PersistOptions
+ ): Promise {
return this.persist('insert', data, options)
}
@@ -858,7 +858,10 @@ export default class Query {
data: Data.Record | Data.Record[] | UpdateClosure,
condition: UpdateCondition,
options: Options.PersistOptions
- ): Data.Item | Data.Collection | Data.Collections {
+ ):
+ | Promise>
+ | Promise>
+ | Promise {
// If the data is array, simply normalize the data and update them.
if (Utils.isArray(data)) {
return this.persist('update', data, options)
@@ -925,10 +928,10 @@ export default class Query {
/**
* Update the state by id.
*/
- updateById(
+ async updateById(
data: Data.Record | UpdateClosure,
id: string | number
- ): Data.Item {
+ ): Promise> {
id = typeof id === 'number' ? id.toString() : this.normalizeIndexId(id)
const record = this.state.data[id]
@@ -951,10 +954,10 @@ export default class Query {
/**
* Update the state by condition.
*/
- updateByCondition(
+ async updateByCondition(
data: Data.Record | UpdateClosure,
condition: Contracts.Predicate
- ): Data.Collection {
+ ): Promise> {
const instances = Object.keys(this.state.data).reduce>(
(instances, id) => {
const instance = this.hydrate(this.state.data[id])
@@ -1066,7 +1069,7 @@ export default class Query {
insertOrUpdate(
data: Data.Record | Data.Record[],
options: Options.PersistOptions
- ): Data.Collections {
+ ): Promise {
return this.persist('insertOrUpdate', data, options)
}
@@ -1098,11 +1101,11 @@ export default class Query {
/**
* Persist data into the state while preserving it's original structure.
*/
- persist(
+ async persist(
method: Options.PersistMethods,
data: Data.Record | Data.Record[],
- options: Options.PersistOptions
- ): Data.Collections {
+ options: Options.PersistOptions = {}
+ ): Promise {
const clonedData = Utils.cloneDeep(data)
const normalizedData = this.normalize(clonedData)
diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts
index 6c34c6bc..9f81ab90 100644
--- a/src/repository/Repository.ts
+++ b/src/repository/Repository.ts
@@ -4,8 +4,11 @@ import Database from '../database/Database'
import { Record, Item, Collection, Collections } from '../data'
import Model from '../model/Model'
import * as Payloads from '../modules/payloads/Actions'
+import PayloadBuilder from '../modules/support/PayloadBuilder'
import Query from '../query/Query'
import Predicate from '../query/contracts/Predicate'
+import { PersistOptions } from '../query/options'
+import { InsertObject, normalizeInsertPayload } from './support/Payloads'
interface ConstructorOf extends BaseConstructorOf {
entity: string
@@ -56,7 +59,7 @@ export default class Repository {
}
/**
- * Call Vuex Getetrs.
+ * Call Vuex Getters.
*/
getters(method: string): any {
return this.store.getters[this.namespace(method)]
@@ -101,7 +104,7 @@ export default class Repository {
* Get query instance.
*/
query(): Query {
- return this.getters('query')()
+ return new Query(this.store, this.model.entity)
}
/**
@@ -115,7 +118,7 @@ export default class Repository {
* Create new data with all fields filled by default values.
*/
new(): Promise {
- return this.dispatch('new')
+ return this.query().new()
}
/**
@@ -123,29 +126,48 @@ export default class Repository {
* store. If you want to save data without replacing existing records,
* use the `insert` method instead.
*/
- create(payload: Payloads.Create): Promise {
- return this.dispatch('create', payload)
+ create(
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
+ ): Promise {
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().create(d, o)
}
/**
* Insert records.
*/
- insert(payload: Payloads.Insert): Promise {
- return this.dispatch('insert', payload)
+ insert(
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
+ ): Promise {
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().insert(d, o)
}
/**
* Update records.
*/
- update(payload: Payloads.Update): Promise {
- return this.dispatch('update', payload)
+ update(
+ payload: Payloads.Update,
+ options?: PersistOptions
+ ): Promise {
+ return this.dispatch('update', PayloadBuilder.normalize(payload, options))
}
/**
* Insert or update records.
*/
- insertOrUpdate(payload: Payloads.InsertOrUpdate): Promise {
- return this.dispatch('insertOrUpdate', payload)
+ insertOrUpdate(
+ payload: Payloads.InsertOrUpdate,
+ options?: PersistOptions
+ ): Promise {
+ return this.dispatch(
+ 'insertOrUpdate',
+ PayloadBuilder.normalize(payload, options)
+ )
}
/**
diff --git a/src/repository/support/Payloads.ts b/src/repository/support/Payloads.ts
new file mode 100644
index 00000000..69332c76
--- /dev/null
+++ b/src/repository/support/Payloads.ts
@@ -0,0 +1,39 @@
+import { isArray } from '../../support/Utils'
+import { Record } from '../../data'
+import { PersistOptions } from '../../query/options'
+
+export interface InsertObject extends PersistOptions {
+ data: Record | Record[]
+}
+
+export interface InsertPayload {
+ data: Record | Record[]
+ options?: PersistOptions
+}
+
+/**
+ * Normalize the payload arguments for persist methods. It's required for
+ * backward compatibility for the new persist method argument structure.
+ * It may be deprecated and be removed in the future.
+ */
+export function normalizeInsertPayload(
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
+): InsertPayload {
+ // If the data is an array, then the data should be an array of data.
+ // Therefore the whole payload should be passed directly as `data`.
+ if (isArray(data)) {
+ return { data, options }
+ }
+
+ // If the data doesn't have a `data` property, it can be assumed that the
+ // user has passed an object as the payload. Therefore the entire payload
+ // should be declared as `data`.
+ if (data.data === undefined) {
+ return { data, options }
+ }
+
+ // If the data contains `data` property, we should extract it and pass that
+ // property as `data`.
+ return { data: data.data, options: data }
+}
diff --git a/test/feature/basics/Create.spec.ts b/test/feature/basics/Create.spec.ts
deleted file mode 100644
index 17024030..00000000
--- a/test/feature/basics/Create.spec.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import { createStore } from 'test/support/Helpers'
-import Model from '@/model/Model'
-
-describe('Feature – Basics – Create', () => {
- class User extends Model {
- static entity = 'users'
-
- static fields() {
- return {
- id: this.attr(null),
- name: this.attr('JD')
- }
- }
- }
-
- it('can create a record', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: { id: 1, name: 'John Doe' }
- })
-
- const expected = {
- 1: { $id: '1', id: 1, name: 'John Doe' }
- }
-
- expect(store.state.entities.users.data[1]).not.toBeInstanceOf(User)
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('can create a list of records', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
-
- const expected = {
- 1: { $id: '1', id: 1, name: 'John Doe' },
- 2: { $id: '2', id: 2, name: 'Jane Doe' }
- }
-
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('replaces any existing records', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: { id: 1, name: 'John Doe' }
- })
-
- await store.dispatch('entities/users/create', {
- data: { id: 2, name: 'Jane Doe' }
- })
-
- const expected = {
- 2: { $id: '2', id: 2, name: 'Jane Doe' }
- }
-
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('cleans all existing records when passing empty object', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: { id: 1, name: 'John Doe' }
- })
-
- await store.dispatch('entities/users/create', {
- data: {}
- })
-
- const expected = {}
-
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('cleans all existing records when passing empty array', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: { id: 1, name: 'John Doe' }
- })
-
- await store.dispatch('entities/users/create', {
- data: []
- })
-
- const expected = {}
-
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('fills missing fields with the default value', async () => {
- const store = createStore([{ model: User }])
-
- await store.dispatch('entities/users/create', {
- data: { id: 1 }
- })
-
- const expected = {
- 1: { $id: '1', id: 1, name: 'JD' }
- }
-
- expect(store.state.entities.users.data).toEqual(expected)
- })
-
- it('returns a newly created record', async () => {
- const store = createStore([{ model: User }])
-
- const collection = await store.dispatch('entities/users/create', {
- data: { id: 1, name: 'John Doe' }
- })
-
- const expected = {
- users: [new User({ $id: '1', id: 1, name: 'John Doe' })]
- }
-
- expect(collection).toEqual(expected)
- })
-
- it('returns list of newly created record', async () => {
- const store = createStore([{ model: User }])
-
- const collection = await store.dispatch('entities/users/create', {
- data: [
- { id: 1, name: 'John Doe' },
- { id: 2, name: 'Jane Doe' }
- ]
- })
-
- const expected = {
- users: [
- new User({ $id: '1', id: 1, name: 'John Doe' }),
- new User({ $id: '2', id: 2, name: 'Jane Doe' })
- ]
- }
-
- expect(collection).toEqual(expected)
- })
-
- it('returns null when creating an empty record', async () => {
- const store = createStore([{ model: User }])
-
- const collection = await store.dispatch('entities/users/create', {
- data: {}
- })
-
- expect(collection).toEqual({})
- })
-})
diff --git a/test/feature/basics/Insert.spec.ts b/test/feature/basics/Insert.spec.ts
deleted file mode 100644
index 8d5db833..00000000
--- a/test/feature/basics/Insert.spec.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { createStore, createState } from 'test/support/Helpers'
-import Model from '@/model/Model'
-
-describe('Feature – Basics – Insert', () => {
- class User extends Model {
- static entity = 'users'
-
- static fields() {
- return {
- id: this.attr(null),
- name: this.string('John Doe')
- }
- }
- }
-
- const getStore = () => createStore([{ model: User }])
-
- it('can insert a record', async () => {
- const store = getStore()
-
- await store.dispatch('entities/users/insert', {
- data: { id: 1, name: 'John Doe' }
- })
-
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, name: 'John Doe' }
- }
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-
- it('does nothing if an empty object is passed', async () => {
- const store = getStore()
-
- await store.dispatch('entities/users/insert', {
- data: {}
- })
-
- const expected = createState({
- users: {}
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-
- it('can insert record with primary key value of `null`', async () => {
- const store = getStore()
-
- await store.dispatch('entities/users/insert', {
- data: { id: null, name: 'John Doe' }
- })
-
- const expected = createState({
- users: {
- $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
- }
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-})
diff --git a/test/feature/models/static_inserts_create.spec.ts b/test/feature/models/static_inserts_create.spec.ts
new file mode 100644
index 00000000..1e947c6b
--- /dev/null
+++ b/test/feature/models/static_inserts_create.spec.ts
@@ -0,0 +1,102 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('feature/models/static_inserts_create', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ it('can create a record', async () => {
+ const store = createStore([User])
+
+ await User.create({ id: 1, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can create multiple records', async () => {
+ const store = createStore([User])
+
+ await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('replaces any existing records', async () => {
+ const store = createStore([User])
+
+ await User.create({ id: 1, name: 'John Doe' })
+ await User.create({ id: 2, name: 'Jane Doe' })
+
+ const expected = createState({
+ users: {
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ createStore([User])
+
+ const result = await User.create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+
+ // Test for deprecated payload API syntax.
+ it('accepts the "payload" object as an argument', async () => {
+ const store = createStore([User])
+
+ await User.create({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/models/static_inserts_insert.spec.ts b/test/feature/models/static_inserts_insert.spec.ts
new file mode 100644
index 00000000..90e7ee0a
--- /dev/null
+++ b/test/feature/models/static_inserts_insert.spec.ts
@@ -0,0 +1,103 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('feature/models/static_inserts_insert', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ it('can insert a record', async () => {
+ const store = createStore([User])
+
+ await User.insert({ id: 1, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert multiple records', async () => {
+ const store = createStore([User])
+
+ await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('keeps existing records', async () => {
+ const store = createStore([User])
+
+ await User.insert({ id: 1, name: 'John Doe' })
+ await User.insert({ id: 2, name: 'Jane Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ createStore([User])
+
+ const result = await User.insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+
+ // Test for deprecated payload API syntax.
+ it('accepts the "payload" object as an argument', async () => {
+ const store = createStore([User])
+
+ await User.insert({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/modules/api_inserts_create.spec.ts b/test/feature/modules/api_inserts_create.spec.ts
new file mode 100644
index 00000000..fd9ea8e8
--- /dev/null
+++ b/test/feature/modules/api_inserts_create.spec.ts
@@ -0,0 +1,95 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('feature/modules/api_inserts_create', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ it('can create a record', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/create', {
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can create multiple records', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/create', {
+ data: [
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ]
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('replaces any existing records', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/create', {
+ data: { id: 1, name: 'John Doe' }
+ })
+ await store.dispatch('entities/users/create', {
+ data: { id: 2, name: 'Jane Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ const store = createStore([User])
+
+ const result = await store.dispatch('entities/users/create', {
+ data: [
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ]
+ })
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+})
diff --git a/test/feature/modules/api_inserts_insert.spec.ts b/test/feature/modules/api_inserts_insert.spec.ts
new file mode 100644
index 00000000..06645906
--- /dev/null
+++ b/test/feature/modules/api_inserts_insert.spec.ts
@@ -0,0 +1,96 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import { Model } from '@/index'
+
+describe('feature/modules/inserts_insert', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('')
+ }
+ }
+ }
+
+ it('can insert a record', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/insert', {
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert multiple records', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/insert', {
+ data: [
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ]
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('keeps existing records', async () => {
+ const store = createStore([User])
+
+ await store.dispatch('entities/users/insert', {
+ data: { id: 1, name: 'John Doe' }
+ })
+ await store.dispatch('entities/users/insert', {
+ data: { id: 2, name: 'Jane Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ const store = createStore([User])
+
+ const result = await store.dispatch('entities/users/insert', {
+ data: [
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ]
+ })
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+})
diff --git a/test/feature/query/inserts_create.spec.ts b/test/feature/query/inserts_create.spec.ts
new file mode 100644
index 00000000..15cbc475
--- /dev/null
+++ b/test/feature/query/inserts_create.spec.ts
@@ -0,0 +1,160 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import Uid from '@/support/Uid'
+import { Model } from '@/index'
+
+describe('feature/query/inserts_create', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('Default Doe')
+ }
+ }
+ }
+
+ beforeEach(() => {
+ Uid.reset()
+ })
+
+ it('can create a record', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ id: 1, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can create multiple records', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('replaces any existing records', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ id: 1, name: 'John Doe' })
+ await store.$repo(User).create({ id: 2, name: 'Jane Doe' })
+
+ const expected = createState({
+ users: {
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('cleans all existing records if the empty data is passed', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ id: 1, name: 'John Doe' })
+ await store.$repo(User).create({})
+
+ const expected = createState({
+ users: {}
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('fills missing fields with the default value', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ id: 1 })
+
+ const expected = {
+ 1: { $id: '1', id: 1, name: 'Default Doe' }
+ }
+
+ expect(store.state.entities.users.data).toEqual(expected)
+ })
+
+ it('can insert record with missing primary key value', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert record with primary key value of `null`', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({ id: null, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ const store = createStore([User])
+
+ const result = await store.$repo(User).create([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+
+ // Test for deprecated payload API syntax.
+ it('accepts the "payload" object as an argument', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).create({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/query/inserts_insert.spec.ts b/test/feature/query/inserts_insert.spec.ts
new file mode 100644
index 00000000..afd6f247
--- /dev/null
+++ b/test/feature/query/inserts_insert.spec.ts
@@ -0,0 +1,160 @@
+import {
+ createStore,
+ createState,
+ serializeCollection
+} from 'test/support/Helpers'
+import Uid from '@/support/Uid'
+import { Model } from '@/index'
+
+describe('feature/query/inserts_insert', () => {
+ class User extends Model {
+ static entity = 'users'
+
+ static fields() {
+ return {
+ id: this.attr(null),
+ name: this.string('Default Doe')
+ }
+ }
+ }
+
+ beforeEach(() => {
+ Uid.reset()
+ })
+
+ it('does nothing if the given data is empty', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({})
+
+ const expected = createState({
+ users: {}
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert a record', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({ id: 1, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert multiple records', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('keeps existing records', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({ id: 1, name: 'John Doe' })
+ await store.$repo(User).insert({ id: 2, name: 'Jane Doe' })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' },
+ 2: { $id: '2', id: 2, name: 'Jane Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('fills missing fields with the default value', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({ id: 1 })
+
+ const expected = {
+ 1: { $id: '1', id: 1, name: 'Default Doe' }
+ }
+
+ expect(store.state.entities.users.data).toEqual(expected)
+ })
+
+ it('can insert record with missing primary key value', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({ name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('can insert record with primary key value of `null`', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({ id: null, name: 'John Doe' })
+
+ const expected = createState({
+ users: {
+ $uid1: { $id: '$uid1', id: '$uid1', name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+
+ it('returns newly created data', async () => {
+ const store = createStore([User])
+
+ const result = await store.$repo(User).insert([
+ { id: 1, name: 'John Doe' },
+ { id: 2, name: 'Jane Doe' }
+ ])
+
+ const expected = [
+ { $id: '1', id: 1, name: 'John Doe' },
+ { $id: '2', id: 2, name: 'Jane Doe' }
+ ]
+
+ expect(result.users.length).toBe(2)
+ expect(result.users[0]).toBeInstanceOf(User)
+ expect(result.users[1]).toBeInstanceOf(User)
+ expect(serializeCollection(result.users)).toEqual(expected)
+ })
+
+ // Test for deprecated payload API syntax.
+ it('accepts the "payload" object as an argument', async () => {
+ const store = createStore([User])
+
+ await store.$repo(User).insert({
+ data: { id: 1, name: 'John Doe' }
+ })
+
+ const expected = createState({
+ users: {
+ 1: { $id: '1', id: 1, name: 'John Doe' }
+ }
+ })
+
+ expect(store.state.entities).toEqual(expected)
+ })
+})
diff --git a/test/feature/repositories/Crud_Create.spec.ts b/test/feature/repositories/Crud_Create.spec.ts
deleted file mode 100644
index 47f4b579..00000000
--- a/test/feature/repositories/Crud_Create.spec.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { createStore, createState } from 'test/support/Helpers'
-import { Model } from '@/index'
-
-describe('Feature - Repositories - CRUD Create', () => {
- it('can create given record to the store', async () => {
- class User extends Model {
- static entity = 'users'
-
- static fields() {
- return {
- id: this.attr(null),
- name: this.string('')
- }
- }
- }
-
- const store = createStore([User])
-
- await store.$repo(User).create({
- data: { id: 1, name: 'John Doe' }
- })
-
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, name: 'John Doe' }
- }
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-})
diff --git a/test/feature/repositories/Crud_Insert.spec.ts b/test/feature/repositories/Crud_Insert.spec.ts
deleted file mode 100644
index 6f549819..00000000
--- a/test/feature/repositories/Crud_Insert.spec.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { createStore, createState } from 'test/support/Helpers'
-import { Model } from '@/index'
-
-describe('Feature - Repositories - CRUD Insert', () => {
- it('can insert given record to the store', async () => {
- class User extends Model {
- static entity = 'users'
-
- static fields() {
- return {
- id: this.attr(null),
- name: this.string('')
- }
- }
- }
-
- const store = createStore([User])
-
- await store.$repo(User).insert({
- data: { id: 1, name: 'John Doe' }
- })
-
- const expected = createState({
- users: {
- 1: { $id: '1', id: 1, name: 'John Doe' }
- }
- })
-
- expect(store.state.entities).toEqual(expected)
- })
-})
diff --git a/test/support/Helpers.ts b/test/support/Helpers.ts
index 39550e4a..c0995207 100644
--- a/test/support/Helpers.ts
+++ b/test/support/Helpers.ts
@@ -2,6 +2,7 @@ import Vue from 'vue'
import Vuex, { Store, Module } from 'vuex'
import VuexORM from '@/index'
import { mapValues } from '@/support/Utils'
+import { Record, Collection } from '@/data'
import Database from '@/database/Database'
import Model from '@/model/Model'
import State from '@/modules/contracts/State'
@@ -51,13 +52,24 @@ export function createStoreFromDatabase(database: Database): Store {
})
}
+/**
+ * Fill store data with the given state.
+ */
+export function fillState(store: Store, state: Record): void {
+ for (const entity in state) {
+ store.commit('entities/$mutate', {
+ entity,
+ callback(s: State) {
+ s.data = state[entity]
+ }
+ })
+ }
+}
+
/**
* Create a new entity state.
*/
-export function createState(
- state: Record,
- namespace: string = 'entities'
-) {
+export function createState(state: Record, namespace: string = 'entities') {
return {
$name: namespace,
...mapValues(state, (data, name) => ({
@@ -68,8 +80,18 @@ export function createState(
}
}
+/**
+ * Serialize given collection by invoking `$getAttributes` on each model
+ * in the given collection.
+ */
+export function serializeCollection(collection: Collection): Record[] {
+ return collection.map((m) => m.$getAttributes())
+}
+
export default {
createStore,
createStoreFromDatabase,
- createState
+ fillState,
+ createState,
+ serializeCollection
}
From 135664a013e24e42e08ffec946fcadad75073699 Mon Sep 17 00:00:00 2001
From: Cue <1493221+cuebit@users.noreply.github.com>
Date: Mon, 6 Apr 2020 04:22:19 +0100
Subject: [PATCH 13/56] feat(Repository): migrate new persist options syntax
---
src/repository/Repository.ts | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts
index 9f81ab90..8080142b 100644
--- a/src/repository/Repository.ts
+++ b/src/repository/Repository.ts
@@ -4,11 +4,10 @@ import Database from '../database/Database'
import { Record, Item, Collection, Collections } from '../data'
import Model from '../model/Model'
import * as Payloads from '../modules/payloads/Actions'
+import * as PersistOptions from '../modules/options/Actions'
import PayloadBuilder from '../modules/support/PayloadBuilder'
import Query from '../query/Query'
import Predicate from '../query/contracts/Predicate'
-import { PersistOptions } from '../query/options'
-import { InsertObject, normalizeInsertPayload } from './support/Payloads'
interface ConstructorOf extends BaseConstructorOf {
entity: string
@@ -104,7 +103,7 @@ export default class Repository {
* Get query instance.
*/
query(): Query {
- return new Query(this.store, this.model.entity)
+ return this.getters('query')()
}
/**
@@ -118,7 +117,7 @@ export default class Repository {
* Create new data with all fields filled by default values.
*/
new(): Promise {
- return this.query().new()
+ return this.dispatch('new')
}
/**
@@ -127,24 +126,20 @@ export default class Repository {
* use the `insert` method instead.
*/
create(
- data: Record | Record[] | InsertObject,
- options?: PersistOptions
+ payload: Payloads.Create,
+ options?: PersistOptions.Create
): Promise {
- const { data: d, options: o } = normalizeInsertPayload(data, options)
-
- return this.query().create(d, o)
+ return this.dispatch('create', PayloadBuilder.normalize(payload, options))
}
/**
* Insert records.
*/
insert(
- data: Record | Record[] | InsertObject,
- options?: PersistOptions
+ payload: Payloads.Insert,
+ options?: PersistOptions.Insert
): Promise {
- const { data: d, options: o } = normalizeInsertPayload(data, options)
-
- return this.query().insert(d, o)
+ return this.dispatch('insert', PayloadBuilder.normalize(payload, options))
}
/**
@@ -152,7 +147,7 @@ export default class Repository {
*/
update(
payload: Payloads.Update,
- options?: PersistOptions
+ options?: PersistOptions.Insert
): Promise {
return this.dispatch('update', PayloadBuilder.normalize(payload, options))
}
@@ -162,7 +157,7 @@ export default class Repository {
*/
insertOrUpdate(
payload: Payloads.InsertOrUpdate,
- options?: PersistOptions
+ options?: PersistOptions.Insert
): Promise {
return this.dispatch(
'insertOrUpdate',
From cfb5c18d2face52b5502d8067131aaf404a81500 Mon Sep 17 00:00:00 2001
From: Kia Ishii
Date: Mon, 6 Apr 2020 18:56:25 +0900
Subject: [PATCH 14/56] refactor: align repository create/insert api with the
latest spec
---
src/repository/Repository.ts | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/repository/Repository.ts b/src/repository/Repository.ts
index 8080142b..9f81ab90 100644
--- a/src/repository/Repository.ts
+++ b/src/repository/Repository.ts
@@ -4,10 +4,11 @@ import Database from '../database/Database'
import { Record, Item, Collection, Collections } from '../data'
import Model from '../model/Model'
import * as Payloads from '../modules/payloads/Actions'
-import * as PersistOptions from '../modules/options/Actions'
import PayloadBuilder from '../modules/support/PayloadBuilder'
import Query from '../query/Query'
import Predicate from '../query/contracts/Predicate'
+import { PersistOptions } from '../query/options'
+import { InsertObject, normalizeInsertPayload } from './support/Payloads'
interface ConstructorOf extends BaseConstructorOf {
entity: string
@@ -103,7 +104,7 @@ export default class Repository {
* Get query instance.
*/
query(): Query {
- return this.getters('query')()
+ return new Query(this.store, this.model.entity)
}
/**
@@ -117,7 +118,7 @@ export default class Repository {
* Create new data with all fields filled by default values.
*/
new(): Promise {
- return this.dispatch('new')
+ return this.query().new()
}
/**
@@ -126,20 +127,24 @@ export default class Repository {
* use the `insert` method instead.
*/
create(
- payload: Payloads.Create,
- options?: PersistOptions.Create
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
): Promise {
- return this.dispatch('create', PayloadBuilder.normalize(payload, options))
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().create(d, o)
}
/**
* Insert records.
*/
insert(
- payload: Payloads.Insert,
- options?: PersistOptions.Insert
+ data: Record | Record[] | InsertObject,
+ options?: PersistOptions
): Promise {
- return this.dispatch('insert', PayloadBuilder.normalize(payload, options))
+ const { data: d, options: o } = normalizeInsertPayload(data, options)
+
+ return this.query().insert(d, o)
}
/**
@@ -147,7 +152,7 @@ export default class Repository {
*/
update(
payload: Payloads.Update,
- options?: PersistOptions.Insert
+ options?: PersistOptions
): Promise {
return this.dispatch('update', PayloadBuilder.normalize(payload, options))
}
@@ -157,7 +162,7 @@ export default class Repository {
*/
insertOrUpdate(
payload: Payloads.InsertOrUpdate,
- options?: PersistOptions.Insert
+ options?: PersistOptions
): Promise {
return this.dispatch(
'insertOrUpdate',
From cc0da6256679be551f0996bee8b1a535fd2eceaf Mon Sep 17 00:00:00 2001
From: Kia Ishii
Date: Mon, 6 Apr 2020 23:55:40 +0900
Subject: [PATCH 15/56] wip: working on
---
src/connections/Connection.ts | 37 +++++++++++++++++++++++---
src/data/RecordWithId.ts | 7 +++++
src/data/index.ts | 2 ++
src/model/Model.ts | 3 ++-
src/model/Serialize.ts | 6 ++---
src/modules/RootMutations.ts | 25 ++++++++++++------
src/modules/payloads/RootMutations.ts | 16 +++++------
src/query/Query.ts | 38 +++++++++++----------------
8 files changed, 86 insertions(+), 48 deletions(-)
create mode 100644 src/data/RecordWithId.ts
diff --git a/src/connections/Connection.ts b/src/connections/Connection.ts
index 4db34830..75ddcb8c 100644
--- a/src/connections/Connection.ts
+++ b/src/connections/Connection.ts
@@ -1,6 +1,5 @@
import { Store } from 'vuex'
-import Record from '../data/Record'
-import Records from '../data/Records'
+import { Records, RecordWithId } from '../data'
import RootState from '../modules/contracts/RootState'
import State from '../modules/contracts/State'
@@ -41,11 +40,31 @@ export default class Connection {
this.state = this.rootState[entity]
}
+ /**
+ * Commit Vuex Mutation.
+ */
+ private commit(name: string, payload: any): void {
+ this.store.commit(`${this.connection}/${name}`, payload)
+ }
+
+ /**
+ * Commit the given record by `new` method.
+ */
+ new(record: RecordWithId): void {
+ this.commit('new', {
+ entity: this.entity,
+ data: { [record.$id]: record }
+ })
+ }
+
/**
* Insert the given record.
*/
- insert(record: Record): void {
- this.state.data = { ...this.state.data, [record.$id]: record }
+ insert(records: RecordWithId[]): void {
+ this.commit('new', {
+ entity: this.entity,
+ data: this.mapRecordToRecords(records)
+ })
}
/**
@@ -69,4 +88,14 @@ export default class Connection {
this.state.data = data
}
+
+ /**
+ * Map the given records to `Records` type object.
+ */
+ private mapRecordToRecords(records: RecordWithId[]): Records {
+ return records.reduce((carry, record) => {
+ carry[record.$id] = record
+ return carry
+ }, {})
+ }
}
diff --git a/src/data/RecordWithId.ts b/src/data/RecordWithId.ts
new file mode 100644
index 00000000..60c7b94c
--- /dev/null
+++ b/src/data/RecordWithId.ts
@@ -0,0 +1,7 @@
+import Record from './Record'
+
+export interface RecordWithId extends Record {
+ $id: string
+}
+
+export default RecordWithId
diff --git a/src/data/index.ts b/src/data/index.ts
index 0cb78956..19fb4667 100644
--- a/src/data/index.ts
+++ b/src/data/index.ts
@@ -1,4 +1,5 @@
import Record from './Record'
+import RecordWithId from './RecordWithId'
import Records from './Records'
import NormalizedData from './NormalizedData'
import Instance from './Instance'
@@ -11,6 +12,7 @@ import Collections from './Collections'
export {
Record,
+ RecordWithId,
Records,
NormalizedData,
InstanceOf,
diff --git a/src/model/Model.ts b/src/model/Model.ts
index 71798d55..43f83b2f 100644
--- a/src/model/Model.ts
+++ b/src/model/Model.ts
@@ -4,6 +4,7 @@ import Uid from '../support/Uid'
import Container from '../container/Container'
import Database from '../database/Database'
import Record from '../data/Record'
+import RecordWithId from '../data/RecordWithId'
import InstanceOf from '../data/InstanceOf'
import Item from '../data/Item'
import Collection from '../data/Collection'
@@ -1062,7 +1063,7 @@ export default class Model {
* value as well. This method is mainly used when saving a model to
* the store.
*/
- $getAttributes(): Record {
+ $getAttributes(): RecordWithId {
return toAttributes(this)
}
diff --git a/src/model/Serialize.ts b/src/model/Serialize.ts
index 8e1bf6ee..a07de0d3 100644
--- a/src/model/Serialize.ts
+++ b/src/model/Serialize.ts
@@ -1,5 +1,5 @@
import { isArray } from '../support/Utils'
-import Record from '../data/Record'
+import { Record, RecordWithId } from '../data'
import Item from '../data/Item'
import Collection from '../data/Collection'
import Relation from '../attributes/relations/Relation'
@@ -17,12 +17,12 @@ const defaultOption: Option = {
* Serialize the given model to attributes. This method will ignore
* relationships, and it includes the index id.
*/
-export function toAttributes(model: Model): Record {
+export function toAttributes(model: Model): RecordWithId {
const record = toJson(model, { relations: false })
record.$id = model.$id
- return record
+ return record as RecordWithId
}
/**
diff --git a/src/modules/RootMutations.ts b/src/modules/RootMutations.ts
index c5223279..dc02ca3b 100644
--- a/src/modules/RootMutations.ts
+++ b/src/modules/RootMutations.ts
@@ -1,6 +1,6 @@
import { Store } from 'vuex'
import Connection from '../connections/Connection'
-import RootState from './contracts/RootState'
+import State from './contracts/RootState'
import MutationsContract from './contracts/RootMutations'
import * as Payloads from './payloads/RootMutations'
@@ -10,24 +10,32 @@ import * as Payloads from './payloads/RootMutations'
*/
function $mutate(
this: Store,
- state: RootState,
+ state: State,
payload: Payloads.$Mutate
): void {
payload.callback(state[payload.entity])
}
/**
- * Insert the given record.
+ * Commit the given records by `new` method.
*/
-function insert(this: Store, state: RootState, payload: any): void {
- const { entity, record } = payload
- new Connection(this, state.$name, entity).insert(record)
+function newRecord(state: State, payload: Payloads.New): void {
+ const entity = state[payload.entity]
+ entity.data = { ...entity.data, ...payload.data }
+}
+
+/**
+ * Commit the given records by `insert` method.
+ */
+function insert(state: State, payload: Payloads.Insert): void {
+ const entity = state[payload.entity]
+ entity.data = { ...entity.data, ...payload.data }
}
/**
* Insert the given records.
*/
-function insertRecords(this: Store, state: RootState, payload: any): void {
+function insertRecords(this: Store, state: State, payload: any): void {
const { entity, records } = payload
new Connection(this, state.$name, entity).insertRecords(records)
}
@@ -37,13 +45,14 @@ function insertRecords(this: Store, state: RootState, payload: any): void {
* `delete`, but named `destroy` here because `delete` can't be declared at
* this scope level.
*/
-function destroy(this: Store, state: RootState, payload: any): void {
+function destroy(this: Store, state: State, payload: any): void {
const { entity, id } = payload
new Connection(this, state.$name, entity).delete(id)
}
const RootMutations: MutationsContract = {
$mutate,
+ new: newRecord,
insert,
insertRecords,
delete: destroy
diff --git a/src/modules/payloads/RootMutations.ts b/src/modules/payloads/RootMutations.ts
index 7e52bdfb..e9ec3684 100644
--- a/src/modules/payloads/RootMutations.ts
+++ b/src/modules/payloads/RootMutations.ts
@@ -1,7 +1,7 @@
-import Record from '../../data/Record'
+import { Record, Records } from '../../data'
import Predicate from '../../query/contracts/Predicate'
-import State from '../contracts/State'
import PersistOptions from '../../query/options/PersistOptions'
+import State from '../contracts/State'
export type Condition = (record: Record) => boolean
@@ -10,18 +10,14 @@ export interface $Mutate {
callback: (state: State) => void
}
-export interface New extends PersistOptions {
+export interface New {
entity: string
+ data: Records
}
-export interface Create extends PersistOptions {
+export interface Insert {
entity: string
- data: Record | Record[]
-}
-
-export interface Insert extends PersistOptions {
- entity: string
- data: Record | Record[]
+ data: Records
}
export interface Update extends PersistOptions {
diff --git a/src/query/Query.ts b/src/query/Query.ts
index 7add3be0..e17fd597 100644
--- a/src/query/Query.ts
+++ b/src/query/Query.ts
@@ -1,6 +1,7 @@
import { Store } from 'vuex'
import Utils from '../support/Utils'
import Database, { Models } from '../database/Database'
+import Connection from '../connections/Connection'
import * as Data from '../data'
import Model from '../model/Model'
import State from '../modules/contracts/State'
@@ -217,6 +218,17 @@ export default class Query {
return new Query(this.store, entity)
}
+ /**
+ * Get the new connection instance.
+ */
+ connection(): Connection {
+ return new Connection(
+ this.store,
+ this.database.namespace,
+ this.entity
+ )
+ }
+
/**
* Get model of given name from the container.
*/
@@ -798,7 +810,7 @@ export default class Query {
async new(): Promise {
const model = new this.model().$generateId() as T
- this.commitInsert(model.$getAttributes())
+ this.connection().new(model.$getAttributes())
return model
}
@@ -844,7 +856,9 @@ export default class Query {
collection = this.executeMutationHooks('beforeCreate', collection)
- this.commitInsertRecords(this.convertCollectionToRecords(collection))
+ this.connection().insert(
+ collection.map((m) => m.$getAttributes())
+ )
this.executeMutationHooks('afterCreate', collection)
@@ -1265,13 +1279,6 @@ export default class Query {
this.commit('insert', { record })
}
- /**
- * Commit insert records mutation.
- */
- private commitInsertRecords(records: Data.Record): void {
- this.commit('insertRecords', { records })
- }
-
/**
* Commit delete mutation.
*/
@@ -1369,19 +1376,6 @@ export default class Query {
return collection
}
- /**
- * Convert given collection to records by using index id as a key.
- */
- private convertCollectionToRecords(
- collection: Data.Collection
- ): Data.Records {
- return collection.reduce((carry, model) => {
- carry[model['$id'] as string] = model.$getAttributes()
-
- return carry
- }, {})
- }
-
/**
* Clears the current state from any data related to current model.
*
From ee8e9f874aae52706f1cb55fd90267692cb17ae2 Mon Sep 17 00:00:00 2001
From: Kia Ishii
Date: Tue, 7 Apr 2020 00:08:23 +0900
Subject: [PATCH 16/56] refresh
---
src/attributes/Attribute.ts | 26 -
src/attributes/contracts/DictionaryMany.ts | 7 -
src/attributes/contracts/DictionaryOne.ts | 7 -
src/attributes/contracts/Mutator.ts | 3 -
src/attributes/contracts/Mutators.ts | 7 -
src/attributes/index.ts | 43 -
src/attributes/relations/BelongsTo.ts | 128 --
src/attributes/relations/BelongsToMany.ts | 257 ---
src/attributes/relations/HasMany.ts | 132 --
src/attributes/relations/HasManyBy.ts | 119 --
src/attributes/relations/HasManyThrough.ts | 156 --
src/attributes/relations/HasOne.ts | 132 --
src/attributes/relations/HasOneThrough.ts | 151 --
src/attributes/relations/MorphMany.ts | 117 --
src/attributes/relations/MorphOne.ts | 113 --
src/attributes/relations/MorphTo.ts | 101 --
src/attributes/relations/MorphToMany.ts | 258 ---
src/attributes/relations/MorphedByMany.ts | 248 ---
src/attributes/relations/Relation.ts | 192 ---
src/attributes/types/Attr.ts | 31 -
src/attributes/types/Boolean.ts | 58 -
src/attributes/types/Number.ts | 52 -
src/attributes/types/String.ts | 44 -
src/attributes/types/Type.ts | 43 -
src/attributes/types/Uid.ts | 28 -
src/connections/Connection.ts | 101 --
src/container/Container.ts | 15 -
src/data/Collection.ts | 6 -
src/data/Collections.ts | 7 -
src/data/Entities.ts | 7 -
src/data/Instance.ts | 5 -
src/data/InstanceOf.ts | 3 -
src/data/Instances.ts | 8 -
src/data/Item.ts | 6 -
src/data/NormalizedData.ts | 7 -
src/data/Record.ts | 5 -
src/data/RecordWithId.ts | 7 -
src/data/Records.ts | 7 -
src/data/index.ts | 25 -
src/database/Database.ts | 403 -----
src/database/HackedDatabase.ts | 28 -
src/index.cjs.ts | 70 +-
src/index.ts | 129 +-
src/model/Model.ts | 1076 ------------
src/model/Serialize.ts | 116 --
src/model/contracts/FieldCache.ts | 7 -
src/model/contracts/Fields.ts | 7 -
src/model/contracts/InheritanceTypes.ts | 7 -
src/model/contracts/State.ts | 5 -
src/model/support/Payloads.ts | 39 -
src/modules/Actions.ts | 151 --
src/modules/Getters.ts | 63 -
src/modules/RootActions.ts | 142 --
src/modules/RootGetters.ts | 50 -
src/modules/RootMutations.ts | 61 -
src/modules/contracts/ActionContext.ts | 6 -
src/modules/contracts/Actions.ts | 6 -
src/modules/contracts/Getters.ts | 6 -
src/modules/contracts/Module.ts | 13 -
src/modules/contracts/RootActionContext.ts | 6 -
src/modules/contracts/RootActions.ts | 6 -
src/modules/contracts/RootGetters.ts | 6 -
src/modules/contracts/RootMutations.ts | 6 -
src/modules/contracts/RootState.ts | 5 -
src/modules/contracts/State.ts | 10 -
src/modules/options/Actions.ts | 13 -
src/modules/payloads/Actions.ts | 38 -
src/modules/payloads/RootActions.ts | 44 -
src/modules/payloads/RootMutations.ts | 41 -
src/modules/support/OptionsBuilder.ts | 15 -
src/modules/support/PayloadBuilder.ts | 44 -
src/plugins/use.ts | 112 --
src/polyfills/index.ts | 6 -
src/query/Query.ts | 1441 -----------------
src/query/contracts/GlobalHook.ts | 8 -
src/query/contracts/GlobalHooks.ts | 7 -
src/query/contracts/HookableClosure.ts | 6 -
src/query/contracts/MutationHook.ts | 9 -
src/query/contracts/Predicate.ts | 5 -
src/query/contracts/RelationshipConstraint.ts | 5 -
src/query/contracts/SelectHook.ts | 8 -
src/query/contracts/index.ts | 17 -
src/query/filters/Filter.ts | 38 -
src/query/filters/LimitFilter.ts | 18 -
src/query/filters/OrderByFilter.ts | 23 -
src/query/filters/WhereFilter.ts | 98 --
src/query/loaders/Loader.ts | 152 --
src/query/options/Constraint.ts | 5 -
src/query/options/Has.ts | 11 -
src/query/options/HasConstraint.ts | 5 -
src/query/options/Load.ts | 7 -
src/query/options/OrderDirection.ts | 3 -
src/query/options/OrderKey.ts | 5 -
src/query/options/Orders.ts | 10 -
src/query/options/PersistMethods.ts | 3 -
src/query/options/PersistOptions.ts | 8 -
src/query/options/PrimaryKey.ts | 3 -
src/query/options/Where.ts | 11 -
src/query/options/WhereBoolean.ts | 3 -
src/query/options/WherePrimaryClosure.ts | 11 -
src/query/options/WhereSecondaryClosure.ts | 3 -
src/query/options/index.ts | 31 -
src/query/processors/Attacher.ts | 27 -
src/query/processors/Normalizer.ts | 22 -
src/query/processors/PivotCreator.ts | 25 -
src/query/processors/Processor.ts | 27 -
src/query/rollcallers/Rollcaller.ts | 202 ---
src/repository/Repository.ts | 188 ---
src/repository/support/Payloads.ts | 39 -
src/schema/IdAttribute.ts | 51 -
src/schema/Schema.ts | 95 --
src/schema/Schemas.ts | 7 -
src/store/index.ts | 94 --
src/support/Uid.ts | 27 -
src/support/Utils.ts | 285 ----
src/types/index.ts | 1 -
src/types/vuex.ts | 32 -
test/Helpers.ts | 1 +
test/feature/aggregates/Aggregates.spec.ts | 90 -
test/feature/attributes/Boolean.spec.ts | 120 --
test/feature/attributes/Number.spec.ts | 112 --
test/feature/attributes/String.spec.ts | 102 --
test/feature/attributes/Uid.spec.ts | 95 --
test/feature/basics/Delete.spec.ts | 225 ---
.../basics/Delete_Composite_Key.spec.ts | 59 -
test/feature/basics/Exists.spec.ts | 45 -
test/feature/basics/InsertOrUpdate.spec.ts | 70 -
test/feature/basics/PersistOptions.spec.ts | 131 --
test/feature/basics/Retrieve.spec.ts | 210 ---
.../basics/Retrieve_LimitAndOffset.spec.ts | 53 -
test/feature/basics/Retrieve_OrderBy.spec.ts | 145 --
.../basics/Retrieve_SSRSupport.spec.ts | 50 -
test/feature/basics/Retrieve_Where.spec.ts | 519 ------
.../Retrieve_Where_Composite_Key.spec.ts | 178 --
test/feature/basics/State.spec.ts | 98 --
test/feature/basics/Update.spec.ts | 690 --------
test/feature/database/RegisterModel.spec.ts | 198 ---
test/feature/hooks/Global.spec.ts | 107 --
test/feature/hooks/Global_Create.spec.ts | 94 --
test/feature/hooks/Global_Delete.spec.ts | 74 -
test/feature/hooks/Global_Select.spec.ts | 55 -
test/feature/hooks/Global_Update.spec.ts | 73 -
test/feature/hooks/Local_Binding.spec.ts | 43 -
test/feature/hooks/Local_Create.spec.ts | 147 --
test/feature/hooks/Local_Delete.spec.ts | 120 --
test/feature/hooks/Local_Insert.spec.ts | 149 --
test/feature/hooks/Local_Select.spec.ts | 43 -
test/feature/hooks/Local_Update.spec.ts | 161 --
test/feature/inheritance/Inheritance.spec.ts | 130 --
.../inheritance/Inheritance_CRUD.spec.ts | 233 ---
.../Inheritance_Discriminator.spec.ts | 200 ---
.../Inheritance_RelationInstantiation.spec.ts | 174 --
.../inheritance/Inheritance_Relations.spec.ts | 433 -----
test/feature/models/All.spec.ts | 55 -
test/feature/models/Create.spec.ts | 257 ---
test/feature/models/Find.spec.ts | 288 ----
test/feature/models/Insert.spec.ts | 263 ---
test/feature/models/InsertOrUpdate.spec.ts | 207 ---
test/feature/models/Query.spec.ts | 52 -
test/feature/models/Save.spec.ts | 90 -
test/feature/models/Update.spec.ts | 243 ---
.../models/static_inserts_create.spec.ts | 102 --
.../models/static_inserts_insert.spec.ts | 103 --
.../feature/models/static_inserts_new.spec.ts | 50 -
.../SubGetters_DirectEntityCall.spec.ts | 28 -
.../modules/api_inserts_create.spec.ts | 95 --
.../modules/api_inserts_insert.spec.ts | 96 --
test/feature/modules/api_inserts_new.spec.ts | 50 -
test/feature/modules/modules.spec.ts | 48 -
test/feature/plugin/Plugin.spec.ts | 187 ---
test/feature/query/inserts_create.spec.ts | 160 --
test/feature/query/inserts_insert.spec.ts | 160 --
test/feature/query/inserts_new.spec.ts | 50 -
test/feature/relations/BelongsTo.spec.ts | 261 ---
.../relations/BelongsToMany_Persist.spec.ts | 564 -------
.../relations/BelongsToMany_Retrieve.spec.ts | 453 ------
test/feature/relations/HasMany.spec.ts | 190 ---
test/feature/relations/HasManyBy.spec.ts | 284 ----
test/feature/relations/HasManyThrough.spec.ts | 572 -------
test/feature/relations/HasOne.spec.ts | 193 ---
test/feature/relations/HasOneThrough.spec.ts | 551 -------
.../relations/MorphMany_Persist.spec.ts | 749 ---------
.../relations/MorphMany_Retrieve.spec.ts | 448 -----
.../relations/MorphOne_Persist.spec.ts | 515 ------
.../relations/MorphOne_Retrieve.spec.ts | 404 -----
test/feature/relations/MorphTo.spec.ts | 270 ---
.../relations/MorphToMany_Persist.spec.ts | 576 -------
.../relations/MorphToMany_Retrieve.spec.ts | 664 --------
.../relations/MorphedByMany_Persist.spec.ts | 353 ----
.../relations/MorphedByMany_Retrieve.spec.ts | 541 -------
.../relations/Persist_NestedMorph.spec.ts | 81 -
.../relations/Retrieve_Constraint.spec.ts | 54 -
.../relations/Retrieve_DeepLoad.spec.ts | 88 -
test/feature/relations/Retrieve_Has.spec.ts | 321 ----
.../relations/Retrieve_SelfRelation.spec.ts | 39 -
.../relations/Retrieve_StringDefine.spec.ts | 56 -
test/feature/relations/Retrieve_With.spec.ts | 951 -----------
.../Retrieve_With_NestedConstraints.spec.ts | 149 --
test/feature/relations/WhereFk.spec.ts | 48 -
test/feature/repositories/Crud_Delete.spec.ts | 74 -
.../repositories/Crud_InsertOrUpdate.spec.ts | 39 -
.../repositories/Crud_Retrieve.spec.ts | 195 ---
test/feature/repositories/Crud_Update.spec.ts | 35 -
test/feature/repositories/Repository.spec.ts | 100 --
test/performance/Retrieve_BelongsTo.spec.ts | 61 -
.../Retrieve_BelongsToMany.spec.ts | 79 -
test/performance/Retrieve_HasMany.spec.ts | 55 -
.../Retrieve_HasManyThrough.spec.ts | 80 -
.../Retrieve_HasOneThrough.spec.ts | 76 -
test/support/Helpers.ts | 97 --
test/unit/VuexORM.spec.ts | 76 -
test/unit/database/Database.spec.ts | 264 ---
test/unit/model/Model.spec.ts | 298 ----
.../model/Model_Attributes_Boolean.spec.ts | 95 --
.../model/Model_Attributes_Mutators.spec.ts | 70 -
.../model/Model_Attributes_Number.spec.ts | 89 -
.../model/Model_Attributes_String.spec.ts | 86 -
test/unit/model/Model_Relations.spec.ts | 285 ----
.../Model_Relations_BelongsToMany.spec.ts | 61 -
.../model/Model_Relations_MorphMany.spec.ts | 71 -
.../model/Model_Relations_MorphOne.spec.ts | 66 -
.../model/Model_Relations_MorphTo.spec.ts | 116 --
.../model/Model_Relations_MorphToMany.spec.ts | 112 --
.../Model_Relations_MorphedByMany.spec.ts | 112 --
test/unit/model/Model_Serialization.spec.ts | 138 --
test/unit/model/Model_Store.spec.ts | 174 --
test/unit/model/Model_Utilities.spec.ts | 99 --
test/unit/query/Query.spec.ts | 38 -
test/unit/support/Utils.spec.ts | 138 --
229 files changed, 3 insertions(+), 29137 deletions(-)
delete mode 100644 src/attributes/Attribute.ts
delete mode 100644 src/attributes/contracts/DictionaryMany.ts
delete mode 100644 src/attributes/contracts/DictionaryOne.ts
delete mode 100644 src/attributes/contracts/Mutator.ts
delete mode 100644 src/attributes/contracts/Mutators.ts
delete mode 100644 src/attributes/index.ts
delete mode 100644 src/attributes/relations/BelongsTo.ts
delete mode 100644 src/attributes/relations/BelongsToMany.ts
delete mode 100644 src/attributes/relations/HasMany.ts
delete mode 100644 src/attributes/relations/HasManyBy.ts
delete mode 100644 src/attributes/relations/HasManyThrough.ts
delete mode 100644 src/attributes/relations/HasOne.ts
delete mode 100644 src/attributes/relations/HasOneThrough.ts
delete mode 100644 src/attributes/relations/MorphMany.ts
delete mode 100644 src/attributes/relations/MorphOne.ts
delete mode 100644 src/attributes/relations/MorphTo.ts
delete mode 100644 src/attributes/relations/MorphToMany.ts
delete mode 100644 src/attributes/relations/MorphedByMany.ts
delete mode 100644 src/attributes/relations/Relation.ts
delete mode 100644 src/attributes/types/Attr.ts
delete mode 100644 src/attributes/types/Boolean.ts
delete mode 100644 src/attributes/types/Number.ts
delete mode 100644 src/attributes/types/String.ts
delete mode 100644 src/attributes/types/Type.ts
delete mode 100644 src/attributes/types/Uid.ts
delete mode 100644 src/connections/Connection.ts
delete mode 100644 src/container/Container.ts
delete mode 100644 src/data/Collection.ts
delete mode 100644 src/data/Collections.ts
delete mode 100644 src/data/Entities.ts
delete mode 100644 src/data/Instance.ts
delete mode 100644 src/data/InstanceOf.ts
delete mode 100644 src/data/Instances.ts
delete mode 100644 src/data/Item.ts
delete mode 100644 src/data/NormalizedData.ts
delete mode 100644 src/data/Record.ts
delete mode 100644 src/data/RecordWithId.ts
delete mode 100644 src/data/Records.ts
delete mode 100644 src/data/index.ts
delete mode 100644 src/database/Database.ts
delete mode 100644 src/database/HackedDatabase.ts
delete mode 100644 src/model/Model.ts
delete mode 100644 src/model/Serialize.ts
delete mode 100644 src/model/contracts/FieldCache.ts
delete mode 100644 src/model/contracts/Fields.ts
delete mode 100644 src/model/contracts/InheritanceTypes.ts
delete mode 100644 src/model/contracts/State.ts
delete mode 100644 src/model/support/Payloads.ts
delete mode 100644 src/modules/Actions.ts
delete mode 100644 src/modules/Getters.ts
delete mode 100644 src/modules/RootActions.ts
delete mode 100644 src/modules/RootGetters.ts
delete mode 100644 src/modules/RootMutations.ts
delete mode 100644 src/modules/contracts/ActionContext.ts
delete mode 100644 src/modules/contracts/Actions.ts
delete mode 100644 src/modules/contracts/Getters.ts
delete mode 100644 src/modules/contracts/Module.ts
delete mode 100644 src/modules/contracts/RootActionContext.ts
delete mode 100644 src/modules/contracts/RootActions.ts
delete mode 100644 src/modules/contracts/RootGetters.ts
delete mode 100644 src/modules/contracts/RootMutations.ts
delete mode 100644 src/modules/contracts/RootState.ts
delete mode 100644 src/modules/contracts/State.ts
delete mode 100644 src/modules/options/Actions.ts
delete mode 100644 src/modules/payloads/Actions.ts
delete mode 100644 src/modules/payloads/RootActions.ts
delete mode 100644 src/modules/payloads/RootMutations.ts
delete mode 100644 src/modules/support/OptionsBuilder.ts
delete mode 100644 src/modules/support/PayloadBuilder.ts
delete mode 100644 src/plugins/use.ts
delete mode 100644 src/polyfills/index.ts
delete mode 100644 src/query/Query.ts
delete mode 100644 src/query/contracts/GlobalHook.ts
delete mode 100644 src/query/contracts/GlobalHooks.ts
delete mode 100644 src/query/contracts/HookableClosure.ts
delete mode 100644 src/query/contracts/MutationHook.ts
delete mode 100644 src/query/contracts/Predicate.ts
delete mode 100644 src/query/contracts/RelationshipConstraint.ts
delete mode 100644 src/query/contracts/SelectHook.ts
delete mode 100644 src/query/contracts/index.ts
delete mode 100644 src/query/filters/Filter.ts
delete mode 100644 src/query/filters/LimitFilter.ts
delete mode 100644 src/query/filters/OrderByFilter.ts
delete mode 100644 src/query/filters/WhereFilter.ts
delete mode 100644 src/query/loaders/Loader.ts
delete mode 100644 src/query/options/Constraint.ts
delete mode 100644 src/query/options/Has.ts
delete mode 100644 src/query/options/HasConstraint.ts
delete mode 100644 src/query/options/Load.ts
delete mode 100644 src/query/options/OrderDirection.ts
delete mode 100644 src/query/options/OrderKey.ts
delete mode 100644 src/query/options/Orders.ts
delete mode 100644 src/query/options/PersistMethods.ts
delete mode 100644 src/query/options/PersistOptions.ts
delete mode 100644 src/query/options/PrimaryKey.ts
delete mode 100644 src/query/options/Where.ts
delete mode 100644 src/query/options/WhereBoolean.ts
delete mode 100644 src/query/options/WherePrimaryClosure.ts
delete mode 100644 src/query/options/WhereSecondaryClosure.ts
delete mode 100644 src/query/options/index.ts
delete mode 100644 src/query/processors/Attacher.ts
delete mode 100644 src/query/processors/Normalizer.ts
delete mode 100644 src/query/processors/PivotCreator.ts
delete mode 100644 src/query/processors/Processor.ts
delete mode 100644 src/query/rollcallers/Rollcaller.ts
delete mode 100644 src/repository/Repository.ts
delete mode 100644 src/repository/support/Payloads.ts
delete mode 100644 src/schema/IdAttribute.ts
delete mode 100644 src/schema/Schema.ts
delete mode 100644 src/schema/Schemas.ts
delete mode 100644 src/store/index.ts
delete mode 100644 src/support/Uid.ts
delete mode 100644 src/support/Utils.ts
delete mode 100644 src/types/index.ts
delete mode 100644 src/types/vuex.ts
create mode 100644 test/Helpers.ts
delete mode 100644 test/feature/aggregates/Aggregates.spec.ts
delete mode 100644 test/feature/attributes/Boolean.spec.ts
delete mode 100644 test/feature/attributes/Number.spec.ts
delete mode 100644 test/feature/attributes/String.spec.ts
delete mode 100644 test/feature/attributes/Uid.spec.ts
delete mode 100644 test/feature/basics/Delete.spec.ts
delete mode 100644 test/feature/basics/Delete_Composite_Key.spec.ts
delete mode 100644 test/feature/basics/Exists.spec.ts
delete mode 100644 test/feature/basics/InsertOrUpdate.spec.ts
delete mode 100644 test/feature/basics/PersistOptions.spec.ts
delete mode 100644 test/feature/basics/Retrieve.spec.ts
delete mode 100644 test/feature/basics/Retrieve_LimitAndOffset.spec.ts
delete mode 100644 test/feature/basics/Retrieve_OrderBy.spec.ts
delete mode 100644 test/feature/basics/Retrieve_SSRSupport.spec.ts
delete mode 100644 test/feature/basics/Retrieve_Where.spec.ts
delete mode 100644 test/feature/basics/Retrieve_Where_Composite_Key.spec.ts
delete mode 100644 test/feature/basics/State.spec.ts
delete mode 100644 test/feature/basics/Update.spec.ts
delete mode 100644 test/feature/database/RegisterModel.spec.ts
delete mode 100644 test/feature/hooks/Global.spec.ts
delete mode 100644 test/feature/hooks/Global_Create.spec.ts
delete mode 100644 test/feature/hooks/Global_Delete.spec.ts
delete mode 100644 test/feature/hooks/Global_Select.spec.ts
delete mode 100644 test/feature/hooks/Global_Update.spec.ts
delete mode 100644 test/feature/hooks/Local_Binding.spec.ts
delete mode 100644 test/feature/hooks/Local_Create.spec.ts
delete mode 100644 test/feature/hooks/Local_Delete.spec.ts
delete mode 100644 test/feature/hooks/Local_Insert.spec.ts
delete mode 100644 test/feature/hooks/Local_Select.spec.ts
delete mode 100644 test/feature/hooks/Local_Update.spec.ts
delete mode 100644 test/feature/inheritance/Inheritance.spec.ts
delete mode 100644 test/feature/inheritance/Inheritance_CRUD.spec.ts
delete mode 100644 test/feature/inheritance/Inheritance_Discriminator.spec.ts
delete mode 100644 test/feature/inheritance/Inheritance_RelationInstantiation.spec.ts
delete mode 100644 test/feature/inheritance/Inheritance_Relations.spec.ts
delete mode 100644 test/feature/models/All.spec.ts
delete mode 100644 test/feature/models/Create.spec.ts
delete mode 100644 test/feature/models/Find.spec.ts
delete mode 100644 test/feature/models/Insert.spec.ts
delete mode 100644 test/feature/models/InsertOrUpdate.spec.ts
delete mode 100644 test/feature/models/Query.spec.ts
delete mode 100644 test/feature/models/Save.spec.ts
delete mode 100644 test/feature/models/Update.spec.ts
delete mode 100644 test/feature/models/static_inserts_create.spec.ts
delete mode 100644 test/feature/models/static_inserts_insert.spec.ts
delete mode 100644 test/feature/models/static_inserts_new.spec.ts
delete mode 100644 test/feature/modules/SubGetters_DirectEntityCall.spec.ts
delete mode 100644 test/feature/modules/api_inserts_create.spec.ts
delete mode 100644 test/feature/modules/api_inserts_insert.spec.ts
delete mode 100644 test/feature/modules/api_inserts_new.spec.ts
delete mode 100644 test/feature/modules/modules.spec.ts
delete mode 100644 test/feature/plugin/Plugin.spec.ts
delete mode 100644 test/feature/query/inserts_create.spec.ts
delete mode 100644 test/feature/query/inserts_insert.spec.ts
delete mode 100644 test/feature/query/inserts_new.spec.ts
delete mode 100644 test/feature/relations/BelongsTo.spec.ts
delete mode 100644 test/feature/relations/BelongsToMany_Persist.spec.ts
delete mode 100644 test/feature/relations/BelongsToMany_Retrieve.spec.ts
delete mode 100644 test/feature/relations/HasMany.spec.ts
delete mode 100644 test/feature/relations/HasManyBy.spec.ts
delete mode 100644 test/feature/relations/HasManyThrough.spec.ts
delete mode 100644 test/feature/relations/HasOne.spec.ts
delete mode 100644 test/feature/relations/HasOneThrough.spec.ts
delete mode 100644 test/feature/relations/MorphMany_Persist.spec.ts
delete mode 100644 test/feature/relations/MorphMany_Retrieve.spec.ts
delete mode 100644 test/feature/relations/MorphOne_Persist.spec.ts
delete mode 100644 test/feature/relations/MorphOne_Retrieve.spec.ts
delete mode 100644 test/feature/relations/MorphTo.spec.ts
delete mode 100644 test/feature/relations/MorphToMany_Persist.spec.ts
delete mode 100644 test/feature/relations/MorphToMany_Retrieve.spec.ts
delete mode 100644 test/feature/relations/MorphedByMany_Persist.spec.ts
delete mode 100644 test/feature/relations/MorphedByMany_Retrieve.spec.ts
delete mode 100644 test/feature/relations/Persist_NestedMorph.spec.ts
delete mode 100644 test/feature/relations/Retrieve_Constraint.spec.ts
delete mode 100644 test/feature/relations/Retrieve_DeepLoad.spec.ts
delete mode 100644 test/feature/relations/Retrieve_Has.spec.ts
delete mode 100644 test/feature/relations/Retrieve_SelfRelation.spec.ts
delete mode 100644 test/feature/relations/Retrieve_StringDefine.spec.ts
delete mode 100644 test/feature/relations/Retrieve_With.spec.ts
delete mode 100644 test/feature/relations/Retrieve_With_NestedConstraints.spec.ts
delete mode 100644 test/feature/relations/WhereFk.spec.ts
delete mode 100644 test/feature/repositories/Crud_Delete.spec.ts
delete mode 100644 test/feature/repositories/Crud_InsertOrUpdate.spec.ts
delete mode 100644 test/feature/repositories/Crud_Retrieve.spec.ts
delete mode 100644 test/feature/repositories/Crud_Update.spec.ts
delete mode 100644 test/feature/repositories/Repository.spec.ts
delete mode 100644 test/performance/Retrieve_BelongsTo.spec.ts
delete mode 100644 test/performance/Retrieve_BelongsToMany.spec.ts
delete mode 100644 test/performance/Retrieve_HasMany.spec.ts
delete mode 100644 test/performance/Retrieve_HasManyThrough.spec.ts
delete mode 100644 test/performance/Retrieve_HasOneThrough.spec.ts
delete mode 100644 test/support/Helpers.ts
delete mode 100644 test/unit/VuexORM.spec.ts
delete mode 100644 test/unit/database/Database.spec.ts
delete mode 100644 test/unit/model/Model.spec.ts
delete mode 100644 test/unit/model/Model_Attributes_Boolean.spec.ts
delete mode 100644 test/unit/model/Model_Attributes_Mutators.spec.ts
delete mode 100644 test/unit/model/Model_Attributes_Number.spec.ts
delete mode 100644 test/unit/model/Model_Attributes_String.spec.ts
delete mode 100644 test/unit/model/Model_Relations.spec.ts
delete mode 100644 test/unit/model/Model_Relations_BelongsToMany.spec.ts
delete mode 100644 test/unit/model/Model_Relations_MorphMany.spec.ts
delete mode 100644 test/unit/model/Model_Relations_MorphOne.spec.ts
delete mode 100644 test/unit/model/Model_Relations_MorphTo.spec.ts
delete mode 100644 test/unit/model/Model_Relations_MorphToMany.spec.ts
delete mode 100644 test/unit/model/Model_Relations_MorphedByMany.spec.ts
delete mode 100644 test/unit/model/Model_Serialization.spec.ts
delete mode 100644 test/unit/model/Model_Store.spec.ts
delete mode 100644 test/unit/model/Model_Utilities.spec.ts
delete mode 100644 test/unit/query/Query.spec.ts
delete mode 100644 test/unit/support/Utils.spec.ts
diff --git a/src/attributes/Attribute.ts b/src/attributes/Attribute.ts
deleted file mode 100644
index 866f62d4..00000000
--- a/src/attributes/Attribute.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import Record from '../data/Record'
-import Model from '../model/Model'
-
-export default abstract class Attribute {
- /**
- * The model that this attributes is being registerd.
- */
- model: typeof Model
-
- /**
- * The default value of the field.
- */
- value: any
-
- /**
- * Create a new attribute instance.
- */
- constructor(model: typeof Model) {
- this.model = model
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- abstract make(value: any, parent: Record, key: string): any
-}
diff --git a/src/attributes/contracts/DictionaryMany.ts b/src/attributes/contracts/DictionaryMany.ts
deleted file mode 100644
index 3ff747da..00000000
--- a/src/attributes/contracts/DictionaryMany.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Collection from '../../data/Collection'
-
-export interface DictionaryMany {
- [key: string]: Collection
-}
-
-export default DictionaryMany
diff --git a/src/attributes/contracts/DictionaryOne.ts b/src/attributes/contracts/DictionaryOne.ts
deleted file mode 100644
index fba70b9f..00000000
--- a/src/attributes/contracts/DictionaryOne.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Model from '../../model/Model'
-
-export interface DictionaryOne {
- [key: string]: Model
-}
-
-export default DictionaryOne
diff --git a/src/attributes/contracts/Mutator.ts b/src/attributes/contracts/Mutator.ts
deleted file mode 100644
index 44a5350d..00000000
--- a/src/attributes/contracts/Mutator.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type Mutator = (value: T) => T
-
-export default Mutator
diff --git a/src/attributes/contracts/Mutators.ts b/src/attributes/contracts/Mutators.ts
deleted file mode 100644
index 004f5c61..00000000
--- a/src/attributes/contracts/Mutators.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Mutator from './Mutator'
-
-export interface Mutators {
- [name: string]: Mutator
-}
-
-export default Mutators
diff --git a/src/attributes/index.ts b/src/attributes/index.ts
deleted file mode 100644
index fc70103d..00000000
--- a/src/attributes/index.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import Attribute from './Attribute'
-import Type from './types/Type'
-import Attr from './types/Attr'
-import String from './types/String'
-import Number from './types/Number'
-import Boolean from './types/Boolean'
-import Uid from './types/Uid'
-import Relation from './relations/Relation'
-import HasOne from './relations/HasOne'
-import BelongsTo from './relations/BelongsTo'
-import HasMany from './relations/HasMany'
-import HasManyBy from './relations/HasManyBy'
-import HasOneThrough from './relations/HasOneThrough'
-import HasManyThrough from './relations/HasManyThrough'
-import BelongsToMany from './relations/BelongsToMany'
-import MorphTo from './relations/MorphTo'
-import MorphOne from './relations/MorphOne'
-import MorphMany from './relations/MorphMany'
-import MorphToMany from './relations/MorphToMany'
-import MorphedByMany from './relations/MorphedByMany'
-
-export {
- Attribute,
- Type,
- Attr,
- String,
- Number,
- Boolean,
- Uid,
- Relation,
- HasOne,
- BelongsTo,
- HasMany,
- HasManyBy,
- HasOneThrough,
- HasManyThrough,
- BelongsToMany,
- MorphTo,
- MorphOne,
- MorphMany,
- MorphToMany,
- MorphedByMany
-}
diff --git a/src/attributes/relations/BelongsTo.ts b/src/attributes/relations/BelongsTo.ts
deleted file mode 100644
index d8191e4f..00000000
--- a/src/attributes/relations/BelongsTo.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import DictionaryOne from '../contracts/DictionaryOne'
-import Relation from './Relation'
-
-export default class BelongsTo extends Relation {
- /**
- * The parent model.
- */
- parent: typeof Model
-
- /**
- * The foreign key of the model.
- */
- foreignKey: string
-
- /**
- * The associated key on the parent model.
- */
- ownerKey: string
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- parent: typeof Model | string,
- foreignKey: string,
- ownerKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.parent = this.model.relation(parent)
- this.foreignKey = foreignKey
- this.ownerKey = ownerKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.one(this.parent)
- }
-
- /**
- * Attach the relational key to the given data. For example, when Post
- * belongs to User, it will attach value to the `user_id` field of
- * Post record.
- */
- attach(key: any, record: Record, data: NormalizedData): void {
- // See if the record has the foreign key, if yes, it means the user has
- // provided the key explicitly so do nothing and return.
- if (record[this.foreignKey] !== undefined) {
- return
- }
-
- // If there is no foreign key, let's set it here.
- record[this.foreignKey] =
- data[this.parent.entity] && data[this.parent.entity][key]
- ? data[this.parent.entity][key][this.ownerKey]
- : key
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model | null {
- return this.makeOneRelation(value, this.parent)
- }
-
- /**
- * Load the belongs to relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relation = this.getRelation(query, this.parent.entity, constraints)
-
- this.addEagerConstraints(relation, collection)
-
- this.match(collection, relation.get(), name)
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- private addEagerConstraints(relation: Query, collection: Collection): void {
- relation.whereFk(this.ownerKey, this.getKeys(collection, this.foreignKey))
- }
-
- /**
- * Match the eagerly loaded results to their parents.
- */
- private match(
- collection: Collection,
- relations: Collection,
- name: string
- ): void {
- const dictionary = this.buildDictionary(relations)
-
- collection.forEach((model) => {
- const id = model[this.foreignKey]
- const relation = id !== null ? dictionary[id] : null
-
- model[name] = relation || null
- })
- }
-
- /**
- * Build model dictionary keyed by the relation's foreign key.
- */
- private buildDictionary(relations: Collection): DictionaryOne {
- return relations.reduce((dictionary, relation) => {
- const key = relation[this.ownerKey]
-
- dictionary[key] = relation
-
- return dictionary
- }, {})
- }
-}
diff --git a/src/attributes/relations/BelongsToMany.ts b/src/attributes/relations/BelongsToMany.ts
deleted file mode 100644
index 9858a518..00000000
--- a/src/attributes/relations/BelongsToMany.ts
+++ /dev/null
@@ -1,257 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import Utils from '../../support/Utils'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export interface PivotRecord {
- [entity: string]: {
- [id: string]: {
- $id: string
- [pivotKey: string]: any
- }
- }
-}
-
-export default class BelongsToMany extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The pivot model.
- */
- pivot: typeof Model
-
- /**
- * The foreign key of the parent model.
- */
- foreignPivotKey: string
-
- /**
- * The associated key of the relation.
- */
- relatedPivotKey: string
-
- /**
- * The key name of the parent model.
- */
- parentKey: string
-
- /**
- * The key name of the related model.
- */
- relatedKey: string
-
- /**
- * The key name of the pivot data.
- */
- pivotKey: string = 'pivot'
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- pivot: Entity,
- foreignPivotKey: string,
- relatedPivotKey: string,
- parentKey: string,
- relatedKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.pivot = this.model.relation(pivot)
- this.foreignPivotKey = foreignPivotKey
- this.relatedPivotKey = relatedPivotKey
- this.parentKey = parentKey
- this.relatedKey = relatedKey
- }
-
- /**
- * Specify the custom pivot accessor to use for the relationship.
- */
- as(accessor: string): this {
- this.pivotKey = accessor
-
- return this
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given data. Since belongs to many
- * relationship doesn't have any foreign key, it would do nothing.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the belongs to relationship for the record.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- const pivotQuery = query.newQuery(this.pivot.entity)
-
- this.addEagerConstraintForPivot(pivotQuery, collection)
-
- const pivots = pivotQuery.get()
-
- this.addEagerConstraintForRelated(relatedQuery, pivots)
-
- const relateds = this.mapPivotRelations(pivots, relatedQuery)
-
- collection.forEach((item) => {
- const related = relateds[item[this.parentKey]]
-
- item[name] = related || []
- })
- }
-
- /**
- * Set the constraints for the pivot relation.
- */
- addEagerConstraintForPivot(query: Query, collection: Collection): void {
- query.whereFk(
- this.foreignPivotKey,
- this.getKeys(collection, this.parentKey)
- )
- }
-
- /**
- * Set the constraints for the related relation.
- */
- addEagerConstraintForRelated(query: Query, collection: Collection): void {
- query.whereFk(
- this.relatedKey,
- this.getKeys(collection, this.relatedPivotKey)
- )
- }
-
- /**
- * Create a new indexed map for the pivot relation.
- */
- mapPivotRelations(pivots: Collection, relatedQuery: Query): Records {
- const relations = this.mapManyRelations(relatedQuery.get(), this.relatedKey)
-
- if (relatedQuery.orders.length) {
- return this.mapRelationsByOrders(
- pivots,
- relations,
- this.foreignPivotKey,
- this.relatedPivotKey
- )
- }
-
- return pivots.reduce((records, record) => {
- const id = record[this.foreignPivotKey]
-
- if (!records[id]) {
- records[id] = []
- }
-
- const related = relations.get(record[this.relatedPivotKey])
-
- if (related) {
- records[id] = records[id].concat(
- related.map((model: Record) => {
- model[this.pivotKey] = record
- return model
- })
- )
- }
-
- return records
- }, {})
- }
-
- /**
- * Create pivot records for the given records if needed.
- */
- createPivots(
- parent: typeof Model,
- data: NormalizedData,
- key: string
- ): NormalizedData {
- if (!Utils.isArray(this.pivot.primaryKey)) return data
-
- Utils.forOwn(data[parent.entity], (record) => {
- const related = record[key]
-
- if (related === undefined || related.length === 0) {
- return
- }
-
- this.createPivotRecord(data, record, related)
- })
-
- return data
- }
-
- /**
- * Create a pivot record.
- */
- createPivotRecord(
- data: NormalizedData,
- record: Record,
- related: any[]
- ): void {
- related.forEach((id) => {
- const parentId = record[this.parentKey]
- const relatedId = data[this.related.entity][id][this.relatedKey]
- const pivotKey = JSON.stringify([
- this.pivot.primaryKey[0] === this.foreignPivotKey
- ? parentId
- : relatedId,
- this.pivot.primaryKey[1] === this.foreignPivotKey ? parentId : relatedId
- ])
- const pivotRecord = data[this.pivot.entity]
- ? data[this.pivot.entity][pivotKey]
- : {}
- const pivotData = data[this.related.entity][id][this.pivotKey] || {}
-
- data[this.pivot.entity] = {
- ...data[this.pivot.entity],
-
- [pivotKey]: {
- ...pivotRecord,
- ...pivotData,
- $id: pivotKey,
- [this.foreignPivotKey]: parentId,
- [this.relatedPivotKey]: relatedId
- }
- }
- })
- }
-}
diff --git a/src/attributes/relations/HasMany.ts b/src/attributes/relations/HasMany.ts
deleted file mode 100644
index 8e8b9244..00000000
--- a/src/attributes/relations/HasMany.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import DictionaryMany from '../contracts/DictionaryMany'
-import Relation from './Relation'
-
-export default class HasMany extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The foreign key of the related model.
- */
- foreignKey: string
-
- /**
- * The local key of the model.
- */
- localKey: string
-
- /**
- * Create a new has many instance.
- */
- constructor(
- model: typeof Model,
- related: typeof Model | string,
- foreignKey: string,
- localKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.foreignKey = foreignKey
- this.localKey = localKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given data.
- */
- attach(key: any, record: Record, data: NormalizedData): void {
- key.forEach((index: any) => {
- const related = data[this.related.entity]
-
- if (
- !related ||
- !related[index] ||
- related[index][this.foreignKey] !== undefined
- ) {
- return
- }
-
- related[index][this.foreignKey] = record[this.localKey]
- })
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the has many relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relation = this.getRelation(query, this.related.entity, constraints)
-
- this.addEagerConstraints(relation, collection)
-
- this.match(collection, relation.get(), name)
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- private addEagerConstraints(relation: Query, collection: Collection): void {
- relation.whereFk(this.foreignKey, this.getKeys(collection, this.localKey))
- }
-
- /**
- * Match the eagerly loaded results to their parents.
- */
- private match(
- collection: Collection,
- relations: Collection,
- name: string
- ): void {
- const dictionary = this.buildDictionary(relations)
-
- collection.forEach((model) => {
- const id = model[this.localKey]
- const relation = dictionary[id]
-
- model[name] = relation || []
- })
- }
-
- /**
- * Build model dictionary keyed by the relation's foreign key.
- */
- private buildDictionary(relations: Collection): DictionaryMany {
- return relations.reduce((dictionary, relation) => {
- const key = relation[this.foreignKey]
-
- if (!dictionary[key]) {
- dictionary[key] = []
- }
-
- dictionary[key].push(relation)
-
- return dictionary
- }, {})
- }
-}
diff --git a/src/attributes/relations/HasManyBy.ts b/src/attributes/relations/HasManyBy.ts
deleted file mode 100644
index ca06ed28..00000000
--- a/src/attributes/relations/HasManyBy.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export default class HasManyBy extends Relation {
- /**
- * The related model.
- */
- parent: typeof Model
-
- /**
- * The foreign key of the model.
- */
- foreignKey: string
-
- /**
- * The associated key on the parent model.
- */
- ownerKey: string
-
- /**
- * Create a new has many by instance.
- */
- constructor(
- model: typeof Model,
- parent: typeof Model | string,
- foreignKey: string,
- ownerKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.parent = this.model.relation(parent)
- this.foreignKey = foreignKey
- this.ownerKey = ownerKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.parent)
- }
-
- /**
- * Attach the relational key to the given data.
- */
- attach(key: any, record: Record, _data: NormalizedData): void {
- if (key.length === 0) {
- return
- }
-
- record[this.foreignKey] = key.map((parentId: any) => {
- return this.parent.getIdFromRecord(_data[this.parent.entity][parentId])
- })
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.parent)
- }
-
- /**
- * Load the has many by relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.parent.entity,
- constraints
- )
-
- this.addConstraintForHasManyBy(relatedQuery, collection)
-
- const relations = this.mapSingleRelations(relatedQuery.get(), this.ownerKey)
-
- collection.forEach((item) => {
- const related = this.getRelatedRecords(relations, item[this.foreignKey])
-
- item[name] = related
- })
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- addConstraintForHasManyBy(query: Query, collection: Collection): void {
- const keys = collection.reduce((keys, item) => {
- return keys.concat(item[this.foreignKey])
- }, [] as string[])
-
- query.where(this.ownerKey, keys)
- }
-
- /**
- * Get related records.
- */
- getRelatedRecords(relations: Map, keys: string[]): Record[] {
- const records: Record[] = []
-
- relations.forEach((record, id) => {
- if (keys.indexOf(id) !== -1) {
- records.push(record)
- }
- })
-
- return records
- }
-}
diff --git a/src/attributes/relations/HasManyThrough.ts b/src/attributes/relations/HasManyThrough.ts
deleted file mode 100644
index 678f28b5..00000000
--- a/src/attributes/relations/HasManyThrough.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class HasManyThrough extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The "through" parent model.
- */
- through: typeof Model
-
- /**
- * The near key on the relationship.
- */
- firstKey: string
-
- /**
- * The far key on the relationship.
- */
- secondKey: string
-
- /**
- * The local key on the relationship.
- */
- localKey: string
-
- /**
- * The local key on the intermediary model.
- */
- secondLocalKey: string
-
- /**
- * Create a new has many through instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- through: Entity,
- firstKey: string,
- secondKey: string,
- localKey: string,
- secondLocalKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.through = this.model.relation(through)
- this.firstKey = firstKey
- this.secondKey = secondKey
- this.localKey = localKey
- this.secondLocalKey = secondLocalKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given data. Since has many through
- * relationship doesn't have any foreign key, it would do nothing.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the has many through relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- const throughQuery = query.newQuery(this.through.entity)
-
- this.addEagerConstraintForThrough(throughQuery, collection)
-
- const throughs = throughQuery.get()
-
- this.addEagerConstraintForRelated(relatedQuery, throughs)
-
- const relateds = this.mapThroughRelations(throughs, relatedQuery)
-
- collection.forEach((item) => {
- const related = relateds[item[this.localKey]]
-
- item[name] = related || []
- })
- }
-
- /**
- * Set the constraints for the through relation.
- */
- addEagerConstraintForThrough(query: Query, collection: Collection): void {
- query.where(this.firstKey, this.getKeys(collection, this.localKey))
- }
-
- /**
- * Set the constraints for the related relation.
- */
- addEagerConstraintForRelated(query: Query, collection: Collection): void {
- query.where(this.secondKey, this.getKeys(collection, this.secondLocalKey))
- }
-
- /**
- * Create a new indexed map for the through relation.
- */
- mapThroughRelations(throughs: Collection, relatedQuery: Query): Records {
- const relations = this.mapManyRelations(relatedQuery.get(), this.secondKey)
-
- return throughs.reduce((records, record) => {
- const id = record[this.firstKey]
-
- if (!records[id]) {
- records[id] = []
- }
-
- const related = relations.get(record[this.secondLocalKey])
-
- if (related === undefined) {
- return records
- }
-
- records[id] = records[id].concat(related)
-
- return records
- }, {})
- }
-}
diff --git a/src/attributes/relations/HasOne.ts b/src/attributes/relations/HasOne.ts
deleted file mode 100644
index 550c4ab2..00000000
--- a/src/attributes/relations/HasOne.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import DictionaryOne from '../contracts/DictionaryOne'
-import Relation from './Relation'
-
-export default class HasOne extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The foreign key of the related model.
- */
- foreignKey: string
-
- /**
- * The local key of the model.
- */
- localKey: string
-
- /**
- * Create a new has one instance.
- */
- constructor(
- model: typeof Model,
- related: typeof Model | string,
- foreignKey: string,
- localKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.foreignKey = foreignKey
- this.localKey = localKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.one(this.related)
- }
-
- /**
- * Attach the relational key to the related data. For example,
- * when User has one Phone, it will attach value to the
- * `user_id` field of Phone record.
- */
- attach(key: any, record: Record, data: NormalizedData): void {
- // Check if the record has local key set. If not, set the local key to be
- // the id value. This happens if the user defines the custom local key
- // and didn't include it in the data being normalized.
- if (!record[this.localKey]) {
- record[this.localKey] = this.model.getIndexIdFromRecord(record)
- }
-
- // Then set the foreign key of the related record if it exists to be the
- // local key of this record.
- const related = data[this.related.entity] && data[this.related.entity][key]
-
- if (related) {
- related[this.foreignKey] = record[this.localKey]
- }
- }
-
- /**
- * Make value to be set to model property. This method is used when
- * instantiating a model or creating a plain object from a model.
- */
- make(value: any, _parent: Record, _key: string): Model | null {
- return this.makeOneRelation(value, this.related)
- }
-
- /**
- * Load the has one relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relation = this.getRelation(query, this.related.entity, constraints)
-
- this.addEagerConstraints(relation, collection)
-
- this.match(collection, relation.get(), name)
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- private addEagerConstraints(relation: Query, collection: Collection): void {
- relation.whereFk(this.foreignKey, this.getKeys(collection, this.localKey))
- }
-
- /**
- * Match the eagerly loaded results to their parents.
- */
- private match(
- collection: Collection,
- relations: Collection,
- name: string
- ): void {
- const dictionary = this.buildDictionary(relations)
-
- collection.forEach((model) => {
- const id = model[this.localKey]
- const relation = dictionary[id]
-
- model[name] = relation || null
- })
- }
-
- /**
- * Build model dictionary keyed by the relation's foreign key.
- */
- private buildDictionary(relations: Collection): DictionaryOne {
- return relations.reduce((dictionary, relation) => {
- const key = relation[this.foreignKey]
-
- dictionary[key] = relation
-
- return dictionary
- }, {})
- }
-}
diff --git a/src/attributes/relations/HasOneThrough.ts b/src/attributes/relations/HasOneThrough.ts
deleted file mode 100644
index 17547306..00000000
--- a/src/attributes/relations/HasOneThrough.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class HasOneThrough extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The "through" parent model.
- */
- through: typeof Model
-
- /**
- * The near key on the relation.
- */
- firstKey: string
-
- /**
- * The far key on the relation.
- */
- secondKey: string
-
- /**
- * The local key on the relation.
- */
- localKey: string
-
- /**
- * The local key on the intermediary model.
- */
- secondLocalKey: string
-
- /**
- * Create a new relation instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- through: Entity,
- firstKey: string,
- secondKey: string,
- localKey: string,
- secondLocalKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.through = this.model.relation(through)
- this.firstKey = firstKey
- this.secondKey = secondKey
- this.localKey = localKey
- this.secondLocalKey = secondLocalKey
- }
-
- /**
- * Define the normalizr schema for the relation.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.one(this.related)
- }
-
- /**
- * Since the relation doesn't have a foreign key, there is no relational key
- * to attach to the given data.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model | null {
- return this.makeOneRelation(value, this.related)
- }
-
- /**
- * Load the relation for the given collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- const throughQuery = query.newQuery(this.through.entity)
-
- this.addEagerConstraintForThrough(throughQuery, collection)
-
- const through = throughQuery.get()
-
- this.addEagerConstraintForRelated(relatedQuery, through)
-
- const related = this.mapThroughRelations(through, relatedQuery)
-
- collection.forEach((item) => {
- const relation = related[item[this.localKey]]
-
- item[name] = relation || null
- })
- }
-
- /**
- * Set the constraints for the "through" relation.
- */
- addEagerConstraintForThrough(query: Query, collection: Collection): void {
- query.where(this.firstKey, this.getKeys(collection, this.localKey))
- }
-
- /**
- * Set the constraints for the "related" relation.
- */
- addEagerConstraintForRelated(query: Query, collection: Collection): void {
- query.where(this.secondKey, this.getKeys(collection, this.secondLocalKey))
- }
-
- /**
- * Create a new indexed map for the "through" relation.
- */
- mapThroughRelations(through: Collection, relatedQuery: Query): Records {
- const relations = this.mapSingleRelations(
- relatedQuery.get(),
- this.secondKey
- )
-
- return through.reduce((records, record) => {
- const id = record[this.firstKey]
-
- const related = relations.get(record[this.secondLocalKey])
-
- records[id] = related || null
-
- return records
- }, {})
- }
-}
diff --git a/src/attributes/relations/MorphMany.ts b/src/attributes/relations/MorphMany.ts
deleted file mode 100644
index 80248806..00000000
--- a/src/attributes/relations/MorphMany.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class MorphMany extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The field name that contains id of the parent model.
- */
- id: string
-
- /**
- * The field name that contains type of the parent model.
- */
- type: string
-
- /**
- * The local key of the model.
- */
- localKey: string
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- id: string,
- type: string,
- localKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.id = id
- this.type = type
- this.localKey = localKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given data.
- */
- attach(key: any, record: Record, data: NormalizedData): void {
- const relatedItems = data[this.related.entity]
-
- key.forEach((id: any) => {
- const relatedItem = relatedItems[id]
-
- relatedItem[this.id] =
- relatedItem[this.id] || this.related.getIdFromRecord(record)
- relatedItem[this.type] = relatedItem[this.type] || this.model.entity
- })
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the morph many relationship for the record.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- this.addEagerConstraintForMorphMany(relatedQuery, collection, query.entity)
-
- const relations = this.mapManyRelations(relatedQuery.get(), this.id)
-
- collection.forEach((item) => {
- const related = relations.get(item[this.localKey])
-
- item[name] = related || []
- })
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- addEagerConstraintForMorphMany(
- query: Query,
- collection: Collection,
- type: string
- ): void {
- query
- .whereFk(this.type, type)
- .whereFk(this.id, this.getKeys(collection, this.localKey))
- }
-}
diff --git a/src/attributes/relations/MorphOne.ts b/src/attributes/relations/MorphOne.ts
deleted file mode 100644
index 15671a2a..00000000
--- a/src/attributes/relations/MorphOne.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class MorphOne extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The field name that contains id of the parent model.
- */
- id: string
-
- /**
- * The field name that contains type of the parent model.
- */
- type: string
-
- /**
- * The local key of the model.
- */
- localKey: string
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- id: string,
- type: string,
- localKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.id = id
- this.type = type
- this.localKey = localKey
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.one(this.related)
- }
-
- /**
- * Attach the relational key to the given data.
- */
- attach(key: any, record: Record, data: NormalizedData): void {
- const relatedRecord = data[this.related.entity][key]
-
- relatedRecord[this.id] =
- relatedRecord[this.id] || this.related.getIdFromRecord(record)
- relatedRecord[this.type] = relatedRecord[this.type] || this.model.entity
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model | null {
- return this.makeOneRelation(value, this.related)
- }
-
- /**
- * Load the morph many relationship for the record.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- this.addEagerConstraintForMorphOne(relatedQuery, collection, query.entity)
-
- const relations = this.mapSingleRelations(relatedQuery.get(), this.id)
-
- collection.forEach((item) => {
- const related = relations.get(item[this.localKey])
-
- item[name] = related || null
- })
- }
-
- /**
- * Set the constraints for an eager load of the relation.
- */
- addEagerConstraintForMorphOne(
- query: Query,
- collection: Collection,
- type: string
- ): void {
- query
- .whereFk(this.type, type)
- .whereFk(this.id, this.getKeys(collection, this.localKey))
- }
-}
diff --git a/src/attributes/relations/MorphTo.ts b/src/attributes/relations/MorphTo.ts
deleted file mode 100644
index df5a90b7..00000000
--- a/src/attributes/relations/MorphTo.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Schema from '../../schema/Schema'
-import { Record, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class MorphTo extends Relation {
- /**
- * The field name that contains id of the parent model.
- */
- id: string
-
- /**
- * The field name that contains type of the parent model.
- */
- type: string
-
- /**
- * Create a new morph to instance.
- */
- constructor(model: typeof Model, id: string, type: string) {
- super(model) /* istanbul ignore next */
-
- this.id = id
- this.type = type
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.union((_value, parentValue) => parentValue[this.type])
- }
-
- /**
- * Attach the relational key to the given record. Since morph to
- * relationship doesn't have any foreign key, it would do nothing.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, parent: Record, _key: string): Model | null {
- const related = parent[this.type] as string
-
- try {
- const model = this.model.relation(related)
- return this.makeOneRelation(value, model)
- } catch {
- return null
- }
- }
-
- /**
- * Load the morph to relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const types = this.getTypes(collection)
-
- const relations = types.reduce((related, type) => {
- const relatedQuery = this.getRelation(query, type, constraints)
-
- related[type] = this.mapSingleRelations(relatedQuery.get(), '$id')
-
- return related
- }, {})
-
- collection.forEach((item) => {
- const id = item[this.id]
- const type = item[this.type]
- const related = relations[type].get(String(id))
-
- item[name] = related || null
- })
- }
-
- /**
- * Get all types from the collection.
- */
- getTypes(collection: Collection): string[] {
- return collection.reduce((types, item) => {
- const type = item[this.type]
-
- !types.includes(type) && types.push(type)
-
- return types
- }, [] as string[])
- }
-}
diff --git a/src/attributes/relations/MorphToMany.ts b/src/attributes/relations/MorphToMany.ts
deleted file mode 100644
index a4982c3c..00000000
--- a/src/attributes/relations/MorphToMany.ts
+++ /dev/null
@@ -1,258 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Utils from '../../support/Utils'
-import Schema from '../../schema/Schema'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class MorphToMany extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The pivot model.
- */
- pivot: typeof Model
-
- /**
- * The field name that contains id of the related model.
- */
- relatedId: string
-
- /**
- * The field name that contains id of the parent model.
- */
- id: string
-
- /**
- * The field name that contains type of the parent model.
- */
- type: string
-
- /**
- * The key name of the parent model.
- */
- parentKey: string
-
- /**
- * The key name of the related model.
- */
- relatedKey: string
-
- /**
- * The key name of the pivot data.
- */
- pivotKey: string = 'pivot'
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- pivot: Entity,
- relatedId: string,
- id: string,
- type: string,
- parentKey: string,
- relatedKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.pivot = this.model.relation(pivot)
- this.relatedId = relatedId
- this.id = id
- this.type = type
- this.parentKey = parentKey
- this.relatedKey = relatedKey
- }
-
- /**
- * Specify the custom pivot accessor to use for the relationship.
- */
- as(accessor: string): this {
- this.pivotKey = accessor
-
- return this
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given record. Since morph to many
- * relationship doesn't have any foreign key, it would do nothing.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the morph to many relationship for the collection.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- const pivotQuery = query.newQuery(this.pivot.entity)
-
- this.addEagerConstraintForPivot(pivotQuery, collection, query.entity)
-
- const pivots = pivotQuery.get()
-
- this.addEagerConstraintForRelated(relatedQuery, pivots)
-
- const relateds = this.mapPivotRelations(pivots, relatedQuery)
-
- collection.forEach((item) => {
- const related = relateds[item[this.parentKey]]
-
- item[name] = related || []
- })
- }
-
- /**
- * Set the constraints for the pivot relation.
- */
- addEagerConstraintForPivot(
- query: Query,
- collection: Collection,
- type: string
- ): void {
- query
- .whereFk(this.type, type)
- .whereFk(this.id, this.getKeys(collection, this.parentKey))
- }
-
- /**
- * Set the constraints for the related relation.
- */
- addEagerConstraintForRelated(query: Query, collection: Collection): void {
- query.whereFk(this.relatedKey, this.getKeys(collection, this.relatedId))
- }
-
- /**
- * Create a new indexed map for the pivot relation.
- */
- mapPivotRelations(pivots: Collection, relatedQuery: Query): Records {
- const relations = this.mapManyRelations(relatedQuery.get(), this.relatedKey)
-
- if (relatedQuery.orders.length) {
- return this.mapRelationsByOrders(
- pivots,
- relations,
- this.id,
- this.relatedId
- )
- }
-
- return pivots.reduce((records, record) => {
- const id = record[this.id]
-
- if (!records[id]) {
- records[id] = []
- }
-
- const related = relations.get(record[this.relatedId])
-
- /* istanbul ignore if */
- if (related === undefined || related.length === 0) {
- return records
- }
-
- records[id] = records[id].concat(
- related.map((model: Record) => {
- model[this.pivotKey] = record
- return model
- })
- )
-
- return records
- }, {})
- }
-
- /**
- * Create pivot records for the given records if needed.
- */
- createPivots(
- parent: typeof Model,
- data: NormalizedData,
- key: string
- ): NormalizedData {
- Utils.forOwn(data[parent.entity], (record) => {
- const relatedIds = parent
- .query()
- .newQuery(this.pivot.entity)
- .where(this.id, record[this.parentKey])
- .where(this.type, parent.entity)
- .get()
-
- const relateds = (record[key] || []).filter(
- (relatedId: any) => !relatedIds.includes(relatedId)
- )
-
- if (!Utils.isArray(relateds) || relateds.length === 0) {
- return
- }
-
- this.createPivotRecord(parent, data, record, relateds)
- })
-
- return data
- }
-
- /**
- * Create a pivot record.
- */
- createPivotRecord(
- parent: typeof Model,
- data: NormalizedData,
- record: Record,
- related: any[]
- ): void {
- related.forEach((id) => {
- const parentId = record[this.parentKey]
- const relatedId = data[this.related.entity][id][this.relatedKey]
- const pivotKey = `${parentId}_${id}_${parent.entity}`
- const pivotData = data[this.related.entity][id][this.pivotKey] || {}
-
- data[this.pivot.entity] = {
- ...data[this.pivot.entity],
-
- [pivotKey]: {
- ...pivotData,
- $id: pivotKey,
- [this.relatedId]: relatedId,
- [this.id]: parentId,
- [this.type]: parent.entity
- }
- }
- })
- }
-}
diff --git a/src/attributes/relations/MorphedByMany.ts b/src/attributes/relations/MorphedByMany.ts
deleted file mode 100644
index 3e78c2f2..00000000
--- a/src/attributes/relations/MorphedByMany.ts
+++ /dev/null
@@ -1,248 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import Utils from '../../support/Utils'
-import Schema from '../../schema/Schema'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Relation from './Relation'
-
-export type Entity = typeof Model | string
-
-export default class MorphedByMany extends Relation {
- /**
- * The related model.
- */
- related: typeof Model
-
- /**
- * The pivot model.
- */
- pivot: typeof Model
-
- /**
- * The field name that contains id of the related model.
- */
- relatedId: string
-
- /**
- * The field name that contains id of the parent model.
- */
- id: string
-
- /**
- * The field name that contains type of the parent model.
- */
- type: string
-
- /**
- * The key name of the parent model.
- */
- parentKey: string
-
- /**
- * The key name of the related model.
- */
- relatedKey: string
-
- /**
- * The key name of the pivot data.
- */
- pivotKey: string = 'pivot'
-
- /**
- * Create a new belongs to instance.
- */
- constructor(
- model: typeof Model,
- related: Entity,
- pivot: Entity,
- relatedId: string,
- id: string,
- type: string,
- parentKey: string,
- relatedKey: string
- ) {
- super(model) /* istanbul ignore next */
-
- this.related = this.model.relation(related)
- this.pivot = this.model.relation(pivot)
- this.relatedId = relatedId
- this.id = id
- this.type = type
- this.parentKey = parentKey
- this.relatedKey = relatedKey
- }
-
- /**
- * Specify the custom pivot accessor to use for the relationship.
- */
- as(accessor: string): this {
- this.pivotKey = accessor
-
- return this
- }
-
- /**
- * Define the normalizr schema for the relationship.
- */
- define(schema: Schema): NormalizrSchema {
- return schema.many(this.related)
- }
-
- /**
- * Attach the relational key to the given data. Since morphed by many
- * relationship doesn't have any foreign key, it would do nothing.
- */
- attach(_key: any, _record: Record, _data: NormalizedData): void {
- return
- }
-
- /**
- * Make value to be set to model property. This method is used when
- * instantiating a model or creating a plain object from a model.
- */
- make(value: any, _parent: Record, _key: string): Model[] {
- return this.makeManyRelation(value, this.related)
- }
-
- /**
- * Load the morph many relationship for the record.
- */
- load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void {
- const relatedQuery = this.getRelation(
- query,
- this.related.entity,
- constraints
- )
-
- const pivotQuery = query.newQuery(this.pivot.entity)
-
- this.addEagerConstraintForPivot(pivotQuery, collection, this.related.entity)
-
- const pivots = pivotQuery.get()
-
- this.addEagerConstraintForRelated(relatedQuery, pivots)
-
- const relateds = this.mapPivotRelations(pivots, relatedQuery)
-
- collection.forEach((item) => {
- const related = relateds[item[this.parentKey]]
-
- item[name] = related || []
- })
- }
-
- /**
- * Set the constraints for the pivot relation.
- */
- addEagerConstraintForPivot(
- query: Query,
- collection: Collection,
- type: string
- ): void {
- query
- .whereFk(this.type, type)
- .whereFk(this.relatedId, this.getKeys(collection, this.parentKey))
- }
-
- /**
- * Set the constraints for the related relation.
- */
- addEagerConstraintForRelated(query: Query, collection: Collection): void {
- query.whereFk(this.relatedKey, this.getKeys(collection, this.id))
- }
-
- /**
- * Create a new indexed map for the pivot relation.
- */
- mapPivotRelations(pivots: Collection, relatedQuery: Query): Records {
- const relations = this.mapManyRelations(relatedQuery.get(), this.relatedKey)
-
- if (relatedQuery.orders.length) {
- return this.mapRelationsByOrders(
- pivots,
- relations,
- this.relatedId,
- this.id
- )
- }
-
- return pivots.reduce((records, record) => {
- const id = record[this.relatedId]
-
- if (!records[id]) {
- records[id] = []
- }
-
- const related = relations.get(record[this.id])
-
- /* istanbul ignore if */
- if (related === undefined || related.length === 0) {
- return records
- }
-
- records[id] = records[id].concat(
- related.map((model: Record) => {
- model[this.pivotKey] = record
- return model
- })
- )
-
- return records
- }, {})
- }
-
- /**
- * Create pivot records for the given records if needed.
- */
- createPivots(
- parent: typeof Model,
- data: NormalizedData,
- key: string
- ): NormalizedData {
- Utils.forOwn(data[parent.entity], (record) => {
- const related = record[key]
-
- if (!Utils.isArray(related)) {
- return
- }
-
- this.createPivotRecord(data, record, related)
- })
-
- return data
- }
-
- /**
- * Create a pivot record.
- */
- createPivotRecord(
- data: NormalizedData,
- record: Record,
- related: any[]
- ): void {
- related.forEach((id) => {
- const parentId = record[this.parentKey]
- const pivotKey = `${id}_${parentId}_${this.related.entity}`
- const pivotData = data[this.related.entity][id][this.pivotKey] || {}
-
- data[this.pivot.entity] = {
- ...data[this.pivot.entity],
-
- [pivotKey]: {
- ...pivotData,
- $id: pivotKey,
- [this.relatedId]: parentId,
- [this.id]: this.model.getIdFromRecord(data[this.related.entity][id]),
- [this.type]: this.related.entity
- }
- }
- })
- }
-}
diff --git a/src/attributes/relations/Relation.ts b/src/attributes/relations/Relation.ts
deleted file mode 100644
index 6a45b81b..00000000
--- a/src/attributes/relations/Relation.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import { Schema as NormalizrSchema } from 'normalizr'
-import { isArray } from '../../support/Utils'
-import Schema from '../../schema/Schema'
-import { Record, Records, NormalizedData, Collection } from '../../data'
-import Model from '../../model/Model'
-import Query from '../../query/Query'
-import Constraint from '../../query/contracts/RelationshipConstraint'
-import Attribute from '../Attribute'
-
-export default abstract class Relation extends Attribute {
- /**
- * Define the normalizr schema for the relationship.
- */
- abstract define(schema: Schema): NormalizrSchema
-
- /**
- * Attach the relational key to the given data. Basically, this method
- * should attach any missing foreign keys to the normalized data.
- */
- abstract attach(key: any, record: Record, data: NormalizedData): void
-
- /**
- * Load relationship records.
- */
- abstract load(
- query: Query,
- collection: Collection,
- name: string,
- constraints: Constraint[]
- ): void
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- abstract make(value: any, parent: Record, key: string): Model | Model[] | null
-
- /**
- * Get relation query instance with constraint attached.
- */
- protected getRelation(
- query: Query,
- name: string,
- constraints: Constraint[]
- ): Query {
- const relation = query.newQuery(name)
-
- constraints.forEach((constraint) => {
- constraint(relation)
- })
-
- return relation
- }
-
- /**
- * Get specified keys from the given collection.
- */
- protected getKeys(collection: Collection, key: string): string[] {
- return collection.reduce((models, model) => {
- if (model[key] === null || model[key] === undefined) {
- return models
- }
-
- models.push(model[key] as string)
-
- return models
- }, [])
- }
-
- /**
- * Create a new indexed map for the single relation by specified key.
- */
- mapSingleRelations(collection: Record[], key: string): Map {
- const relations = new Map()
-
- collection.forEach((record) => {
- const id = record[key]
-
- !relations.get(id) && relations.set(id, record)
- })
-
- return relations
- }
-
- /**
- * Create a new indexed map for the many relation by specified key.
- */
- mapManyRelations(collection: Record[], key: string): Map {
- const relations = new Map()
-
- collection.forEach((record) => {
- const id = record[key]
-
- let ownerKeys = relations.get(id)
-
- if (!ownerKeys) {
- ownerKeys = []
- relations.set(id, ownerKeys)
- }
-
- ownerKeys.push(record)
- })
-
- return relations
- }
-
- /**
- * Create a new indexed map for relations with order constraints.
- */
- mapRelationsByOrders(
- collection: Collection,
- relations: Map,
- ownerKey: string,
- relationKey: string
- ): Records {
- const records: Records = {}
-
- relations.forEach((related, id) => {
- collection
- .filter((record) => record[relationKey] === id)
- .forEach((record) => {
- const id = record[ownerKey]
-
- if (!records[id]) {
- records[id] = []
- }
-
- records[id] = records[id].concat(related)
- })
- })
-
- return records
- }
-
- /**
- * Check if the given record is a single relation, which is an object.
- */
- isOneRelation(record: any): boolean {
- if (!isArray(record) && record !== null && typeof record === 'object') {
- return true
- }
-
- return false
- }
-
- /**
- * Check if the given records is a many relation, which is an array
- * of object.
- */
- isManyRelation(records: any): boolean {
- if (!isArray(records)) {
- return false
- }
-
- if (records.length < 1) {
- return false
- }
-
- return true
- }
-
- /**
- * Wrap the given object into a model instance.
- */
- makeOneRelation(record: any, model: typeof Model): Model | null {
- if (!this.isOneRelation(record)) {
- return null
- }
-
- const relatedModel = model.getModelFromRecord(record) || model
-
- return new relatedModel(record)
- }
-
- /**
- * Wrap the given records into a collection of model instances.
- */
- makeManyRelation(records: any, model: typeof Model): Collection {
- if (!this.isManyRelation(records)) {
- return []
- }
-
- return records
- .filter((record: any) => {
- return this.isOneRelation(record)
- })
- .map((record: Record) => {
- const relatedModel = model.getModelFromRecord(record) || model
-
- return new relatedModel(record)
- })
- }
-}
diff --git a/src/attributes/types/Attr.ts b/src/attributes/types/Attr.ts
deleted file mode 100644
index e6363b5c..00000000
--- a/src/attributes/types/Attr.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import Record from '../../data/Record'
-import Model from '../../model/Model'
-import Mutator from '../contracts/Mutator'
-import Type from './Type'
-
-export default class Attr extends Type {
- /**
- * Create a new attr instance.
- */
- constructor(model: typeof Model, value: any, mutator?: Mutator) {
- /* istanbul ignore next */
- super(model, value, mutator)
- }
-
- /**
- * Make value to be set to model property. This method is used when
- * instantiating a model or creating a plain object from a model.
- */
- make(value: any, _parent: Record, key: string): any {
- value = value !== undefined ? value : this.value
-
- // Default Value might be a function (taking no parameter).
- let localValue = value
-
- if (typeof value === 'function') {
- localValue = value()
- }
-
- return this.mutate(localValue, key)
- }
-}
diff --git a/src/attributes/types/Boolean.ts b/src/attributes/types/Boolean.ts
deleted file mode 100644
index a80132f8..00000000
--- a/src/attributes/types/Boolean.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import Record from '../../data/Record'
-import Model from '../../model/Model'
-import Mutator from '../contracts/Mutator'
-import Type from './Type'
-
-export default class Boolean extends Type {
- /**
- * Create a new number instance.
- */
- constructor(
- model: typeof Model,
- value: boolean,
- mutator?: Mutator
- ) {
- /* istanbul ignore next */
- super(model, value, mutator)
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, key: string): boolean | null {
- return this.mutate(this.fix(value), key)
- }
-
- /**
- * Transform given data to the boolean.
- */
- fix(value: any): boolean | null {
- if (value === undefined) {
- return this.value
- }
-
- if (typeof value === 'boolean') {
- return value
- }
-
- if (typeof value === 'string') {
- if (value.length === 0) {
- return false
- }
-
- const int = parseInt(value, 0)
-
- return isNaN(int) ? true : !!int
- }
-
- if (typeof value === 'number') {
- return !!value
- }
-
- if (value === null && this.isNullable) {
- return value
- }
-
- return false
- }
-}
diff --git a/src/attributes/types/Number.ts b/src/attributes/types/Number.ts
deleted file mode 100644
index 0509416b..00000000
--- a/src/attributes/types/Number.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import Record from '../../data/Record'
-import Model from '../../model/Model'
-import Mutator from '../contracts/Mutator'
-import Type from './Type'
-
-export default class Number extends Type {
- /**
- * Create a new number instance.
- */
- constructor(
- model: typeof Model,
- value: number | null,
- mutator?: Mutator
- ) {
- /* istanbul ignore next */
- super(model, value, mutator)
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, key: string): number | null {
- return this.mutate(this.fix(value), key)
- }
-
- /**
- * Transform given data to the number.
- */
- fix(value: any): number | null {
- if (value === undefined) {
- return this.value
- }
-
- if (typeof value === 'number') {
- return value
- }
-
- if (typeof value === 'string') {
- return parseFloat(value)
- }
-
- if (typeof value === 'boolean') {
- return value ? 1 : 0
- }
-
- if (value === null && this.isNullable) {
- return value
- }
-
- return 0
- }
-}
diff --git a/src/attributes/types/String.ts b/src/attributes/types/String.ts
deleted file mode 100644
index 1ba6202a..00000000
--- a/src/attributes/types/String.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import Record from '../../data/Record'
-import Model from '../../model/Model'
-import Mutator from '../contracts/Mutator'
-import Type from './Type'
-
-export default class String extends Type {
- /**
- * Create a new string instance.
- */
- constructor(
- model: typeof Model,
- value: string | null,
- mutator?: Mutator
- ) {
- /* istanbul ignore next */
- super(model, value, mutator)
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value: any, _parent: Record, key: string): string | null {
- return this.mutate(this.fix(value), key)
- }
-
- /**
- * Convert given value to the string.
- */
- fix(value: any): string | null {
- if (value === undefined) {
- return this.value
- }
-
- if (typeof value === 'string') {
- return value
- }
-
- if (value === null && this.isNullable) {
- return value
- }
-
- return value + ''
- }
-}
diff --git a/src/attributes/types/Type.ts b/src/attributes/types/Type.ts
deleted file mode 100644
index f8ea01bb..00000000
--- a/src/attributes/types/Type.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import Model from '../../model/Model'
-import Mutator from '../contracts/Mutator'
-import Attribute from '../Attribute'
-
-export default abstract class Type extends Attribute {
- /**
- * Whether if the attribute can accept `null` as a value.
- */
- isNullable: boolean = false
-
- /**
- * The mutator for the field.
- */
- mutator?: Mutator
-
- /**
- * Create a new type instance.
- */
- constructor(model: typeof Model, value: any, mutator?: (value: any) => any) {
- super(model) /* istanbul ignore next */
-
- this.value = value
- this.mutator = mutator
- }
-
- /**
- * Set `isNullable` to be `true`.
- */
- nullable(): this {
- this.isNullable = true
-
- return this
- }
-
- /**
- * Mutate the given value by mutator.
- */
- mutate(value: any, key: string): any {
- const mutator = this.mutator || this.model.mutators()[key]
-
- return mutator ? mutator(value) : value
- }
-}
diff --git a/src/attributes/types/Uid.ts b/src/attributes/types/Uid.ts
deleted file mode 100644
index 42ec962c..00000000
--- a/src/attributes/types/Uid.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import UidGenerator from '../../support/Uid'
-import Model from '../../model/Model'
-import Type from './Type'
-
-export default class Uid extends Type {
- /**
- * Create a new uid instance.
- */
- constructor(model: typeof Model, value?: () => string | number) {
- /* istanbul ignore next */
- super(model, value)
- }
-
- /**
- * Convert given value to the appropriate value for the attribute.
- */
- make(value?: any): string | number | null {
- if (typeof value === 'number' || typeof value === 'string') {
- return value
- }
-
- if (typeof this.value === 'function') {
- return this.value()
- }
-
- return UidGenerator.make()
- }
-}
diff --git a/src/connections/Connection.ts b/src/connections/Connection.ts
deleted file mode 100644
index 75ddcb8c..00000000
--- a/src/connections/Connection.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { Store } from 'vuex'
-import { Records, RecordWithId } from '../data'
-import RootState from '../modules/contracts/RootState'
-import State from '../modules/contracts/State'
-
-export default class Connection {
- /**
- * The store instance.
- */
- store: Store
-
- /**
- * The connection name.
- */
- connection: string
-
- /**
- * The entity name.
- */
- entity: string
-
- /**
- * The root state.
- */
- rootState: RootState
-
- /**
- * The entity state.
- */
- state: State
-
- /**
- * Create a new connection instance.
- */
- constructor(store: Store, connection: string, entity: string) {
- this.store = store
- this.connection = connection
- this.entity = entity
- this.rootState = this.store.state[connection]
- this.state = this.rootState[entity]
- }
-
- /**
- * Commit Vuex Mutation.
- */
- private commit(name: string, payload: any): void {
- this.store.commit(`${this.connection}/${name}`, payload)
- }
-
- /**
- * Commit the given record by `new` method.
- */
- new(record: RecordWithId): void {
- this.commit('new', {
- entity: this.entity,
- data: { [record.$id]: record }
- })
- }
-
- /**
- * Insert the given record.
- */
- insert(records: RecordWithId[]): void {
- this.commit('new', {
- entity: this.entity,
- data: this.mapRecordToRecords(records)
- })
- }
-
- /**
- * Insert the given records.
- */
- insertRecords(records: Records): void {
- this.state.data = { ...this.state.data, ...records }
- }
-
- /**
- * Delete records that matches the given id.
- */
- delete(id: string[]): void {
- const data: Records = {}
-
- for (const i in this.state.data) {
- if (!id.includes(i)) {
- data[i] = this.state.data[i]
- }
- }
-
- this.state.data = data
- }
-
- /**
- * Map the given records to `Records` type object.
- */
- private mapRecordToRecords(records: RecordWithId[]): Records {
- return records.reduce((carry, record) => {
- carry[record.$id] = record
- return carry
- }, {})
- }
-}
diff --git a/src/container/Container.ts b/src/container/Container.ts
deleted file mode 100644
index 9b2d170e..00000000
--- a/src/container/Container.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Store } from 'vuex'
-
-export default class Container {
- /**
- * The store instance.
- */
- static store: Store
-
- /**
- * Register the store instance.
- */
- static register(store: Store): void {
- this.store = store
- }
-}
diff --git a/src/data/Collection.ts b/src/data/Collection.ts
deleted file mode 100644
index 3f04dbff..00000000
--- a/src/data/Collection.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import Model from '../model/Model'
-import Instance from './Instance'
-
-export type Collection = Instance[]
-
-export default Collection
diff --git a/src/data/Collections.ts b/src/data/Collections.ts
deleted file mode 100644
index 348392b8..00000000
--- a/src/data/Collections.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Collection from './Collection'
-
-export interface Collections {
- [entity: string]: Collection
-}
-
-export default Collections
diff --git a/src/data/Entities.ts b/src/data/Entities.ts
deleted file mode 100644
index 1e9f3846..00000000
--- a/src/data/Entities.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Instances from './Instances'
-
-export interface Entities {
- [entity: string]: Instances
-}
-
-export default Entities
diff --git a/src/data/Instance.ts b/src/data/Instance.ts
deleted file mode 100644
index 1f09eae6..00000000
--- a/src/data/Instance.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import Model from '../model/Model'
-
-export type Instance = M
-
-export default Instance
diff --git a/src/data/InstanceOf.ts b/src/data/InstanceOf.ts
deleted file mode 100644
index 62e651d3..00000000
--- a/src/data/InstanceOf.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type InstanceOf = T extends new (...args: any[]) => infer R ? R : any
-
-export default InstanceOf
diff --git a/src/data/Instances.ts b/src/data/Instances.ts
deleted file mode 100644
index 2ca12741..00000000
--- a/src/data/Instances.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import Instance from './Instance'
-import Model from '../model/Model'
-
-export interface Instances {
- [id: string]: Instance
-}
-
-export default Instances
diff --git a/src/data/Item.ts b/src/data/Item.ts
deleted file mode 100644
index 2494c73f..00000000
--- a/src/data/Item.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import Model from '../model/Model'
-import Instance from './Instance'
-
-export type Item = Instance | null
-
-export default Item
diff --git a/src/data/NormalizedData.ts b/src/data/NormalizedData.ts
deleted file mode 100644
index 00867086..00000000
--- a/src/data/NormalizedData.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Records from './Records'
-
-export interface NormalizedData {
- [entity: string]: Records
-}
-
-export default NormalizedData
diff --git a/src/data/Record.ts b/src/data/Record.ts
deleted file mode 100644
index ae68fd37..00000000
--- a/src/data/Record.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface Record {
- [field: string]: any
-}
-
-export default Record
diff --git a/src/data/RecordWithId.ts b/src/data/RecordWithId.ts
deleted file mode 100644
index 60c7b94c..00000000
--- a/src/data/RecordWithId.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Record from './Record'
-
-export interface RecordWithId extends Record {
- $id: string
-}
-
-export default RecordWithId
diff --git a/src/data/Records.ts b/src/data/Records.ts
deleted file mode 100644
index b70cb1af..00000000
--- a/src/data/Records.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Record from './Record'
-
-export interface Records {
- [id: string]: Record
-}
-
-export default Records
diff --git a/src/data/index.ts b/src/data/index.ts
deleted file mode 100644
index 19fb4667..00000000
--- a/src/data/index.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import Record from './Record'
-import RecordWithId from './RecordWithId'
-import Records from './Records'
-import NormalizedData from './NormalizedData'
-import Instance from './Instance'
-import Instances from './Instances'
-import InstanceOf from './InstanceOf'
-import Entities from './Entities'
-import Item from './Item'
-import Collection from './Collection'
-import Collections from './Collections'
-
-export {
- Record,
- RecordWithId,
- Records,
- NormalizedData,
- InstanceOf,
- Instance,
- Instances,
- Entities,
- Item,
- Collection,
- Collections
-}
diff --git a/src/database/Database.ts b/src/database/Database.ts
deleted file mode 100644
index 4bb6c97a..00000000
--- a/src/database/Database.ts
+++ /dev/null
@@ -1,403 +0,0 @@
-import { Store, Module, MutationTree } from 'vuex'
-import { mapValues } from '../support/Utils'
-import Schema from '../schema/Schema'
-import Schemas from '../schema/Schemas'
-import Model from '../model/Model'
-import ModuleContract from '../modules/contracts/Module'
-import RootState from '../modules/contracts/RootState'
-import RootGettersContract from '../modules/contracts/RootGetters'
-import RootActionsContract from '../modules/contracts/RootActions'
-import RootMutationsContract from '../modules/contracts/RootMutations'
-import RootGetters from '../modules/RootGetters'
-import RootActions from '../modules/RootActions'
-import RootMutations from '../modules/RootMutations'
-import State from '../modules/contracts/State'
-import GettersContract from '../modules/contracts/Getters'
-import ActionsContract from '../modules/contracts/Actions'
-import Getters from '../modules/Getters'
-import Actions from '../modules/Actions'
-
-export interface Entity {
- name: string
- base: string
- model: typeof Model
- module: Module
-}
-
-export type Models = Record
-export type Modules = Record>
-
-export default class Database {
- /**
- * The Vuex Store instance.
- */
- store!: Store
-
- /**
- * The namespace for the Vuex Module. Vuex ORM will create Vuex Modules from the
- * registered models and modules and define them under this namespace.
- */
- namespace!: string
-
- /**
- * The list of entities. It contains models and modules with its name.
- * The name is going to be the namespace for the Vuex Modules.
- */
- entities: Entity[] = []
-
- /**
- * The hacked models registered to the store.
- */
- hackedModels: Models = {}
-
- /**
- * The normalizr schema.
- */
- schemas: Schemas = {}
-
- /**
- * Whether the database has already been installed to Vuex or not.
- * Model registration steps depend on its value.
- */
- isStarted: boolean = false
-
- /**
- * Initialize the database before a user can start using it.
- */
- start(store: Store, namespace: string): void {
- this.store = store
- this.namespace = namespace
-
- this.registerModules()
- this.createSchema()
-
- this.isStarted = true
- }
-
- /**
- * Register a model and a module to Database.
- */
- register(model: typeof Model, module: Module = {}): void {
- this.checkModelTypeMappingCapability(model)
-
- const entity: Entity = {
- name: model.entity,
- base: model.baseEntity || model.entity,
- model,
- module
- }
-
- this.hackedModels[model.entity] = this.createBindingModel(model)
-
- this.entities.push(entity)
-
- if (this.isStarted) {
- this.registerModule(entity)
- this.registerSchema(entity)
- }
- }
-
- /**
- * Get the model of the given name from the entities list.
- */
- model(model: T): T
- model(model: string): typeof Model
- model(model: typeof Model | string): typeof Model | string {
- const name = typeof model === 'string' ? model : model.entity
- const m = this.models()[name]
-
- if (!m) {
- throw new Error(
- `[Vuex ORM] Could not find the model \`${name}\`. Please check if you ` +
- 'have registered the model to the database.'
- )
- }
-
- return m
- }
-
- /**
- * Get the base model of the given name from the entities list.
- */
- baseModel(model: T): T
- baseModel(model: string): typeof Model
- baseModel(model: typeof Model | string): typeof Model | string {
- const name = typeof model === 'string' ? model : model.entity
- const m = this.baseModels()[name]
-
- if (!m) {
- throw new Error(
- `[Vuex ORM] Could not find the model \`${name}\`. Please check if you ` +
- 'have registered the model to the database.'
- )
- }
-
- return m
- }
-
- /**
- * Get all models from the entities list.
- */
- models(): Models {
- return this.entities.reduce((models, entity) => {
- models[entity.name] = entity.model
- return models
- }, {})
- }
-
- /**
- * Get all base models from the entities list.
- */
- baseModels(): Models {
- return this.entities.reduce((models, entity) => {
- models[entity.name] = this.model(entity.base)
- return models
- }, {})
- }
-
- /**
- * Get the module of the given name from the entities list.
- */
- module(name: string): Module {
- const module = this.modules()[name]
-
- if (!module) {
- throw new Error(
- `[Vuex ORM] Could not find the module \`${name}\`. Please check if you ` +
- 'have registered the module to the database.'
- )
- }
-
- return module
- }
-
- /**
- * Get all modules from the entities list.
- */
- modules(): Modules {
- return this.entities.reduce((modules, entity) => {
- modules[entity.name] = entity.module
- return modules
- }, {})
- }
-
- /**
- * Get the root state from the store.
- */
- getState(): RootState {
- return this.store.state[this.namespace]
- }
-
- /**
- * Create a new model that binds the database.
- *
- * Transpiled classes cannot extend native classes. Implemented a workaround
- * until Babel releases a fix (https://github.com/babel/babel/issues/9367).
- */
- private createBindingModel(model: typeof Model): typeof Model {
- let proxy: typeof Model
-
- try {
- proxy = new Function(
- 'model',
- `
- 'use strict';
- return class ${model.name} extends model {}
- `
- )(model)
- } catch {
- /* istanbul ignore next: rollback (mostly <= IE10) */
- proxy = class extends model {}
-
- /* istanbul ignore next: allocate model name */
- Object.defineProperty(proxy, 'name', { get: () => model.name })
- }
-
- Object.defineProperty(proxy, 'store', {
- value: (): Store => this.store
- })
-
- return proxy
- }
-
- /**
- * Create Vuex Module from the registered entities, and register to
- * the store.
- */
- private registerModules(): void {
- this.store.registerModule(this.namespace, this.createModule())
- }
-
- /**
- * Generate module from the given entity, and register to the store.
- */
- private registerModule(entity: Entity): void {
- this.store.registerModule(
- [this.namespace, entity.name],
- this.createSubModule(entity)
- )
- }
-
- /**
- * Create Vuex Module from the registered entities.
- */
- private createModule(): Module {
- const module = this.createRootModule()
-
- this.entities.forEach((entity) => {
- module.modules[entity.name] = this.createSubModule(entity)
- })
-
- return module
- }
-
- /**
- * Create root module.
- */
- private createRootModule(): ModuleContract {
- return {
- namespaced: true,
- state: this.createRootState(),
- getters: this.createRootGetters(),
- actions: this.createRootActions(),
- mutations: this.createRootMutations(),
- modules: {}
- }
- }
-
- /**
- * Create root state.
- */
- private createRootState(): () => RootState {
- return () => ({ $name: this.namespace })
- }
-
- /**
- * Create root getters. For the getters, we bind the store instance to each
- * function to retrieve database instances within getters. We only need this
- * for the getter since actions and mutations are already bound to store.
- */
- private createRootGetters(): RootGettersContract {
- return mapValues(RootGetters, (_getter, name) => {
- return RootGetters[name].bind(this.store)
- })
- }
-
- /**
- * Create root actions.
- */
- private createRootActions(): RootActionsContract {
- return RootActions
- }
-
- /**
- * Create root mutations.
- */
- private createRootMutations(): RootMutationsContract {
- return RootMutations
- }
-
- /**
- * Create sub module.
- */
- private createSubModule(entity: Entity): Module {
- return {
- namespaced: true,
- state: this.createSubState(entity),
- getters: this.createSubGetters(entity),
- actions: this.createSubActions(entity),
- mutations: this.createSubMutations(entity)
- }
- }
-
- /**
- * Create sub state.
- */
- private createSubState(entity: Entity): () => State {
- const { name, model, module } = entity
-
- const modelState =
- typeof model.state === 'function' ? model.state() : model.state
- const moduleState =
- typeof module.state === 'function' ? module.state() : module.state
-
- return () => ({
- ...modelState,
- ...moduleState,
- $connection: this.namespace,
- $name: name,
- data: {}
- })
- }
-
- /**
- * Create sub getters.
- */
- private createSubGetters(entity: Entity): GettersContract {
- return { ...Getters, ...entity.module.getters }
- }
-
- /**
- * Create sub actions.
- */
- private createSubActions(entity: Entity): ActionsContract {
- return { ...Actions, ...entity.module.actions }
- }
-
- /**
- * Create sub mutations.
- */
- private createSubMutations(entity: Entity): MutationTree {
- return entity.module.mutations ?? {}
- }
-
- /**
- * Create the schema definition from registered entities list and set it to
- * the `schema` property. This schema will be used by the normalizer
- * to normalize data before persisting them to the Vuex Store.
- */
- private createSchema(): void {
- this.entities.forEach((entity) => {
- this.registerSchema(entity)
- })
- }
-
- /**
- * Generate schema from the given entity.
- */
- private registerSchema(entity: Entity): void {
- this.schemas[entity.name] = Schema.create(entity.model)
- }
-
- /**
- * Warn user if the given model is a type of an inherited model that is being
- * defined without overwriting `Model.types()` because the user will not be
- * able to use the type mapping feature in this case.
- */
- private checkModelTypeMappingCapability(model: typeof Model): void {
- // We'll not be logging any warning if it's on a production environment,
- // so let's return here if it is.
- /* istanbul ignore next */
- if (!__DEV__) {
- return
- }
-
- // If the model doesn't have `baseEntity` property set, we'll assume it is
- // not an inherited model so we can stop here.
- if (!model.baseEntity) {
- return
- }
-
- // Now it seems like the model is indeed an inherited model. Let's check if
- // it has `types()` method declared, or we'll warn the user that it's not
- // possible to use type mapping feature.
- const baseModel = this.model(model.baseEntity)
-
- if (baseModel && baseModel.types === Model.types) {
- console.warn(
- `[Vuex ORM] Model \`${model.name}\` extends \`${baseModel.name}\` which doesn't ` +
- 'overwrite Model.types(). You will not be able to use type mapping.'
- )
- }
- }
-}
diff --git a/src/database/HackedDatabase.ts b/src/database/HackedDatabase.ts
deleted file mode 100644
index 71b1302c..00000000
--- a/src/database/HackedDatabase.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import Database from './Database'
-import Model from '../model/Model'
-
-export default class HackedDatabase {
- /**
- * The database instance to look up models.
- */
- database: Database
-
- /**
- * Create a new hacked database.
- */
- constructor(database: Database) {
- this.database = database
- }
-
- /**
- * Get the hacked model of the given name from the entities list.
- */
- model(model: M): M
- model(model: string): typeof Model
- model(model: typeof Model | string): typeof Model | string {
- /* istanbul ignore next */
- const name = typeof model === 'string' ? model : model.entity
-
- return this.database.hackedModels[name]
- }
-}
diff --git a/src/index.cjs.ts b/src/index.cjs.ts
index c0159d6c..c15f26f4 100644
--- a/src/index.cjs.ts
+++ b/src/index.cjs.ts
@@ -1,69 +1 @@
-import './polyfills'
-
-import { install } from './store'
-import { use } from './plugins/use'
-import Container from './container/Container'
-import Database from './database/Database'
-import Model from './model/Model'
-import Query from './query/Query'
-import Attribute from './attributes/Attribute'
-import Type from './attributes/types/Type'
-import Attr from './attributes/types/Attr'
-import String from './attributes/types/String'
-import Number from './attributes/types/Number'
-import Boolean from './attributes/types/Boolean'
-import Uid from './attributes/types/Uid'
-import Relation from './attributes/relations/Relation'
-import HasOne from './attributes/relations/HasOne'
-import BelongsTo from './attributes/relations/BelongsTo'
-import HasMany from './attributes/relations/HasMany'
-import HasManyBy from './attributes/relations/HasManyBy'
-import BelongsToMany from './attributes/relations/BelongsToMany'
-import HasOneThrough from './attributes/relations/HasOneThrough'
-import HasManyThrough from './attributes/relations/HasManyThrough'
-import MorphTo from './attributes/relations/MorphTo'
-import MorphOne from './attributes/relations/MorphOne'
-import MorphMany from './attributes/relations/MorphMany'
-import MorphToMany from './attributes/relations/MorphToMany'
-import MorphedByMany from './attributes/relations/MorphedByMany'
-import Repository from './repository/Repository'
-import Getters from './modules/Getters'
-import Actions from './modules/Actions'
-import RootGetters from './modules/RootGetters'
-import RootActions from './modules/RootActions'
-import RootMutations from './modules/RootMutations'
-
-export default {
- install,
- use,
- Container,
- Database,
- Model,
- Attribute,
- Type,
- Attr,
- String,
- Number,
- Boolean,
- Uid,
- Relation,
- HasOne,
- BelongsTo,
- HasMany,
- HasManyBy,
- BelongsToMany,
- HasOneThrough,
- HasManyThrough,
- MorphTo,
- MorphOne,
- MorphMany,
- MorphToMany,
- MorphedByMany,
- Repository,
- Getters,
- Actions,
- RootGetters,
- RootActions,
- RootMutations,
- Query
-}
+// ...
diff --git a/src/index.ts b/src/index.ts
index bcc101f0..c15f26f4 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,128 +1 @@
-import './types/vuex'
-import './polyfills'
-
-import { install } from './store'
-import { use, PluginComponents } from './plugins/use'
-import Container from './container/Container'
-import Database from './database/Database'
-import Model from './model/Model'
-import Fields from './model/contracts/Fields'
-import Attribute from './attributes/Attribute'
-import Type from './attributes/types/Type'
-import Attr from './attributes/types/Attr'
-import String from './attributes/types/String'
-import Number from './attributes/types/Number'
-import Boolean from './attributes/types/Boolean'
-import Uid from './attributes/types/Uid'
-import Relation from './attributes/relations/Relation'
-import HasOne from './attributes/relations/HasOne'
-import BelongsTo from './attributes/relations/BelongsTo'
-import HasMany from './attributes/relations/HasMany'
-import HasManyBy from './attributes/relations/HasManyBy'
-import BelongsToMany from './attributes/relations/BelongsToMany'
-import HasOneThrough from './attributes/relations/HasOneThrough'
-import HasManyThrough from './attributes/relations/HasManyThrough'
-import MorphTo from './attributes/relations/MorphTo'
-import MorphOne from './attributes/relations/MorphOne'
-import MorphMany from './attributes/relations/MorphMany'
-import MorphToMany from './attributes/relations/MorphToMany'
-import MorphedByMany from './attributes/relations/MorphedByMany'
-import Repository from './repository/Repository'
-import Getters from './modules/Getters'
-import Actions from './modules/Actions'
-import RootGetters from './modules/RootGetters'
-import RootActions from './modules/RootActions'
-import RootMutations from './modules/RootMutations'
-import Query from './query/Query'
-import Record from './data/Record'
-import Records from './data/Records'
-import NormalizedData from './data/NormalizedData'
-import Instance from './data/Instance'
-import Instances from './data/Instances'
-import InstanceOf from './data/InstanceOf'
-import Entities from './data/Entities'
-import Item from './data/Item'
-import Collection from './data/Collection'
-import Collections from './data/Collections'
-
-export {
- install,
- use,
- PluginComponents,
- Container,
- Database,
- Model,
- Fields,
- Attribute,
- Type,
- Attr,
- String,
- Number,
- Boolean,
- Uid,
- Relation,
- HasOne,
- BelongsTo,
- HasMany,
- HasManyBy,
- BelongsToMany,
- HasOneThrough,
- HasManyThrough,
- MorphTo,
- MorphOne,
- MorphMany,
- MorphToMany,
- MorphedByMany,
- Repository,
- Getters,
- Actions,
- RootGetters,
- RootActions,
- RootMutations,
- Query,
- Record,
- Records,
- NormalizedData,
- Instance,
- Instances,
- InstanceOf,
- Entities,
- Item,
- Collection,
- Collections
-}
-
-export default {
- install,
- use,
- Container,
- Database,
- Model,
- Attribute,
- Type,
- Attr,
- String,
- Number,
- Boolean,
- Uid,
- Relation,
- HasOne,
- BelongsTo,
- HasMany,
- HasManyBy,
- BelongsToMany,
- HasOneThrough,
- HasManyThrough,
- MorphTo,
- MorphOne,
- MorphMany,
- MorphToMany,
- MorphedByMany,
- Repository,
- Getters,
- Actions,
- RootGetters,
- RootActions,
- RootMutations,
- Query
-}
+// ...
diff --git a/src/model/Model.ts b/src/model/Model.ts
deleted file mode 100644
index 43f83b2f..00000000
--- a/src/model/Model.ts
+++ /dev/null
@@ -1,1076 +0,0 @@
-import * as Vuex from 'vuex'
-import Utils from '../support/Utils'
-import Uid from '../support/Uid'
-import Container from '../container/Container'
-import Database from '../database/Database'
-import Record from '../data/Record'
-import RecordWithId from '../data/RecordWithId'
-import InstanceOf from '../data/InstanceOf'
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Collections from '../data/Collections'
-import State from '../modules/contracts/State'
-import * as Attributes from '../attributes'
-import Mutator from '../attributes/contracts/Mutator'
-import Mutators from '../attributes/contracts/Mutators'
-import Predicate from '../query/contracts/Predicate'
-import Query from '../query/Query'
-import * as Payloads from '../modules/payloads/Actions'
-import * as PersistOptions from '../modules/options/Actions'
-import Fields from './contracts/Fields'
-import FieldCache from './contracts/FieldCache'
-import ModelState from './contracts/State'
-import InheritanceTypes from './contracts/InheritanceTypes'
-import { toAttributes, toJson } from './Serialize'
-import PayloadBuilder from '../modules/support/PayloadBuilder'
-import { PersistOptions as QueryPersistOptions } from '../query/options'
-import { InsertObject, normalizeInsertPayload } from './support/Payloads'
-
-export default class Model {
- /**
- * The name that is going be used as module name in Vuex Store.
- */
- static entity: string
-
- /**
- * The reference to the base entity name if the class extends a base entity.
- */
- static baseEntity: string
-
- /**
- * The primary key to be used for the model.
- */
- static primaryKey: string | string[] = 'id'
-
- /**
- * The discriminator key to be used for the model when inheritance is used
- */
- static typeKey: string = 'type'
-
- /**
- * Vuex Store state definition.
- */
- static state: ModelState | (() => ModelState) = {}
-
- /**
- * The cached attribute fields of the model.
- */
- static cachedFields: FieldCache
-
- /**
- * The index ID for the model.
- */
- $id: string | null = null
-
- /**
- * Create a new model instance.
- */
- constructor(record?: Record) {
- this.$fill(record)
- }
-
- /**
- * The definition of the fields of the model and its relations.
- */
- static fields(): Fields {
- return {}
- }
-
- /**
- * Create an attr attribute.
- */
- static attr(value: any, mutator?: Mutator): Attributes.Attr {
- return new Attributes.Attr(this, value, mutator)
- }
-
- /**
- * Create a string attribute.
- */
- static string(
- value: any,
- mutator?: Mutator
- ): Attributes.String {
- return new Attributes.String(this, value, mutator)
- }
-
- /**
- * Create a number attribute.
- */
- static number(
- value: any,
- mutator?: Mutator
- ): Attributes.Number {
- return new Attributes.Number(this, value, mutator)
- }
-
- /**
- * Create a boolean attribute.
- */
- static boolean(
- value: any,
- mutator?: Mutator
- ): Attributes.Boolean {
- return new Attributes.Boolean(this, value, mutator)
- }
-
- /**
- * Create an uid attribute.
- */
- static uid(value?: () => string | number): Attributes.Uid {
- return new Attributes.Uid(this, value)
- }
-
- /**
- * @deprecated Use `uid` attribute instead.
- */
- static increment(): Attributes.Uid {
- /* istanbul ignore next */
- if (__DEV__) {
- console.warn(
- '[Vuex ORM] Attribute type `increment` has been deprecated and replaced with `uid`.'
- )
- }
-
- return this.uid()
- }
-
- /**
- * Create a has one relationship.
- */
- static hasOne(
- related: typeof Model | string,
- foreignKey: string,
- localKey?: string
- ): Attributes.HasOne {
- return new Attributes.HasOne(
- this,
- related,
- foreignKey,
- this.localKey(localKey)
- )
- }
-
- /**
- * Create a belongs to relationship.
- */
- static belongsTo(
- parent: typeof Model | string,
- foreignKey: string,
- ownerKey?: string
- ): Attributes.BelongsTo {
- return new Attributes.BelongsTo(
- this,
- parent,
- foreignKey,
- this.relation(parent).localKey(ownerKey)
- )
- }
-
- /**
- * Create a has many relationship.
- */
- static hasMany(
- related: typeof Model | string,
- foreignKey: string,
- localKey?: string
- ): Attributes.HasMany {
- return new Attributes.HasMany(
- this,
- related,
- foreignKey,
- this.localKey(localKey)
- )
- }
-
- /**
- * Create a has many by relationship.
- */
- static hasManyBy(
- parent: typeof Model | string,
- foreignKey: string,
- ownerKey?: string
- ): Attributes.HasManyBy {
- return new Attributes.HasManyBy(
- this,
- parent,
- foreignKey,
- this.relation(parent).localKey(ownerKey)
- )
- }
-
- /**
- * Create a has one through relationship.
- */
- static hasOneThrough(
- related: typeof Model | string,
- through: typeof Model | string,
- firstKey: string,
- secondKey: string,
- localKey?: string,
- secondLocalKey?: string
- ): Attributes.HasOneThrough {
- return new Attributes.HasOneThrough(
- this,
- related,
- through,
- firstKey,
- secondKey,
- this.localKey(localKey),
- this.relation(through).localKey(secondLocalKey)
- )
- }
-
- /**
- * Create a has many through relationship.
- */
- static hasManyThrough(
- related: typeof Model | string,
- through: typeof Model | string,
- firstKey: string,
- secondKey: string,
- localKey?: string,
- secondLocalKey?: string
- ): Attributes.HasManyThrough {
- return new Attributes.HasManyThrough(
- this,
- related,
- through,
- firstKey,
- secondKey,
- this.localKey(localKey),
- this.relation(through).localKey(secondLocalKey)
- )
- }
-
- /**
- * Create a belongs to many relationship.
- */
- static belongsToMany(
- related: typeof Model | string,
- pivot: typeof Model | string,
- foreignPivotKey: string,
- relatedPivotKey: string,
- parentKey?: string,
- relatedKey?: string
- ): Attributes.BelongsToMany {
- return new Attributes.BelongsToMany(
- this,
- related,
- pivot,
- foreignPivotKey,
- relatedPivotKey,
- this.localKey(parentKey),
- this.relation(related).localKey(relatedKey)
- )
- }
-
- /**
- * Create a morph to relationship.
- */
- static morphTo(id: string, type: string): Attributes.MorphTo {
- return new Attributes.MorphTo(this, id, type)
- }
-
- /**
- * Create a morph one relationship.
- */
- static morphOne(
- related: typeof Model | string,
- id: string,
- type: string,
- localKey?: string
- ): Attributes.MorphOne {
- return new Attributes.MorphOne(
- this,
- related,
- id,
- type,
- this.localKey(localKey)
- )
- }
-
- /**
- * Create a morph many relationship.
- */
- static morphMany(
- related: typeof Model | string,
- id: string,
- type: string,
- localKey?: string
- ): Attributes.MorphMany {
- return new Attributes.MorphMany(
- this,
- related,
- id,
- type,
- this.localKey(localKey)
- )
- }
-
- /**
- * Create a morph to many relationship.
- */
- static morphToMany(
- related: typeof Model | string,
- pivot: typeof Model | string,
- relatedId: string,
- id: string,
- type: string,
- parentKey?: string,
- relatedKey?: string
- ): Attributes.MorphToMany {
- return new Attributes.MorphToMany(
- this,
- related,
- pivot,
- relatedId,
- id,
- type,
- this.localKey(parentKey),
- this.relation(related).localKey(relatedKey)
- )
- }
-
- /**
- * Create a morphed by many relationship.
- */
- static morphedByMany(
- related: typeof Model | string,
- pivot: typeof Model | string,
- relatedId: string,
- id: string,
- type: string,
- parentKey?: string,
- relatedKey?: string
- ): Attributes.MorphedByMany {
- return new Attributes.MorphedByMany(
- this,
- related,
- pivot,
- relatedId,
- id,
- type,
- this.localKey(parentKey),
- this.relation(related).localKey(relatedKey)
- )
- }
-
- /**
- * Mutators to mutate matching fields when instantiating the model.
- */
- static mutators(): Mutators {
- return {}
- }
-
- /**
- * Types mapping used to dispatch entities based on their discriminator field
- */
- static types(): InheritanceTypes {
- return {}
- }
-
- /**
- * Get the store instance from the container.
- */
- static store(): Vuex.Store {
- return Container.store
- }
-
- /**
- * Get the database instance from store.
- */
- static database(): Database {
- return this.store().$database
- }
-
- /**
- * Create a namespaced method name for Vuex Module from the given
- * method name.
- */
- static namespace(method: string): string {
- return `${this.database().namespace}/${this.entity}/${method}`
- }
-
- /**
- * Call Vuex Getters.
- */
- static getters(method: string): any {
- return this.store().getters[this.namespace(method)]
- }
-
- /**
- * Dispatch Vuex Action.
- */
- static dispatch(method: string, payload?: any): Promise {
- return this.store().dispatch(this.namespace(method), payload)
- }
-
- /**
- * Commit Vuex Mutation.
- */
- static commit(callback: (state: State) => void) {
- this.store().commit(`${this.database().namespace}/$mutate`, {
- entity: this.entity,
- callback
- })
- }
-
- /**
- * Get the Model schema definition from the cache.
- */
- static getFields(): Fields {
- if (!this.cachedFields) {
- this.cachedFields = {}
- }
-
- if (this.cachedFields[this.entity]) {
- return this.cachedFields[this.entity]
- }
-
- this.cachedFields[this.entity] = this.fields()
-
- return this.cachedFields[this.entity]
- }
-
- /**
- * Get all records.
- */
- static all(this: T): Collection> {
- return this.getters('all')()
- }
-
- /**
- * Find a record.
- */
- static find(
- this: T,
- id: string | number | (number | string)[]
- ): Item> {
- return this.getters('find')(id)
- }
-
- /**
- * Get the record of the given array of ids.
- */
- static findIn(
- this: T,
- idList: (number | string | (number | string)[])[]
- ): Collection> {
- return this.getters('findIn')(idList)
- }
-
- /**
- * Get query instance.
- */
- static query(this: M): Query> {
- return new Query(this.store(), this.entity)
- }
-
- /**
- * Check wether the associated database contains data.
- */
- static exists(this: T): boolean {
- return this.query().exists()
- }
-
- /**
- * Create new data with all fields filled by default values.
- */
- static new(this: T): Promise> {
- return this.query().new()
- }
-
- /**
- * Save given data to the store by replacing all existing records in the
- * store. If you want to save data without replacing existing records,
- * use the `insert` method instead.
- */
- static create(
- data: Record | Record[] | InsertObject,
- options?: QueryPersistOptions
- ): Promise {
- const { data: d, options: o } = normalizeInsertPayload(data, options)
-
- return this.query().create(d, o)
- }
-
- /**
- * Insert records.
- */
- static insert(
- data: Record | Record[] | InsertObject,
- options?: QueryPersistOptions
- ): Promise {
- const { data: d, options: o } = normalizeInsertPayload(data, options)
-
- return this.query().insert(d, o)
- }
-
- /**
- * Update records.
- */
- static update(
- this: T,
- payload: Payloads.Update,
- options?: PersistOptions.Update
- ): Promise {
- return this.dispatch('update', PayloadBuilder.normalize(payload, options))
- }
-
- /**
- * Insert or update records.
- */
- static insertOrUpdate(
- this: T,
- payload: Payloads.InsertOrUpdate,
- options?: PersistOptions.InsertOrUpdate
- ): Promise {
- return this.dispatch(
- 'insertOrUpdate',
- PayloadBuilder.normalize(payload, options)
- )
- }
-
- /**
- * Delete records that matches the given condition.
- */
- static delete(
- this: M,
- id: string | number | (number | string)[]
- ): Promise- >>
- static delete(
- this: M,
- condition: Predicate>
- ): Promise>>
- static delete(this: M, payload: any): any {
- return this.dispatch('delete', payload)
- }
-
- /**
- * Delete all records from the store.
- */
- static deleteAll(
- this: M
- ): Promise>> {
- return this.dispatch('deleteAll')
- }
-
- /**
- * Check if the given key is the primary key. If the model has composite
- * primary key, this method is going to check if the given key is included
- * in the composite key.
- */
- static isPrimaryKey(key: string): boolean {
- if (!Utils.isArray(this.primaryKey)) {
- return this.primaryKey === key
- }
-
- return this.primaryKey.includes(key)
- }
-
- /**
- * Check if the primary key is a composite key.
- */
- static isCompositePrimaryKey(): boolean {
- return Utils.isArray(this.primaryKey)
- }
-
- /**
- * Get the id (value of primary key) from teh given record. If primary key is
- * not present, or it is invalid primary key value, which is other than
- * `string` or `number`, it's going to return `null`.
- *
- * If the model has composite key, it's going to return array of ids. If any
- * composite key missing, it will return `null`.
- */
- static getIdFromRecord(
- record: Record
- ): string | number | (string | number)[] | null {
- const key = this.primaryKey
-
- if (typeof key === 'string') {
- return this.getIdFromValue(record[key])
- }
-
- const ids = key.reduce<(string | number)[]>((keys, k) => {
- const id = this.getIdFromValue(record[k])
-
- id !== null && keys.push(id)
-
- return keys
- }, [])
-
- return ids.length === key.length ? ids : null
- }
-
- /**
- * Get correct index id, which is `string` | `number`, from the given value.
- */
- static getIdFromValue(value: any): string | number | null {
- if (typeof value === 'string' && value !== '') {
- return value
- }
-
- if (typeof value === 'number') {
- return value
- }
-
- return null
- }
-
- /**
- * Get the index ID value from the given record. An index ID is a value that
- * used as a key for records within the Vuex Store.
- *
- * Most of the time, it's same as the value for the Model's primary key but
- * it's always `string`, even if the primary key value is `number`.
- *
- * If the Model has a composite primary key, each value corresponding to
- * those primary key will be stringified and become a single string value
- * such as `'[1,2]'`.
- *
- * If the primary key is not present at the given record, it returns `null`.
- * For the composite primary key, every key must exist at a given record,
- * or it will return `null`.
- */
- static getIndexIdFromRecord(record: Record): string | null {
- const id = this.getIdFromRecord(record)
-
- if (id === null) {
- return null
- }
-
- if (Utils.isArray(id)) {
- return JSON.stringify(id)
- }
-
- return String(id)
- }
-
- /**
- * Get local key to pass to the attributes.
- */
- static localKey(key?: string): string {
- if (key) {
- return key
- }
-
- return typeof this.primaryKey === 'string' ? this.primaryKey : 'id'
- }
-
- /**
- * Get the model object that matches the given record type. The method is for
- * getting the correct model object when the model has any inheritance
- * children model.
- *
- * For example, if a User Model have `static types()` declared, and if you
- * pass record with `{ type: 'admin' }`, then the method will likely to
- * return SuperUser class.
- */
- static getModelFromRecord(record: Record | Model): typeof Model | null {
- // If the given record is already a model instance, return the
- // model object.
- if (record instanceof this) {
- return record.$self()
- }
-
- // Else, get the corresponding model for the type value if there's any.
- return this.getTypeModel(record[this.typeKey])
- }
-
- /**
- * Get a model from the container.
- */
- static relation(model: typeof Model | string): typeof Model {
- if (typeof model !== 'string') {
- return model
- }
-
- return this.database().model(model)
- }
-
- /**
- * Get all `belongsToMany` fields from the schema.
- */
- static pivotFields(): {
- [key: string]:
- | Attributes.BelongsToMany
- | Attributes.MorphToMany
- | Attributes.MorphedByMany
- }[] {
- const fields: {
- [key: string]:
- | Attributes.BelongsToMany
- | Attributes.MorphToMany
- | Attributes.MorphedByMany
- }[] = []
-
- Utils.forOwn(this.getFields(), (field, key) => {
- if (
- field instanceof Attributes.BelongsToMany ||
- field instanceof Attributes.MorphToMany ||
- field instanceof Attributes.MorphedByMany
- ) {
- fields.push({ [key]: field })
- }
- })
-
- return fields
- }
-
- /**
- * Check if fields contains the `belongsToMany` field type.
- */
- static hasPivotFields(): boolean {
- return this.pivotFields().length > 0
- }
-
- /**
- * Check if the current model has a type definition
- */
- static hasTypes(): boolean {
- return Object.keys(this.types()).length > 0
- }
-
- /**
- * Get the model corresponding to the given type name. If it can't be found,
- * it'll return `null`.
- */
- static getTypeModel(name: string): typeof Model | null {
- const model = this.types()[name]
-
- if (!model) {
- return null
- }
-
- return model
- }
-
- /**
- * Given a Model, this returns the corresponding key in the InheritanceTypes mapping
- */
- static getTypeKeyValueFromModel(model?: typeof Model): string | null {
- const modelToCheck = model || this
- const types = this.types()
- for (const type in types) {
- if (types[type].entity === modelToCheck.entity) {
- return type
- }
- }
- return null
- }
-
- /**
- * Tries to find a Relation field in all types defined in the InheritanceTypes mapping
- */
- static findRelationInSubTypes(
- relationName: string
- ): Attributes.Relation | null {
- const types = this.types()
-
- for (const type in types) {
- const fields = types[type].getFields()
-
- for (const fieldName in fields) {
- if (
- fieldName === relationName &&
- fields[fieldName] instanceof Attributes.Relation
- ) {
- return fields[fieldName] as Attributes.Relation
- }
- }
- }
-
- return null
- }
-
- /**
- * Fill any missing fields in the given record with the default value defined
- * in the model schema.
- */
- static hydrate(record?: Record): Record {
- return new this(record).$getAttributes()
- }
-
- /**
- * Get the constructor of this model.
- */
- $self(): typeof Model {
- return this.constructor as typeof Model
- }
-
- /**
- * Get the primary key for the model.
- */
- $primaryKey(): string | string[] {
- return this.$self().primaryKey
- }
-
- /**
- * The definition of the fields of the model and its relations.
- */
- $fields(): Fields {
- return this.$self().getFields()
- }
-
- /**
- * Set index id.
- */
- $setIndexId(id: string | null): this {
- this.$id = id
-
- return this
- }
-
- /**
- * Get the store instance from the container.
- */
- $store(): Vuex.Store {
- return this.$self().store()
- }
-
- /**
- * Create a namespaced method name for Vuex Module from the given
- * method name.
- */
- $namespace(method: string): string {
- return this.$self().namespace(method)
- }
-
- /**
- * Call Vuex Getters.
- */
- $getters(method: string): any {
- return this.$self().getters(method)
- }
-
- /**
- * Dispatch Vuex Action.
- */
- async $dispatch(method: string, payload?: any): Promise {
- return this.$self().dispatch(method, payload)
- }
-
- /**
- * Get all records.
- */
- $all(this: T): Collection {
- return this.$getters('all')()
- }
-
- /**
- * Find a record.
- */
- $find(
- this: T,
- id: string | number | (number | string)[]
- ): Item {
- return this.$getters('find')(id)
- }
-
- /**
- * Find record of the given array of ids.
- */
- $findIn(
- this: T,
- idList: (number | string | (number | string)[])[]
- ): Collection {
- return this.$getters('findIn')(idList)
- }
-
- /**
- * Get query instance.
- */
- $query(): Query {
- return this.$getters('query')()
- }
-
- /**
- * Create records.
- */
- async $create(
- payload: Payloads.Create,
- options?: PersistOptions.Create
- ): Promise {
- return this.$dispatch('create', PayloadBuilder.normalize(payload, options))
- }
-
- /**
- * Insert records.
- */
- async $insert(
- payload: Payloads.Insert,
- options?: PersistOptions.Insert
- ): Promise {
- return this.$dispatch('insert', PayloadBuilder.normalize(payload, options))
- }
-
- /**
- * Update records.
- */
- async $update(
- payload: Payloads.Update,
- options?: PersistOptions.Update
- ): Promise {
- if (Utils.isArray(payload)) {
- return this.$dispatch(
- 'update',
- PayloadBuilder.normalize(payload, options)
- )
- }
-
- if (
- payload.where !== undefined ||
- (options && options.where !== undefined)
- ) {
- return this.$dispatch(
- 'update',
- PayloadBuilder.normalize(payload, options)
- )
- }
-
- if (this.$self().getIndexIdFromRecord(payload) === null) {
- /* istanbul ignore else */
- if (!options) {
- options = {}
- }
-
- options.where = this.$self().getIdFromRecord(this)
-
- return this.$dispatch(
- 'update',
- PayloadBuilder.normalize(payload, options)
- )
- }
-
- return this.$dispatch('update', PayloadBuilder.normalize(payload, options))
- }
-
- /**
- * Insert or update records.
- */
- async $insertOrUpdate(
- payload: Payloads.InsertOrUpdate,
- options?: PersistOptions.InsertOrUpdate
- ): Promise {
- return this.$dispatch(
- 'insertOrUpdate',
- PayloadBuilder.normalize(payload, options)
- )
- }
-
- /**
- * Save record.
- */
- async $save(this: T): Promise
- > {
- const fields = this.$self().getFields()
-
- const record = Object.keys(fields).reduce((record, key) => {
- if (fields[key] instanceof Attributes.Type) {
- record[key] = this[key]
- }
-
- return record
- }, {} as Record)
-
- const records = await this.$dispatch('insertOrUpdate', { data: record })
-
- this.$fill(records[this.$self().entity][0])
-
- return this
- }
-
- /**
- * Delete records that matches the given condition.
- */
- async $delete(): Promise
- > {
- const primaryKey = this.$primaryKey()
-
- if (!Utils.isArray(primaryKey)) {
- return this.$dispatch('delete', this[primaryKey])
- }
-
- return this.$dispatch('delete', (model: this): boolean => {
- return primaryKey.every((id) => model[id] === this[id])
- })
- }
-
- /**
- * Delete all records.
- */
- async $deleteAll(): Promise> {
- return this.$dispatch('deleteAll')
- }
-
- /**
- * Fill the model instance with the given record. If no record were passed,
- * or if the record has any missing fields, each value of the fields will
- * be filled with its default value defined at model fields definition.
- */
- $fill(record: Record = {}): void {
- const fields = this.$fields()
-
- for (const key in fields) {
- const field = fields[key]
- const value = record[key]
-
- this[key] = field.make(value, record, key)
- }
-
- // If the record contains index id, set it to the model.
- record.$id !== undefined && this.$setIndexId(record.$id)
- }
-
- /**
- * Generate missing primary ids and index id.
- */
- $generateId(): this {
- return this.$generatePrimaryId().$generateIndexId()
- }
-
- /**
- * Generate any missing primary ids.
- */
- $generatePrimaryId(): this {
- const key = this.$self().primaryKey
- const keys = Utils.isArray(key) ? key : [key]
-
- keys.forEach((k) => {
- if (this[k] === undefined || this[k] === null) {
- this[k] = Uid.make()
- }
- })
-
- return this
- }
-
- /**
- * Generate index id from current model attributes.
- */
- $generateIndexId(): this {
- return this.$setIndexId(this.$getIndexIdFromAttributes())
- }
-
- /**
- * Get index id based on current model attributes.
- */
- $getIndexIdFromAttributes(): string | null {
- return this.$self().getIndexIdFromRecord(this)
- }
-
- /**
- * Get all of the current attributes on the model. It includes index id
- * value as well. This method is mainly used when saving a model to
- * the store.
- */
- $getAttributes(): RecordWithId {
- return toAttributes(this)
- }
-
- /**
- * Serialize field values into json.
- */
- $toJson(): Record {
- return toJson(this)
- }
-}
diff --git a/src/model/Serialize.ts b/src/model/Serialize.ts
deleted file mode 100644
index a07de0d3..00000000
--- a/src/model/Serialize.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { isArray } from '../support/Utils'
-import { Record, RecordWithId } from '../data'
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Relation from '../attributes/relations/Relation'
-import Model from './Model'
-
-export interface Option {
- relations?: boolean
-}
-
-const defaultOption: Option = {
- relations: true
-}
-
-/**
- * Serialize the given model to attributes. This method will ignore
- * relationships, and it includes the index id.
- */
-export function toAttributes(model: Model): RecordWithId {
- const record = toJson(model, { relations: false })
-
- record.$id = model.$id
-
- return record as RecordWithId
-}
-
-/**
- * Serialize given model POJO.
- */
-export function toJson(model: Model, option: Option = {}): Record {
- option = { ...defaultOption, ...option }
-
- const record: Record = {}
-
- const fields = model.$fields()
-
- for (const key in fields) {
- const f = fields[key]
- const v = model[key]
-
- if (f instanceof Relation) {
- record[key] = option.relations ? relation(v) : emptyRelation(v)
- continue
- }
-
- record[key] = value(model[key])
- }
-
- return record
-}
-
-/**
- * Serialize given value.
- */
-function value(v: any): any {
- if (v === null) {
- return null
- }
-
- if (isArray(v)) {
- return array(v)
- }
-
- if (typeof v === 'object') {
- return object(v)
- }
-
- return v
-}
-
-/**
- * Serialize an array into json.
- */
-function array(a: any[]): any[] {
- return a.map((v) => value(v))
-}
-
-/**
- * Serialize an object into json.
- */
-function object(o: object): object {
- const obj = {}
-
- for (const key in o) {
- obj[key] = value(o[key])
- }
-
- return obj
-}
-
-/**
- * Serialize given relation into json.
- */
-function relation(relation: Item): Record | null
-function relation(relation: Collection): Record[]
-function relation(relation: Item | Collection): Record | Record[] | null {
- if (relation === null) {
- return null
- }
-
- if (isArray(relation)) {
- return relation.map((model) => model.$toJson())
- }
-
- return relation.$toJson()
-}
-
-/**
- * Serialize given relation into empty json.
- */
-function emptyRelation(relation: Item): null
-function emptyRelation(relation: Collection): []
-function emptyRelation(relation: Item | Collection): [] | null {
- return isArray(relation) ? [] : null
-}
diff --git a/src/model/contracts/FieldCache.ts b/src/model/contracts/FieldCache.ts
deleted file mode 100644
index fc1a53eb..00000000
--- a/src/model/contracts/FieldCache.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Fields from './Fields'
-
-export interface FieldCache {
- [key: string]: Fields
-}
-
-export default FieldCache
diff --git a/src/model/contracts/Fields.ts b/src/model/contracts/Fields.ts
deleted file mode 100644
index c307be3c..00000000
--- a/src/model/contracts/Fields.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Attribute from '../../attributes/Attribute'
-
-export interface Fields {
- [key: string]: Attribute
-}
-
-export default Fields
diff --git a/src/model/contracts/InheritanceTypes.ts b/src/model/contracts/InheritanceTypes.ts
deleted file mode 100644
index 8a1ba6fd..00000000
--- a/src/model/contracts/InheritanceTypes.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import Model from '../Model'
-
-export interface InheritanceTypes {
- [key: string]: typeof Model
-}
-
-export default InheritanceTypes
diff --git a/src/model/contracts/State.ts b/src/model/contracts/State.ts
deleted file mode 100644
index b866e773..00000000
--- a/src/model/contracts/State.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface State {
- [key: string]: any
-}
-
-export default State
diff --git a/src/model/support/Payloads.ts b/src/model/support/Payloads.ts
deleted file mode 100644
index 69332c76..00000000
--- a/src/model/support/Payloads.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { isArray } from '../../support/Utils'
-import { Record } from '../../data'
-import { PersistOptions } from '../../query/options'
-
-export interface InsertObject extends PersistOptions {
- data: Record | Record[]
-}
-
-export interface InsertPayload {
- data: Record | Record[]
- options?: PersistOptions
-}
-
-/**
- * Normalize the payload arguments for persist methods. It's required for
- * backward compatibility for the new persist method argument structure.
- * It may be deprecated and be removed in the future.
- */
-export function normalizeInsertPayload(
- data: Record | Record[] | InsertObject,
- options?: PersistOptions
-): InsertPayload {
- // If the data is an array, then the data should be an array of data.
- // Therefore the whole payload should be passed directly as `data`.
- if (isArray(data)) {
- return { data, options }
- }
-
- // If the data doesn't have a `data` property, it can be assumed that the
- // user has passed an object as the payload. Therefore the entire payload
- // should be declared as `data`.
- if (data.data === undefined) {
- return { data, options }
- }
-
- // If the data contains `data` property, we should extract it and pass that
- // property as `data`.
- return { data: data.data, options: data }
-}
diff --git a/src/modules/Actions.ts b/src/modules/Actions.ts
deleted file mode 100644
index 82e0573e..00000000
--- a/src/modules/Actions.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Collections from '../data/Collections'
-import Model from '../model/Model'
-import ActionsContract from './contracts/Actions'
-import ActionContext from './contracts/ActionContext'
-import * as Payloads from './payloads/Actions'
-import PayloadBuilder from './support/PayloadBuilder'
-
-/**
- * Create new data with all fields filled by default values.
- */
-async function newRecord(context: ActionContext): Promise {
- const state = context.state
- const entity = state.$name
-
- return context.dispatch(
- `${state.$connection}/new`,
- { entity },
- { root: true }
- )
-}
-
-/**
- * Save given data to the store by replacing all existing records in the
- * store. If you want to save data without replacing existing records,
- * use the `insert` method instead.
- */
-async function create(
- context: ActionContext,
- payload: Payloads.Create
-): Promise {
- const state = context.state
- const entity = state.$name
- const data = PayloadBuilder.createPersistPayload(payload)
-
- return context.dispatch(
- `${state.$connection}/create`,
- { entity, ...data },
- { root: true }
- )
-}
-
-/**
- * Insert given data to the state. Unlike `create`, this method will not
- * remove existing data within the state, but it will update the data
- * with the same primary key.
- */
-async function insert(
- context: ActionContext,
- payload: Payloads.Insert
-): Promise {
- const state = context.state
- const entity = state.$name
- const data = PayloadBuilder.createPersistPayload(payload)
-
- return context.dispatch(
- `${state.$connection}/insert`,
- { entity, ...data },
- { root: true }
- )
-}
-
-/**
- * Update data in the store.
- */
-async function update(
- context: ActionContext,
- payload: Payloads.Update
-): Promise
- {
- const state = context.state
- const entity = state.$name
- const data = PayloadBuilder.createPersistPayload(payload)
-
- return context.dispatch(
- `${state.$connection}/update`,
- { entity, ...data },
- { root: true }
- )
-}
-
-/**
- * Insert or update given data to the state. Unlike `insert`, this method
- * will not replace existing data within the state, but it will update only
- * the submitted data with the same primary key.
- */
-async function insertOrUpdate(
- context: ActionContext,
- payload: Payloads.InsertOrUpdate
-): Promise {
- const state = context.state
- const entity = state.$name
- const data = PayloadBuilder.createPersistPayload(payload)
-
- return context.dispatch(
- `${state.$connection}/insertOrUpdate`,
- { entity, ...data },
- { root: true }
- )
-}
-
-/**
- * Delete records from the store. The actual name for this action is `delete`,
- * but named `destroy` here because `delete` can't be declared at this
- * scope level.
- */
-async function destroy(
- context: ActionContext,
- payload: Payloads.DeleteById
-): Promise
-
-async function destroy(
- context: ActionContext,
- payload: Payloads.DeleteByCondition
-): Promise
-async function destroy(context: ActionContext, payload: any): Promise {
- const state = context.state
- const entity = state.$name
- const where = payload
-
- return context.dispatch(
- `${state.$connection}/delete`,
- { entity, where },
- { root: true }
- )
-}
-
-/**
- * Delete all data from the store.
- */
-async function deleteAll(context: ActionContext): Promise {
- const state = context.state
- const entity = state.$name
-
- return context.dispatch(
- `${state.$connection}/deleteAll`,
- { entity },
- { root: true }
- )
-}
-
-const Actions: ActionsContract = {
- new: newRecord,
- create,
- insert,
- update,
- insertOrUpdate,
- delete: destroy,
- deleteAll
-}
-
-export default Actions
diff --git a/src/modules/Getters.ts b/src/modules/Getters.ts
deleted file mode 100644
index adf0a75e..00000000
--- a/src/modules/Getters.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Query from '../query/Query'
-import State from './contracts/State'
-import RootState from './contracts/RootState'
-import GettersContract from './contracts/Getters'
-
-/**
- * Create a new Query instance.
- */
-const query = (
- state: State,
- _getters: any,
- _rootState: RootState,
- rootGetters: any
-) => (): Query => {
- return rootGetters[`${state.$connection}/query`](state.$name)
-}
-
-/**
- * Get all data of given entity.
- */
-const all = (
- state: State,
- _getters: any,
- _rootState: RootState,
- rootGetters: any
-) => (): Collection => {
- return rootGetters[`${state.$connection}/all`](state.$name)
-}
-
-/**
- * Find a data of the given entity by given id.
- */
-const find = (
- state: State,
- _getters: any,
- _rootState: RootState,
- rootGetters: any
-) => (id: string | number | (number | string)[]): Item => {
- return rootGetters[`${state.$connection}/find`](state.$name, id)
-}
-
-/**
- * Find array of data of the given entity by given ids.
- */
-const findIn = (
- state: State,
- _getters: any,
- _rootState: RootState,
- rootGetters: any
-) => (idList: Array): Collection => {
- return rootGetters[`${state.$connection}/findIn`](state.$name, idList)
-}
-
-const Getters: GettersContract = {
- query,
- all,
- find,
- findIn
-}
-
-export default Getters
diff --git a/src/modules/RootActions.ts b/src/modules/RootActions.ts
deleted file mode 100644
index 875f001a..00000000
--- a/src/modules/RootActions.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { Store } from 'vuex'
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Collections from '../data/Collections'
-import Model from '../model/Model'
-import Query from '../query/Query'
-import ActionsContract from './contracts/RootActions'
-import ActionContext from './contracts/RootActionContext'
-import OptionsBuilder from './support/OptionsBuilder'
-import * as Payloads from './payloads/RootActions'
-
-/**
- * Create new data with all fields filled by default values.
- */
-async function newRecord(
- this: Store,
- _context: ActionContext,
- payload: Payloads.New
-): Promise {
- return new Query(this, payload.entity).new()
-}
-
-/**
- * Save given data to the store by replacing all existing records in the
- * store. If you want to save data without replacing existing records,
- * use the `insert` method instead.
- */
-async function create(
- this: Store,
- _context: ActionContext,
- payload: Payloads.Create
-): Promise {
- const entity = payload.entity
- const data = payload.data
- const options = OptionsBuilder.createPersistOptions(payload)
-
- return new Query(this, entity).create(data, options)
-}
-
-/**
- * Insert given data to the state. Unlike `create`, this method will not
- * remove existing data within the state, but it will update the data
- * with the same primary key.
- */
-async function insert(
- this: Store,
- _context: ActionContext,
- payload: Payloads.Insert
-): Promise {
- const entity = payload.entity
- const data = payload.data
- const options = OptionsBuilder.createPersistOptions(payload)
-
- return new Query(this, entity).insert(data, options)
-}
-
-/**
- * Update data in the store.
- */
-async function update(
- this: Store,
- _context: ActionContext,
- payload: Payloads.Update
-): Promise
- {
- const entity = payload.entity
- const data = payload.data
- const where = payload.where || null
- const options = OptionsBuilder.createPersistOptions(payload)
-
- return new Query(this, entity).update(data, where, options)
-}
-
-/**
- * Insert or update given data to the state. Unlike `insert`, this method
- * will not replace existing data within the state, but it will update only
- * the submitted data with the same primary key.
- */
-async function insertOrUpdate(
- this: Store,
- _context: ActionContext,
- payload: Payloads.InsertOrUpdate
-): Promise {
- const entity = payload.entity
- const data = payload.data
- const options = OptionsBuilder.createPersistOptions(payload)
-
- return new Query(this, entity).insertOrUpdate(data, options)
-}
-
-/**
- * Delete records from the store. The actual name for this action is `delete`,
- * but named `destroy` here because `delete` can't be declared at this
- * scope level.
- */
-async function destroy(
- this: Store,
- _context: ActionContext,
- payload: Payloads.DeleteById
-): Promise
-
-async function destroy(
- this: Store,
- _context: ActionContext,
- payload: Payloads.DeleteByCondition
-): Promise
-async function destroy(
- this: Store,
- _context: ActionContext,
- payload: any
-): Promise {
- const { entity, where } = payload
-
- return new Query(this, entity).delete(where)
-}
-
-/**
- * Delete all data from the store.
- */
-async function deleteAll(
- this: Store,
- _context: ActionContext,
- payload?: Payloads.DeleteAll
-): Promise {
- if (payload && payload.entity) {
- new Query(this, payload.entity).deleteAll()
-
- return
- }
-
- Query.deleteAll(this)
-}
-
-const RootActions: ActionsContract = {
- new: newRecord,
- create,
- insert,
- update,
- insertOrUpdate,
- delete: destroy,
- deleteAll
-}
-
-export default RootActions
diff --git a/src/modules/RootGetters.ts b/src/modules/RootGetters.ts
deleted file mode 100644
index 84270d01..00000000
--- a/src/modules/RootGetters.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Store } from 'vuex'
-import Item from '../data/Item'
-import Collection from '../data/Collection'
-import Query from '../query/Query'
-import RootState from './contracts/RootState'
-import GettersContract from './contracts/RootGetters'
-
-/**
- * Create a new Query instance.
- */
-function query(this: Store, _state: RootState) {
- return (entity: string): Query => new Query(this, entity)
-}
-
-/**
- * Get all data of given entity.
- */
-function all(this: Store, _state: RootState) {
- return (entity: string): Collection => new Query(this, entity).all()
-}
-
-/**
- * Find a data of the given entity by given id.
- */
-function find(this: Store, _state: RootState) {
- return (entity: string, id: string | number | Array): Item => {
- return new Query(this, entity).find(id)
- }
-}
-
-/**
- * Find a data of the given entity by given id.
- */
-function findIn(this: Store, _state: RootState) {
- return (
- entity: string,
- idList: Array>
- ): Item[] => {
- return new Query(this, entity).findIn(idList)
- }
-}
-
-const RootGetters: GettersContract = {
- query,
- all,
- find,
- findIn
-}
-
-export default RootGetters
diff --git a/src/modules/RootMutations.ts b/src/modules/RootMutations.ts
deleted file mode 100644
index dc02ca3b..00000000
--- a/src/modules/RootMutations.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import { Store } from 'vuex'
-import Connection from '../connections/Connection'
-import State from './contracts/RootState'
-import MutationsContract from './contracts/RootMutations'
-import * as Payloads from './payloads/RootMutations'
-
-/**
- * Execute generic mutation. This method is used by `Model.commit` method so
- * that user can commit any state changes easily through models.
- */
-function $mutate(
- this: Store,
- state: State,
- payload: Payloads.$Mutate
-): void {
- payload.callback(state[payload.entity])
-}
-
-/**
- * Commit the given records by `new` method.
- */
-function newRecord(state: State, payload: Payloads.New): void {
- const entity = state[payload.entity]
- entity.data = { ...entity.data, ...payload.data }
-}
-
-/**
- * Commit the given records by `insert` method.
- */
-function insert(state: State, payload: Payloads.Insert): void {
- const entity = state[payload.entity]
- entity.data = { ...entity.data, ...payload.data }
-}
-
-/**
- * Insert the given records.
- */
-function insertRecords(this: Store, state: State, payload: any): void {
- const { entity, records } = payload
- new Connection(this, state.$name, entity).insertRecords(records)
-}
-
-/**
- * Delete records from the store. The actual name for this mutation is
- * `delete`, but named `destroy` here because `delete` can't be declared at
- * this scope level.
- */
-function destroy(this: Store, state: State, payload: any): void {
- const { entity, id } = payload
- new Connection(this, state.$name, entity).delete(id)
-}
-
-const RootMutations: MutationsContract = {
- $mutate,
- new: newRecord,
- insert,
- insertRecords,
- delete: destroy
-}
-
-export default RootMutations
diff --git a/src/modules/contracts/ActionContext.ts b/src/modules/contracts/ActionContext.ts
deleted file mode 100644
index 1d34fb98..00000000
--- a/src/modules/contracts/ActionContext.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as Vuex from 'vuex'
-import State from './State'
-
-export type ActionContext = Vuex.ActionContext
-
-export default ActionContext
diff --git a/src/modules/contracts/Actions.ts b/src/modules/contracts/Actions.ts
deleted file mode 100644
index 1e2d2bf5..00000000
--- a/src/modules/contracts/Actions.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as Vuex from 'vuex'
-import State from './State'
-
-export type Actions = Vuex.ActionTree
-
-export default Actions
diff --git a/src/modules/contracts/Getters.ts b/src/modules/contracts/Getters.ts
deleted file mode 100644
index 4d0624b6..00000000
--- a/src/modules/contracts/Getters.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import * as Vuex from 'vuex'
-import State from './State'
-
-export type Getters = Vuex.GetterTree
-
-export default Getters
diff --git a/src/modules/contracts/Module.ts b/src/modules/contracts/Module.ts
deleted file mode 100644
index 79c9d35d..00000000
--- a/src/modules/contracts/Module.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as Vuex from 'vuex'
-import RootState from './RootState'
-
-interface VuexModule extends Vuex.Module {
- namespaced: boolean
- state: () => RootState
- getters: Vuex.GetterTree
- actions: Vuex.ActionTree
- mutations: Vuex.MutationTree