Skip to content

Commit

Permalink
feat(pinia-orm): Pinia setup store syntax support (#1905)
Browse files Browse the repository at this point in the history
* feat(pinia-orm): Pinia setup store syntax support

* refactor(pinia-orm): fix lock file

* docs(pinia-orm): Add configuration to documentation

* refactor(pinia-orm): Update eslint caches

Resolves: #1888
  • Loading branch information
CodeDredd authored Nov 25, 2024
1 parent ceaaf3e commit 953826a
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 14 deletions.
35 changes: 35 additions & 0 deletions docs/content/1.guide/1.getting-started/5.configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Configuration

## On initialization

In pinia-orm you can define different configurations for pinia-orm `createORM`.

### Using setup stores in pinia-orm

If you want to use [setup store](https://pinia.vuejs.org/core-concepts/#Setup-Stores) logic in pinia-orm then you need
to use following option.

````ts
createPiniaORM({ pinia: { storeType: 'setupStore' } })
````

Now you can use the syntax in your models by using the regular `piniaOptions` property. And to pass pinia config options
you now need to use `piniaExtend` for example if you want to pass some configuration to an other pinia plugin.

````ts
class User extends Model {
static entity = 'users'

static piniaOptions = {
newData: ref('1'),
}

static piniaExtend = {
persist: true,
}

@Attr(0) declare id: number
@Str('') declare name: string
@Str('') declare username: string
}
````
6 changes: 6 additions & 0 deletions docs/content/2.api/5.configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ icon: heroicons-outline:adjustments
| `provider` | `Weakcache` | Defines which cache provider should be used |
| `shared` | `true` | Activates the cache to be shared between all repositories |

## `pinia`

| Option | Default | Description |
|------------|:--------------:|:------------------------------------------------------------------------|
| `storeType` | `optionStore` | Defines which store syntax to use. Either `optionStore` or `setupStore` |

## Typescript Declarations

````ts
Expand Down
2 changes: 1 addition & 1 deletion packages/axios/.eslintcache

Large diffs are not rendered by default.

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/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default defineBuildConfig({
declaration: true,
failOnWarn: false,
clean: true,
externals: ['@/composables', 'nanoid', 'uuid', 'nanoid/async', 'nanoid/non-secure', 'pinia'],
externals: ['@/composables', 'nanoid', 'uuid', 'nanoid/async', 'nanoid/non-secure', 'pinia', 'vue-demi', 'vue', '@vue/composition-api'],
rollup: {
emitCJS: true,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/pinia-orm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"size-limit": [
{
"path": "dist/index.mjs",
"limit": "13 kB"
"limit": "16 kB"
},
{
"path": "dist/decorators.mjs",
Expand Down
20 changes: 15 additions & 5 deletions packages/pinia-orm/src/composables/useDataStore.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import type { DefineStoreOptionsBase } from 'pinia'
import type { DefineSetupStoreOptions, DefineStoreOptionsBase } from 'pinia'
import { defineStore } from 'pinia'
import { ref } from 'vue-demi'
import type { Query } from '../'
import { config } from '../'
import { useStoreActions } from './useStoreActions'

export function useDataStore<S extends DataStoreState, T extends DataStore = DataStore> (
id: string,
options: DefineStoreOptionsBase<S, T>,
customOptions?: DefineSetupStoreOptions<string, S, T, any>,
query?: Query<any>,
) {
return defineStore(id, {
state: () => ({ data: {} } as S),
actions: useStoreActions(query),
if (config.pinia.storeType === 'optionStore') {
return defineStore(id, {
state: () => ({ data: {} } as S),
actions: useStoreActions(query),
...options,
})
}
return defineStore(id, () => ({
data: ref<Record<string, any>>({}),
...useStoreActions(query),
...options,
})
}), customOptions)
}

export interface DataStoreState {
Expand Down
2 changes: 2 additions & 0 deletions packages/pinia-orm/src/composables/useStoreActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ export function useStoreActions (query?: Query) {
},
}
}

export type StoreActions = 'insert' | 'flush' | 'delete' | 'update' | 'destroy' | 'save' | 'fresh'
9 changes: 9 additions & 0 deletions packages/pinia-orm/src/model/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ export class Model {
*/
protected static piniaOptions = {}

protected static piniaExtend = {}

/**
* The mutators for the model.
*/
Expand Down Expand Up @@ -712,6 +714,13 @@ export class Model {
return this.$self().piniaOptions
}

/**
* Get the extended functionality.
*/
$piniaExtend () {
return this.$self().piniaExtend
}

/**
* Get the primary key for this model.
*/
Expand Down
7 changes: 4 additions & 3 deletions packages/pinia-orm/src/query/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type { HasMany } from '../model/attributes/relations/HasMany'
import type { MorphMany } from '../model/attributes/relations/MorphMany'
import type { Type } from '../model/attributes/types/Type'
import { BelongsToMany } from '../model/attributes/relations/BelongsToMany'
import type { StoreActions } from '../composables/useStoreActions'
import type {
EagerLoad,
EagerLoadConstraint,
Expand Down Expand Up @@ -165,14 +166,14 @@ export class Query<M extends Model = Model> {
/**
* Commit a store action and get the data
*/
protected commit (name: string, payload?: any) {
const store = useDataStore(this.model.$storeName(), this.model.$piniaOptions(), this)(this.pinia)
protected commit (name: StoreActions | 'all' | 'get', payload?: any) {
const store = useDataStore(this.model.$storeName(), this.model.$piniaOptions(), this.model.$piniaExtend(), this)(this.pinia)

if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(store as DataStore, import.meta.hot))
}

if (name && typeof store[name] === 'function') { store[name](payload, false) }
if (name && name !== 'all' && name !== 'get' && typeof store[name] === 'function') { store[name](payload, false) }

if (this.cache && ['get', 'all', 'insert', 'flush', 'delete', 'update', 'destroy'].includes(name)) { this.cache.clear() }

Expand Down
2 changes: 1 addition & 1 deletion packages/pinia-orm/src/repository/Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export class Repository<M extends Model = Model> {
* Returns the pinia store used with this model
*/
piniaStore<S extends DataStoreState = DataStoreState> () {
return useDataStore<S>(this.model.$storeName(), this.model.$piniaOptions(), this.query())(this.pinia)
return useDataStore<S>(this.model.$storeName(), this.model.$piniaOptions(), this.model.$piniaExtend(), this.query())(this.pinia)
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/pinia-orm/src/store/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export const CONFIG_DEFAULTS = {
shared: true,
provider: WeakCache,
},
pinia: {
storeType: 'optionStore',
},
}

export const config: FilledInstallOptions & { [key: string]: any } = { ...CONFIG_DEFAULTS }
7 changes: 7 additions & 0 deletions packages/pinia-orm/src/store/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,21 @@ export interface CacheConfigOptions {
provider?: typeof WeakCache<string, Model[]>
}

export interface PiniaConfigOptions {
storeType?: 'optionStore' | 'setupStore' | string
}

export interface InstallOptions {
model?: ModelConfigOptions
cache?: CacheConfigOptions | boolean
pinia?: PiniaConfigOptions
plugins?: PiniaOrmPlugin[]
}

export interface FilledInstallOptions {
model: Required<ModelConfigOptions>
cache: Required<CacheConfigOptions | boolean>
pinia: Required<PiniaConfigOptions>
}

export interface CreatePiniaOrm {
Expand All @@ -38,6 +44,7 @@ export interface CreatePiniaOrm {
export function createORM (options?: InstallOptions): PiniaPlugin {
config.model = { ...CONFIG_DEFAULTS.model, ...options?.model }
config.cache = options?.cache === false ? false : { ...CONFIG_DEFAULTS.cache, ...(options?.cache !== true && options?.cache) }
config.pinia = { ...CONFIG_DEFAULTS.pinia, ...options?.pinia }

if (options?.plugins) {
options.plugins.forEach(plugin => plugins.push(plugin))
Expand Down
26 changes: 26 additions & 0 deletions packages/pinia-orm/tests/unit/PiniaORM.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest'
import { ref } from 'vue-demi'
import { Model, useRepo } from '../../src'
import { Attr, BelongsTo, BelongsToMany, Num, Str } from '../../src/decorators'
import { createPiniaORM } from '../helpers'
Expand Down Expand Up @@ -114,6 +115,31 @@ describe('unit/PiniaORM', () => {
expect(user.$storeName()).toBe('orm/users')
})

it('can use pinia setupStore', () => {
createPiniaORM({ pinia: { storeType: 'setupStore' } })
Model.clearRegistries()

class User extends Model {
static entity = 'users'

static piniaOptions = {
newData: ref('1'),
}

static piniaExtend = {
persist: true,
}

@Attr(0) declare id: number
@Str('') declare name: string
@Str('') declare username: string
}

const userRepo = useRepo(User)

expect(userRepo.piniaStore().newData).toBe('1')
})

it('can overwrite namespace for a model', () => {
class User extends Model {
static entity = 'users'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ describe('unit/model/Model', () => {
static piniaOptions = {
persist: true,
}

static piniaExtend = {
persist: true,
}
}

it('uses the pinia options in the store', () => {
const user = new User({ id: 1, name: 'John Doe' })
user.$piniaOptions()

expect(user.$piniaOptions()).toEqual({ persist: true })
expect(user.$piniaExtend()).toEqual({ persist: true })
})
})

0 comments on commit 953826a

Please sign in to comment.