Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/pinia-orm/.eslintcache

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/pinia-orm/src/database/Database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class Database {
* Register the given model.
*/
register<M extends Model> (model: M): void {
const entity = model.$entity()
const entity = model.$self().modelEntity()

if (!this.models[entity]) {
this.models[entity] = model
Expand Down
54 changes: 41 additions & 13 deletions packages/pinia-orm/src/model/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export class Model {
*/
static baseEntity: string

/**
* The reference to the base namespace if the class extends a base with a different namespace.
*/
static baseNamespace: string

/**
* Define a namespace if you have multiple equal entity names.
* Resulting in "{namespace}/{entity}"
Expand Down Expand Up @@ -174,25 +179,34 @@ export class Model {
return {}
}

static usedNamespace (): string {
return this.namespace ?? config.model.namespace
}

static modelEntity (): string {
return (this.usedNamespace() ? this.usedNamespace() + '/' : '') + this.entity
}

/**
* Build the schema by evaluating fields and registry.
*/
protected static initializeSchema (): void {
this.schemas[this.entity] = {}
this.fieldsOnDelete[this.entity] = this.fieldsOnDelete[this.entity] ?? {}
const entity = this.modelEntity()
this.schemas[entity] = {}
this.fieldsOnDelete[entity] = this.fieldsOnDelete[entity] ?? {}

const registry = {
...this.fields(),
...this.registries[this.entity],
...this.registries[entity],
}

for (const key in registry) {
const attribute = registry[key]

this.schemas[this.entity][key] =
this.schemas[entity][key] =
typeof attribute === 'function' ? attribute() : attribute

if (this.fieldsOnDelete[this.entity][key]) { this.schemas[this.entity][key] = (this.schemas[this.entity][key] as Relation).onDelete(this.fieldsOnDelete[this.entity][key]) }
if (this.fieldsOnDelete[entity][key]) { this.schemas[entity][key] = (this.schemas[entity][key] as Relation).onDelete(this.fieldsOnDelete[entity][key]) }
}
}

Expand All @@ -204,9 +218,9 @@ export class Model {
key: string,
attribute: () => Attribute,
): M {
if (!this.registries[this.entity]) { this.registries[this.entity] = {} }
if (!this.registries[this.modelEntity()]) { this.registries[this.modelEntity()] = {} }

this.registries[this.entity][key] = attribute
this.registries[this.modelEntity()][key] = attribute

return this
}
Expand All @@ -219,8 +233,8 @@ export class Model {
key: string,
mode: deleteModes,
): M {
this.fieldsOnDelete[this.entity] = this.fieldsOnDelete[this.entity] ?? {}
this.fieldsOnDelete[this.entity][key] = mode
this.fieldsOnDelete[this.modelEntity()] = this.fieldsOnDelete[this.modelEntity()] ?? {}
this.fieldsOnDelete[this.modelEntity()][key] = mode

return this
}
Expand Down Expand Up @@ -615,7 +629,7 @@ export class Model {
* Get the namespace.
*/
$namespace (): String {
return this.$self().namespace ?? config.model.namespace
return this.$self().usedNamespace()
}

/**
Expand All @@ -632,6 +646,20 @@ export class Model {
return this.$self().baseEntity ?? this.$entity()
}

/**
* Get the base namespace for this model.
*/
$baseNamespace (): string {
return this.$self().baseNamespace ?? this.$namespace()
}

/**
* Get the model entity for this model.
*/
$modelEntity (): string {
return this.$self().modelEntity()
}

/**
* Get the type key for this model.
*/
Expand Down Expand Up @@ -664,7 +692,7 @@ export class Model {
* Get the model fields for this model.
*/
$fields (): ModelFields {
return this.$self().schemas[this.$entity()]
return this.$self().schemas[this.$modelEntity()]
}

/**
Expand Down Expand Up @@ -696,8 +724,8 @@ export class Model {
* Bootstrap this model.
*/
protected $boot (): void {
if (!this.$self().booted[this.$entity()]) {
this.$self().booted[this.$entity()] = true
if (!this.$self().booted[this.$modelEntity()]) {
this.$self().booted[this.$modelEntity()] = true

this.$initializeSchema()
}
Expand Down
2 changes: 1 addition & 1 deletion packages/pinia-orm/src/query/Options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Model, WithKeys } from '../model/Model'
import type { Query } from './Query'
import type { Model, WithKeys } from '@/model/Model'

export interface Where<T = Model> {
field: WherePrimaryClosure<T> | NonMethodKeys<T> | string | string[]
Expand Down
6 changes: 2 additions & 4 deletions packages/pinia-orm/src/query/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,6 @@ export class Query<M extends Model = Model> {
* Filter the given collection by the registered order conditions.
*/
protected filterOrder (models: Collection<M>): Collection<M> {
if (this.orders.length === 0) { return models }

const fields = this.orders.map(order => order.field)
const directions = this.orders.map(order => order.direction)

Expand Down Expand Up @@ -793,7 +791,7 @@ export class Query<M extends Model = Model> {
save (records: Element | Element[]): M | M[] {
let processedData: [Element | Element[], NormalizedData] = this.newInterpreter().process(records)
const modelTypes = this.model.$types()
const isChildEntity = this.model.$baseEntity() !== this.model.$entity()
const isChildEntity = this.model.$baseEntity() !== this.model.$entity() || this.model.$baseNamespace() !== this.model.$namespace()

if (Object.values(modelTypes).length > 0 || isChildEntity) {
const modelTypesKeys = Object.keys(modelTypes)
Expand All @@ -809,7 +807,7 @@ export class Query<M extends Model = Model> {
})
for (const entry in recordsByTypes) {
const typeModel = modelTypes[entry]
if (typeModel.entity === this.model.$entity()) { processedData = this.newInterpreter().process(recordsByTypes[entry]) } else { this.newQueryWithConstraints(typeModel.entity).save(recordsByTypes[entry]) }
if (typeModel.modelEntity() === this.model.$modelEntity()) { processedData = this.newInterpreter().process(recordsByTypes[entry]) } else { this.newQueryWithConstraints(typeModel.modelEntity()).save(recordsByTypes[entry]) }
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/pinia-orm/src/schema/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class Schema {
model = model || this.model
parent = parent || this.model

const entity = `${model.$entity()}${parent.$entity()}`
const entity = `${model.$self().modelEntity()}${parent.$self().modelEntity()}`

if (this.schemas[entity]) { return this.schemas[entity] }

Expand All @@ -59,7 +59,7 @@ export class Schema {
*/
union (models: Model[], callback: Normalizr.SchemaFunction): Normalizr.Union {
const schemas = models.reduce<Schemas>((schemas, model) => {
schemas[model.$entity()] = this.one(model)
schemas[model.$self().modelEntity()] = this.one(model)

return schemas
}, {})
Expand All @@ -71,7 +71,7 @@ export class Schema {
* Create a new normalizr entity.
*/
private newEntity (model: Model, parent: Model): Normalizr.Entity {
const entity = model.$entity()
const entity = model.$self().modelEntity()
const idAttribute = this.idAttribute(model, parent)

return new Normalizr.Entity(entity, {}, { idAttribute })
Expand Down Expand Up @@ -123,7 +123,7 @@ export class Schema {

// Check if a list is passed to a one to one relation and throws a error if so
if (['BelongsTo', 'HasOne', 'MorphOne', 'MorphTo'].includes(parent.$fields()[key]?.constructor.name ?? '') && isArray(parentRecord[key])) {
throwError(['You are passing a list to "', `${parent.$entity()}.${key}`, `" which is a one to one Relation(${parent.$fields()[key]?.constructor.name}):`, JSON.stringify(parentRecord[key])])
throwError(['You are passing a list to "', `${parent.$modelEntity()}.${key}`, `" which is a one to one Relation(${parent.$fields()[key]?.constructor.name}):`, JSON.stringify(parentRecord[key])])
}

// Finally, obtain the index id, attach it to the current record at the
Expand Down
42 changes: 41 additions & 1 deletion packages/pinia-orm/tests/unit/PiniaORM.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { Model, useRepo } from '../../src'
import { Attr, Str } from '../../src/decorators'
import { Attr, BelongsTo, Num, Str } from '../../src/decorators'
import { createPiniaORM } from '../helpers'
import { WeakCache } from '../../src/cache/WeakCache'

Expand Down Expand Up @@ -135,4 +135,44 @@ describe('unit/PiniaORM', () => {

expect(user.$storeName()).toBe('otherOrm/users')
})

it('make is using the correct namespace', () => {
class User2 extends Model {
static entity = 'users'

static namespace = 'orm'

@Attr(0) declare id: number
@Str('') declare prename: string
@Num('') declare age: number
}

class User extends Model {
static entity = 'users'

static namespace = 'otherOrm'

@Attr(0) declare id: number
@Str('') declare name: string
@Str('') declare username: string
@Attr() declare user_id: number
@BelongsTo(() => User2, 'user_id') user: User2
}
createPiniaORM({ model: { namespace: 'orm' } })

const userRepo = useRepo(User)
const user = userRepo.make({
id: 1,
name: 'John',
username: 'JD',
user: {
prename: 'John Doe',
age: 30,
},
})

expect(user.$storeName()).toBe('otherOrm/users')
expect(user.user.$storeName()).toBe('orm/users')
expect(user.user.username).toBe(undefined)
})
})