GithubHelp home page GithubHelp logo

codedredd / pinia-orm Goto Github PK

View Code? Open in Web Editor NEW
439.0 2.0 38.0 29.62 MB

The Pinia plugin to enable Object-Relational Mapping access to the Pinia Store.

Home Page: https://pinia-orm.codedredd.de/

License: MIT License

JavaScript 4.15% TypeScript 88.25% Vue 5.72% HTML 1.38% CSS 0.38% Shell 0.12%
pinia pinia-plugin vue orm pinia-orm

pinia-orm's People

Contributors

carlosgamez-nova avatar carstenruetz avatar codedredd avatar danielroe avatar daniser avatar dev1437 avatar github-actions[bot] avatar graphmaxer avatar hi-reeve avatar igolka97 avatar liviuzachin avatar mahmoudawadeen avatar max-kut avatar paolodina avatar qwe12e avatar renovate[bot] avatar sergerdn avatar tintin10q avatar tklaas avatar tripplicate avatar who-jonson avatar yyydevf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pinia-orm's Issues

Subrelations broken after many to many

Environment

(I don't use Nuxt)

Reproduction

https://codesandbox.io/s/wizardly-wood-cq6t5f?file=/src/App.vue

Describe the bug

When I use a many to many relation, I can't use a subquery to get a relation on the related model.

E.g.

If I want to get all users of all roles, and then get all posts of these users, the posts object key of the returned object is empty :

roleRepo.with("users", (query) => query.with("posts")).get()

But if I try to get posts directly from user, it works :

userRepo.with("posts").get()

Thank you for your help and sorry for my bad English !

Additional context

No response

Logs

No response

Improve docs

Model with fields declared like

class User extends Model {
    static entity = 'users'
    static fields() {
        return {
            id: this.number(0),
            name: this.string('')
        }
    }

    id!: number
    name!: string
}

or

class User extends Model {
    static entity = 'users'

    @Attr(0) id!: number
    @Attr('') name!: string
}

dont`t working if option useDefineForClassFields in tsconfig.json set to true (as generate Vite). Please, add note to docs.

Pass pinia options in model

Hi!

I'm currently working on a project in which I have to migrate from Vue2 with Vuex-ORM into Vue3 with Pinia-ORM. One of the requirements of the project is to persist the store during page reloads (which I try to accomplish with the pinia-plugin-persistedstate plugin). To configure this plugin I have to add an option to my store description.

The issue I'm facing is that I can't figure out how to access this store description inside of a Model. I can imagine that other plugins will work the same way (options in the store description), so it might be an interesting addition to the package!

My proposed solution is to add a static field to the Model in which you could add options that are inserted (with a spread operator) into the store description. Maybe something like static piniaOptions = {}?

Cannot read properties of undefined (reading 'newRawInstance') when one to many relation (SSR)

Environment

  • Operating System: Darwin
  • Node Version: v14.20.0
  • Nuxt Version: 3.0.0-rc.11
  • Nitro Version: 0.5.4
  • Package Manager: [email protected]
  • Builder: vite
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/github-hrsy4e?file=app.vue

Describe the bug

Error "Cannot read properties of undefined (reading 'newRawInstance')" on models with one-to-many relations

Additional context

This error threw only in SSR

Logs

No response

hasManyBy for Many To Many?

Describe the feature

I have a backend with contact and contact emails that get serialized out like this:

a contact:

{
  "id": 1,
  "name": "Wanda",
  "emails": [
    {
      "id": 10,
      "contact_ids": [1],
      "email_address": "[email protected]"
    }
  ]
}

On the backend, these models are related many-to-many. There should be a way for pinia-orm to be able to save either a contact or contact email and have the relationships work even when the backend data coming in is an array of ids instead of a serialized object, similar to hasManyBy but works with a pivot table.

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

query issues with many to many relationships

Environment

[email protected]

Reproduction

Given the following entities: Participant and Formfield with a many-to-many relationship ParticipantFormfield


class Participant extends Model {
  static entity = 'participant';

  static fields() {
    return {
      id: this.attr(null),
      name: this.string(''),
      formfields: this.belongsToMany(Formfield, ParticipantFormfield, 'participant_id', 'formfield_id'),
    };
  }
}


export default class ParticipantFormfield extends Model {
  static entity = 'participantformfield';

  static primaryKey = ['participant_id', 'formfield_id'];

  static fields() {
    return {
      participant_id: this.string(''),
      formfield_id: this.string(''),
      value: this.attr(null),
    };
  }
}



export default class Formfield extends Model {
  static entity = 'formfield';
  static fields() {
    return {
      id: this.uid(),
      title: this.string(''),
      participants: this.belongsToMany(Participant, ParticipantFormfield, 'formfield_id', 'participant_id'),
    };
  }
}


useRepo(Formfield).save([
  { id: 'FF1', title: 'name' },
  { id: 'FF2', title: 'age' },
]);

useRepo(Participant).save([
  { id: 'P1', name: 'Peter', formfields: [{ id: 'FF1', pivot: { value: 'Peter S.' } }] },
  { id: 'P2', name: 'Steven', formfields: [{ id: 'FF1', pivot: { value: 'Steven R.' } }] },
]);

console.log('participants: ', useRepo(Participant).with('formfields').get());
console.log('formfields: ', useRepo(Formfield).with('participants').get());


The data is correctly entered into the stores:

1_store_participant

2_store_formfield

3_store_participant_formfield

Describe the bug

However:

(1) when querying the participants including their related formfields

  • P1 is correctly linked to FF1 but with the wrong pivot element for P1 (value is "Steven R.")
  • P2 is correctly linked

4_query_participants

(2) when querying the formfields including their related participants (thus the other way round)

  • FF1 is correctly linked to P1 and P2 but neither shows a pivot element
  • Note: this changes when the second formfield ({ id: 'FF2', title: 'age' },) is not inserted in the store

5_query_formfields

Any ideas on this?
Is my definition wrong?

Thanks in advance!

Additional context

No response

Logs

No response

Usage of child repo is saved with wrong type (STI)

Discussed in #519

Originally posted by n-xt November 2, 2022
The manual shows how to use Single Tabel Inheritance using the static fields() method and using the spread operator calling super.fields(). But what when I am using decorators?

Single Table Inheritance not working when retrieving data

Environment

Recreated in the pinia-orm playground. Same issue when setting up locally.

Reproduction

Pinia-ORM playground demo of issue

Describe the bug

can't use single table inheritance in pinia-orm. When trying to fetch records from a sub class model it errors out reporting the following in the console log
Cannot read properties of undefined (reading 'make')

Adding a .where() before call .all() on the sub class model repo returns all records but does include the sub class model additional fields

Additional context

No response

Logs

No response

Build error: `Can't resolve '#build/orm-options'` on Nuxt 2 without Nuxt-Bridge

Environment

Versions:

Reproduction

Eeeer, sorry I've tried but I'm not fluent enough for that. ๐Ÿ˜… I'm happy to add you as a contributor to my (private) project if that helps.

Describe the bug

nuxt dev failed to build. The file @pinia-orm/nuxt/dist/runtime/nuxt2-plugin.mjs is looking for the package #build/orm-options which does not exists.

I really don't know how to help more, sorry. :/

In the browser:
CleanShot 2022-11-25 at 15 06 21@2x

Additional context

Logs

โœ– Client
  Compiled with some errors in 153.82ms


 ERROR  Failed to compile with 1 errors                                    friendly-errors 14:42:55

This dependency was not found:                                             friendly-errors 14:42:55
                                                                           friendly-errors 14:42:55
* #build/orm-options in ./node_modules/@pinia-orm/nuxt/dist/runtime/nuxt2-plugin.mjs
                                                                           friendly-errors 14:42:55
To install it, you can run: npm install --save #build/orm-options          friendly-errors 14:42:55

Using .whereIn with Sets

Describe the feature

It would be great if you could give sets to the .whereIn method. Currently if you do this typescript gives an error and you also get back an empty list of results. It would be great if sets worked.

I also imagine that it would also be quite faster than using arrays because finding out if something is in a set O(1). But even if you already convert to a set behind the scenes it would still be faster if we could just pass a set directly because than you can skip the conversion.

You probably already know this but you can check that something is a Set using the instanceof keyword. Like so:

const a = new Set(["set"])
console.log("a is a set:", a instanceof Set)

I don't know if this feature could be implemented as a module because I don't really know what that means but I think this is just a simple change to an already existing thing.

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

"new" doesnt fire creating or created hook

Environment

  "dependencies": {
    "pinia": "2.0.28",
    "pinia-orm": "1.4.0",
    "vue": "3.2.45"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0-0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^7.0.0-0"
  },

Reproduction

https://codesandbox.io/s/young-cloud-odi2kr?file=/src/App.vue

Describe the bug

if calling new from repository the hooks for creatingand created not getting called.

Click on "console" and afterwards on the buttons. you will see, that "new" wouldnt trigger these hooks

Additional context

No response

Logs

No response

A few Query methods should have return type this instead of Query<M>

Problem

A few Query methods have return type Query<M>, but I think they should have return type this like the other similar methods (where, has, ...)

declare class Query<M extends Model = Model> {
    orderBy(field: OrderBy, direction?: OrderDirection): Query<M>;
    with(name: string, callback?: EagerLoadConstraint): Query<M>;
    withAll(callback?: EagerLoadConstraint): Query<M>;
    withAllRecursive(depth?: number): Query<M>;
}

Context

I'm writing a small adapter layer to be able to easily switch between vuex-orm and pinia-orm until it's clear that I can fully switch to pinia-orm. The relevant part:

orm_pinia_model.ts

import { Model, Query, type Item, type Collection } from "pinia-orm"

import { database } from "@/orm_pinia"

export class ORMModel extends Model {
  static query<M extends typeof ORMModel>(this: M): ORMQuery<InstanceType<M>> {
    return new ORMQuery(database, this.newRawInstance())
  }

  static exists<M extends typeof ORMModel>(this: M): boolean {
    return this.query().exists()
  }

  static all<M extends typeof ORMModel>(this: M): Collection<InstanceType<M>> {
    return this.query().all()
  }

  static find<M extends typeof ORMModel>(this: M, id: string | number): Item<InstanceType<M>> {
    return this.query().find(id)
  }
}

export class ORMQuery<M extends ORMModel> extends Query<M> {
  public exists(): boolean {
    return this.select().length > 0
  }

  public count(): number {
    return this.select().length
  }
}

The problem

The initial query assignment has my adapter type ORMQuery<Item>, but since orderBy returns Query<Item> instead of this, the second assignment fails:

function items(accountId: string, sort: boolean=false): Item[] {
  let query = Item.query()
    .where("account_id", accountId)

  if (sort) {
    // Type 'Query<Item>' is missing the following properties from type 'ORMQuery<Item>': exists, count [ts(2739)]
    query = query.orderBy("account_id")
  }

  return query.get()
}

belongsTo unexpected behavior?

I have a Registration model and a User model. The Registration model can be created or updated by a User.

Registration model:

import { Model } from "pinia-orm";

import { User } from "src/models/User.js";

export class Registration extends Model {
  static fields() {
    return {
      id: this.uid(),
      created_at: this.attr(null),
      updated_at: this.attr(null),
      createdById: this.attr(null),
      updatedById: this.attr(null),
      created_by: this.belongsTo(User, "createdById"),
      updated_by: this.belongsTo(User, "updatedById"),
      name: this.string("").nullable(),
      status: this.string("").nullable(),
      data: this.attr({}),
    };
  }
}

// Using Quasar Framework, we get Unexpected token '=' for static entity = "registrations"; 
Registration.entity = "registrations";

User model:

import { Model } from "pinia-orm";

import { Registration } from "src/models/Registration";

export class User extends Model {
  static fields() {
    return {
      id: this.attr(null),
      last_login: this.attr(null),
      username: this.string(""),
      first_name: this.string("").nullable(),
      last_name: this.string("").nullable(),
      email: this.string("").nullable(),
      is_active: this.boolean(false),
    };
  }
}
User.entity = "users";

I fetch registrations with this:

import { useRepo } from "pinia-orm";

import { Registration } from "src/models/Registration.js";

import { api } from "src/boot/axios.js";

export default {
  registration: {
    orm: () => useRepo(Registration),
    read: (path) => {
      api.get(path).then((response) => {
        useRepo(Registration).save(response.data.results);
      });
    },
  },
};

// e.g. use inside my component:
// onMounted(() => { db.registration.read("registrations"); });
// const registrations = computed(() => db.registration.orm().withAllRecursive().all());

The backend sends the registrations back like this:

    ...
    "results": [
        {
            "id": 1,
            "created_by": {
                "id": 1,
                "last_login": null,
                "username": "admin",
                "first_name": "",
                "last_name": "",
                "email": null,
                "is_active": true,
            },
            "updated_by": {
                "id": 1,
                "last_login": null,
                "username": "admin",
                "first_name": "",
                "last_name": "",
                "email": null,
                "is_active": true,
            },
            ...

When looking at the Pinia stores in devtools, I see createdById and updatedById are being set to the value 1 in the data in the registrations entity. The users entity is also being populated with the users related, but each registration has no created_by nor updated_by field in the store, despite it being an attribute of the Registration model.

Am I writing these models correctly?

Missing "./" export in "pinia-orm" package

Environment

Reproduction

difficult to reproduce this since i'm migrating a large project

Describe the bug

Migrating my Nuxt 2 (Bridge) application to Nuxt 3 and have encountered this error.

 ERROR  [commonjs--resolver] Missing "./" export in "pinia-orm" package                                                                              19:58:14


 ERROR  Missing "./" export in "pinia-orm" package                                                                                                   19:58:14

  at bail (node_modules/vite/dist/node/chunks/dep-5605cfa4.js:32678:8)

In the browser, it looks like so

[plugin:vite:import-analysis] Missing "./" export

Additional context

No response

Logs

No response

How to use mapRepo in composition API?

Describe the feature

I am facing data loss when I negivate to another page. I am using composition API and defining the following code on each page where required.

    const pinia = createPinia();
    const profileRepo = useRepo(Profile, pinia);

Is this re-iniitating code causing the data? How can I persist models data while navigating back and forth on page?
How to use mapRepo in composition API?

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

Keeping reactivity intact

Describe the feature

Keeping reactivity is incredible important to keep applications performant. However Pinia-ORM (& Vuex-ORM) generate a completely new javascript object for every single model in a collection everytime a mutation is triggered for something in that collection.

This has meant weโ€™ve been forced to move away from Vuex-ORM for our app.

Itโ€™s great to see the progress on Pinia-ORM! Maybe this something Pinia-ORM could fix?

more info; vuex-orm/vuex-orm#746

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

TypeError: attr.setKey is not a function

Environment

  • Operating System: Darwin
  • Node Version: v16.15.0
  • Nuxt Version: 0.0.0
  • Nitro Version: -
  • Package Manager: [email protected]
  • Builder: webpack
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

I just change the primaryKey name. And start getting this error. Now, I changed the name of Model from Pagination to Paginate, everything is working fine. There must be some caching strategy that is causing this bug.

Describe the bug

TypeError: attr.setKey is not a function
    at Pagination.$fillField (index.mjs:1609:98)
    at Pagination.$fill (index.mjs:1586:27)
    at new Model (index.mjs:1383:18)
    at new Pagination (Pagination.js:4:16)
    at Pagination.$newInstance (index.mjs:1542:12)
    at Query.checkAndGetSTI (index.mjs:749:70)
    at Query.hydrate (index.mjs:738:93)
    at Query.saveElements (index.mjs:643:120)
    at Query.save (index.mjs:632:13)
    at Repository.save (index.mjs:966:25)

Getting the above error. The model is as shown below:

import { Model } from "pinia-orm";
import { UidCast } from "pinia-orm/dist/uuid/v1";

export default class Pagination extends Model {
  static entity = "paginations";
  static primaryKey = "repoName";
  static fields() {
    return {
      id: this.attr(""),
      repoName: this.attr(""),
      indexOrder: this.attr(""),
      nextPage: this.attr(""),
    };
  }
  static casts() {
    return {
      id: UidCast,
    };
  }
}

At first, it was working fine and then it start throwing this error. Not sure what is causing the error.

Additional context

If there is some caching strategy, we can remove the cache on server restart or on some sort of watchdog event.

Logs

No response

Complete rewrite proposal

Describe the feature

Dear Mr Becker,

I would like to kindly propose that we would start a collab on rewriting this whole package.

I am sure that you have learned a lot of things during the creation of Pinia ORM, so I would like to ask you if you would be interested in rewriting everything for v2.0.

The aspects of the package that I would like to focus on are:

  1. Generic types (there are lots of possible improvements that could be achieved by generics see #816 for example);
  2. Better hook types (#1067);
  3. Better Model API:
    Typing a Partial type for Element taking into account the field declaration for the current Model instance. For example, let's say we have a Post model that has the following fields: @Uid field and a @Str(null) declare title: string | null. My proposed/theoretical RequiredModelAttributes<TModel extends Model> would see which fields can be null (in this case it would be the title field) and return a type that has all the required fields. This type could be used when using the Repository.save method (i.e. Repository.save<TModel extends Model>(model: RequiredModelAttributes<TModel>).
  4. Implement library interface overloads for globally declaring what entities the app has (e.g. module redeclaration/overloading with an Entities interface).

Let me know what you think, sir. I'm confident this could revolutionize the way people create Vue apps.

Thank you for your consideration!

All the best,
Alfa

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

save not working as expected

Hello,

we have issues using pinia-orm

our model:

import { Model } from 'pinia-orm';

export default class Channel extends Model {
  static entity = 'channels';
  static fields() {
    return {
      id: this.uid(),
      name: this.attr(''),
      description: this.attr('').nullable(),
    };
  }
  id!: number;
  name!: string;
  description!: string;
}

how we add data:

import Channel from 'src/orm/models/Channel';
import { useRepo } from 'pinia-orm';
const channelRepo = useRepo(Channel);
channelRepo.save([
  {
    name: 'Test',
    description: 'Test2',
  },
]);
console.log('Channel find result', channelRepo.all());

Channel items are created but have undefined values

i debugged a little bit and found that in the hydrate function
this.model.$newInstance(records, { relations: false }) does not contain the values

$newInstance calls the contructor of the model which calls $fill
the value returned from $fill still has the values:
$fill result Channelย {id: '2b677ce0-c7a0-11ec-aff0-791bb2832e65', name: 'Test', description: 'Test2'}

but in saveElements they are undefined...

am i doing anything wrong?

pinia-orm is on 0.9.2
node is v16
pinia v2.011
vue3 on latest

Maybe document simple workaround for useDefineForClassFields: true

As documented, pinia-orm (and vuex-orm) is incompatible with the TypeScript setting useDefineForClassFields: true

But the world is moving towards this setting, and the number of other packages which require it keeps growing.

While investigating this issue, I found a nice workaround which works in all 4 combinations - pinia-orm x vuex-orm x useDefineForClassFields: true x useDefineForClassFields: false

One just needs to change the model field declarations from id!: string to declare id: string, like below. This prevents the creation of new style class fields which hide the old style properties, while keeping the typing information:

export default class User extends Model {

  // ...

  declare id: string
  declare name: string
  declare email: string
}

declare was specifically added to TypeScript to solve useDefineForClassFields: true related issues:
https://www.typescriptlang.org/docs/handbook/2/classes.html#type-only-field-declarations

Maybe it's a good idea to document this possible workaround or maybe even recommended it as the way to declare new models. I'm not sure if it has other implications or failure modes, it works for my case, but I'm not using all pinia-orm features.

Querying models with belongsToMany relation are extremely slow

Environment

Reproduction

https://github.com/reramjiawan/pinia-orm-bug

Describe the bug

Querying models with belongsToMany relation are extremely slow.

Additional context

No response

Logs

No response

Flush does not work

Flush does not work. It could be because this model has a list as a primary key?

import { Model } from "pinia-orm";

export default class HumanSavedShow extends Model {
  static entity = "HumanSavedShow";
  static primaryKey = ["human_id", "show_id"];

  static fields() {
    return {
      human_id: this.uid(),
      show_id: this.uid(),
      added_at: this.number(0)
    };
  }
}
<template>
  <button @click="testFlush">Flush does not work</click>
</template>


<script setup lang="ts">
import { useRepo } from "pinia-orm";
import HumanSavedShow from "@/models/HumanSavedShow";

const SAVEDSHOWS = useRepo(Spotify_HumanSavedShow)

function testFlush() {
  console.log('There are ', SAVEDSHOWS.all().length, 'Shows');
  useRepo(Spotify_HumanSavedShow).flush();
  SAVEDSHOWS.flush();
  console.log('There are ', SAVEDSHOWS.all().length, 'Shows');
  SAVEDSHOWS.new()
  console.log('There are ', SAVEDSHOWS.all().length, 'Shows');
}
</script>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "App",
});
</script>

I would expect flush to delete all the records stored. https://next.vuex-orm.org/guide/repository/deleting-data.html#deleting-data

But it doesn't delete anything.

Error on building after version 0.9.3

After updating to version 0.9.3, I get the following error message when building:

ERROR in ./node_modules/@pinia-orm/nuxt/dist/runtime/nuxt2-plugin.mjs
Module not found: Error: Can't resolve 'pinia-orm' in 'xxx/node_modules/@pinia-orm/nuxt/dist/runtime'
 @ ./node_modules/@pinia-orm/nuxt/dist/runtime/nuxt2-plugin.mjs 1:0-33 3:17-25
 @ ./node_modules/.cache/nuxt/index.js
 @ ./node_modules/.cache/nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js ./node_modules/.cache/nuxt/composition-api/register.js ./node_modules/.cache/nuxt/client.js

ERROR in ./node_modules/pinia-orm/dist/index.mjs 1485:75
Module parse failed: Unexpected token (1485:75)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|       const type = model[this.morphType];
|       const id = model[this.morphId];
>       const related = ((_a = dictionary[type]) == null ? void 0 : _a[id]) ?? null;
|       model.$setRelation(relation, related);
|     });
 @ ./src/modules/application/storing/storing.service.ts 11:0-36 80:28-35 101:8-15 118:6-13
 @ ./src/modules/application/storing/storing.plugin.ts
 @ ./node_modules/.cache/nuxt/index.js
 @ ./node_modules/.cache/nuxt/client.js
 @ multi ./node_modules/@nuxt/components/lib/installComponents.js ./node_modules/.cache/nuxt/composition-api/register.js ./node_modules/.cache/nuxt/client.js

I am currently using pinia-orm with nuxt2.

I suspect that the error is in this commit 09e0ebe, here in line 26 the require was changed to .cjs

useRepo -> console.log()

Hey,

I have discovered a console.log in the built version which is a bit annoying :D

I'm using version 0.9.2
I found this in the index.mjs:2283:

function useRepo(modelOrRepository, storeGenerator, connection) {
  const pinia = getActivePinia();
  console.log(pinia);
  let database;
  database = new Database().setConnection(connection || "database");
  const repository = modelOrRepository._isRepository ? new modelOrRepository(database).initialize() : new Repository(database).initialize(modelOrRepository);
  if (storeGenerator) {
    repository.database.setStoreGenerator(storeGenerator);
  }
  try {
    database.register(repository.getModel());
  } catch (e) {
  }
  return repository;
}

Simple query on large object takes very long

Environment

vue3/pinia/pinia-orm/typescript

Reproduction

create a large model (40-50 fields)
add 400 of them to the store

// the below takes about 9 seconds for me
useRepo(Model).query().get()

Describe the bug

Querying large objects on a table with say 300-400 objects takes about 9 seconds on my computer

I didn't have this problem with Vuex ORM so that's why im registering this as a bug

Additional context

I can use the cache but 9 seconds is just too long even as an initial query

Reducing the number of fields reduces the problem. (with only 2 fields, the query still takes a second or so)

From the javascript performance panel in Firefox I can see that it is the $fill function that takes up the time.

I found this reddit threat that might be related
https://www.reddit.com/r/vuejs/comments/zh5xtf/tips_for_performance_issues_while_using_pinia_orm/

Im guessing that PiniaORM creates objects after the query, which are then returned, whereas Vuex ORM returns the actual objects in the store?

  • maybe there can be some kind of lazy querying system
  • maybe it would be an option to select a number of fields as part of the query?

Logs

No response

Using $save $update and $delete shortcuts

Describe the feature

Hi there,

In vuex-orm we can use $ prefixed methods on entities. It looks like it doesn't exist in pinia-orm. It's not mandatory as it's possible todo it differently, but it makes the migration a bit longer.

Example: https://vuex-orm.org/guide/data/inserting-and-updating.html#save-method

const user = new User()
user.name = 'John Doe'
user.$save()

Is it removed on purpose? Do you plan to add it? Or is there an existing alternative I missed?

Thanks

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

@OnDelete and Attr(object) leads to undefined error

Environment

latest npm/vue3/pinia/pinia-orm

Reproduction

Consider these classes:

class Location extends Model {}
class Country extends Model {
@hasone(() => Location, 'locationId') @onDelete('cascade') declare location: Location;
}

class PartyCenter extends Model {
@str('Main Street 1, NL') declare location: string;
}

Describe the bug

The OnDelete decorator seems to build a list of fields that need to be deleted, however it seems to be a global list? In any case, when using the OnDelete decorator on a field like above which also exists on another model as a different type (in the example the 'location' field), you get a TypeError:

typeError: this.schemas[this.entity][key].onDelete is not a function

Additional context

My question would be why this function:

static setFieldDeleteMode<M extends typeof Model>(

is static? Is it indeed supposed to collect these fields across all models? Why is that necessary, and would it not better to restrict this to only the instance?

Logs

Uncaught (in promise) TypeError: this.schemas[this.entity][key].onDelete is not a function
    initializeSchema index.mjs:1443
    $initializeSchema index.mjs:1602
    $boot index.mjs:1598
    Model index.mjs:1426


  static initializeSchema() {
    this.schemas[this.entity] = {};
    const registry = {
      ...this.fields(),
      ...this.registries[this.entity]
    };
    for (const key in registry) {
      const attribute = registry[key];
      this.schemas[this.entity][key] = typeof attribute === "function" ? attribute() : attribute;
      if (this.fieldsOnDelete[key])
>>>>>        this.schemas[this.entity][key] = this.schemas[this.entity][key].onDelete(this.fieldsOnDelete[key]);
    }
  }

Can't get it working on Nuxt2

Hey there! It's a great plugin. Though, I can't install it successfully on my NuxtJS.

` ERROR Failed to compile with 2 errors

ERROR in ./node_modules/pinia-orm/dist/index.mjs

Module parse failed: Unexpected token (341:18)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| var Uid = class extends Type {
| make(value) {

return value ?? nanoid();

| }
| };

@ ./models/models/restaurant.model.ts 29:0-34 53:2-7
@ ./models/index.ts
@ ./services/restaurant/restaurant.service.ts
@ ./services/index.ts
@ ./store/restaurant.store.ts
@ ./.nuxt/store.js
@ ./.nuxt/index.js
@ ./.nuxt/client.js
@ multi ./node_modules/eventsource-polyfill/dist/browserify-eventsource.js (webpack)-hot-middleware/client.js?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2Fbutler%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js

ERROR in ./node_modules/pinia-orm/dist/index.js

Module parse failed: Unexpected token (414:18)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| var Uid = class extends Type {
| make(value) {

return value ?? (0, import_non_secure.nanoid)();

| }
| };

@ ./node_modules/@pinia-orm/nuxt/dist/runtime/nuxt2-plugin.mjs 1:0-33 3:17-25
@ ./.nuxt/index.js
@ ./.nuxt/client.js
@ multi ./node_modules/eventsource-polyfill/dist/browserify-eventsource.js (webpack)-hot-middleware/client.js?reload=true&timeout=30000&ansiColors=&overlayStyles=&path=%2Fbutler%2F__webpack_hmr%2Fclient&name=client ./.nuxt/client.js`

And here is my package.json

{
"name": "ebutler-web",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:prettier": "prettier --check .",
"lint": "npm run lint:prettier",
"lintfix": "prettier --write --list-different ."
},
"dependencies": {
"@nuxtjs/auth-next": "5.0.0-1648802546.c9880dc",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/composition-api": "^0.33.0",
"@nuxtjs/pwa": "^3.3.5",
"@pinia-orm/nuxt": "^1.0.17",
"@pinia/nuxt": "^0.2.1",
"class-transformer": "^0.5.1",
"core-js": "^3.19.3",
"nuxt": "^2.15.8",
"pinia": "^2.0.16",
"pinia-orm": "^1.0.0-rc.4",
"reflect-metadata": "^0.1.13",
"ts-mixer": "^6.0.1",
"vue": "^2.6.14",
"vue-server-renderer": "^2.6.14",
"vue-template-compiler": "^2.6.14",
"vuetify": "^2.6.1",
"webpack": "^4.46.0"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"@nuxt/types": "^2.15.8",
"@nuxt/typescript-build": "^2.1.0",
"@nuxtjs/vuetify": "^1.12.3",
"eslint-config-prettier": "^8.3.0",
"prettier": "^2.5.1"
}
}

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @types/prettier Unavailable

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): update docs dependencies (@nuxtjs/plausible, yarn)

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/changelog.yml
  • actions/checkout v4.1.7@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2@60edb5dd545a775178f52524783378180af0d1f8
.github/workflows/ci.yml
  • actions/checkout v4@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2
  • actions/checkout v4@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2
  • codecov/codecov-action v4
  • actions/checkout v4@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2
  • actions/checkout v4@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2
.github/workflows/release-pr.yml
  • actions/checkout v4
  • actions/setup-node v4.0.2
.github/workflows/release.yml
  • actions/checkout v4.1.7@692973e3d937129bcbf40652eb9f2f61becf3332
  • actions/setup-node v4.0.2@60edb5dd545a775178f52524783378180af0d1f8
npm
docs-playground/package.json
  • @antfu/utils ^0.7.10
  • @headlessui/vue ^1.7.22
  • @types/splitpanes ^2.2.6
  • @vue/runtime-core ^3.4.31
  • @vue/runtime-dom ^3.4.31
  • @vue/shared ^3.4.31
  • @vueuse/core 10.11.0
  • @vueuse/integrations ^10.11.0
  • @vueuse/shared 10.11.0
  • file-saver ^2.0.5
  • jszip ^3.10.1
  • lz-string ^1.5.0
  • monaco-editor 0.50.0
  • monaco-editor-core ^0.50.0
  • pinia ^2.1.7
  • pinia-orm ^1.9.1
  • splitpanes ^3.1.5
  • theme-vitesse ^0.8.0
  • vscode-html-languageservice ^5.3.0
  • vue ^3.4.31
  • @antfu/eslint-config ^2.21.2
  • @iconify/json ^2.2.225
  • @types/file-saver ^2.0.7
  • @types/node ^20.14.9
  • @vitejs/plugin-vue ^5.0.5
  • @vue/compiler-sfc ^3.4.31
  • eslint ^9.6.0
  • typescript ^5.5.3
  • unplugin-icons ^0.19.0
  • unplugin-vue-components ^0.27.2
  • vite ^5.3.3
  • vite-plugin-pwa ^0.20.0
  • vite-plugin-windicss ^1.9.3
  • vue-tsc ^2.0.24
  • windicss ^3.5.6
  • yarn 4.3.1
docs/package.json
  • @nuxt-themes/docus 2.0.0-beta.13
  • @nuxtjs/plausible ^1.0.0
  • @nuxtjs/tailwindcss ^6.12.1
  • @nuxtlabs/github-module ^1.6.3
  • yarn 4.3.1
package.json
  • @lerna-lite/cli ^3.6.0
  • @lerna-lite/run ^3.6.0
  • @types/lodash.kebabcase ^4.1.9
  • @types/node ^20.14.9
  • changelogen ^0.5.5
  • conventional-changelog-cli ^5.0.0
  • enquirer ^2.4.1
  • execa ^9.3.0
  • expect ^29.7.0
  • globby ^14.0.2
  • lint-staged ^15.2.7
  • lodash.kebabcase ^4.1.1
  • minimist ^1.2.8
  • p-series ^3.0.0
  • pascalcase ^2.0.0
  • prettier ^3.3.2
  • rimraf ^6.0.1
  • semver ^7.6.2
  • sponsorkit ^0.14.7
  • typescript ^5.5.3
  • yorkie ^2.0.0
  • pnpm 9.4.0
packages/axios/package.json
  • @nuxt/eslint-config ^0.3.13
  • @nuxtjs/eslint-config-typescript ^12.1.0
  • @size-limit/preset-small-lib ^11.1.4
  • @vitest/coverage-v8 ^2.0.4
  • axios ^1.7.2
  • axios-mock-adapter ^1.22.0
  • eslint ^9.6.0
  • pinia ^2.1.7
  • size-limit ^11.1.4
  • typescript ^5.5.3
  • unbuild ^2.0.0
  • vitest ^2.0.4
  • vue-demi ^0.14.8
  • axios >=1.7.2
  • pinia-orm >=1.9.1
  • pinia >=2.1.7
packages/normalizr/package.json
  • @nuxt/eslint-config ^0.3.13
  • @nuxtjs/eslint-config-typescript ^12.1.0
  • @size-limit/preset-small-lib ^11.1.4
  • eslint ^9.6.0
  • immutable ^4.3.6
  • size-limit ^11.1.4
  • typescript ^5.5.3
  • unbuild ^2.0.0
packages/nuxt/package.json
  • @nuxt/kit ^3.12.3
  • @nuxt/devtools ^1.3.9
  • @nuxt/eslint-config ^0.3.13
  • @nuxt/module-builder ^0.8.1
  • @nuxt/schema ^3.12.3
  • @nuxtjs/eslint-config-typescript ^12.1.0
  • @pinia/nuxt ^0.5.1
  • @types/prettier ^3.0.0
  • eslint ^9.6.0
  • pinia ^2.1.7
  • prettier ^3.3.2
  • std-env ^3.7.0
  • typescript ^5.5.3
  • vite ^5.3.3
  • vue ^3.4.31
  • @pinia/nuxt ^0.5.1
packages/nuxt/playground/package.json
packages/pinia-orm/package.json
  • @nuxt/eslint-config ^0.3.13
  • @nuxtjs/eslint-config-typescript ^12.1.0
  • @pinia/testing ^0.1.3
  • @size-limit/preset-small-lib ^11.1.4
  • @types/node ^20.14.9
  • @types/prettier ^3.0.0
  • @types/uuid ^10.0.0
  • @typescript-eslint/parser ^7.15.0
  • @vitest/coverage-v8 ^2.0.4
  • @vitest/ui ^2.0.4
  • @vue/composition-api ^1.7.2
  • @vue/test-utils ^2.4.6
  • c8 ^10.1.2
  • core-js ^3.37.1
  • eslint ^9.6.0
  • happy-dom ^14.12.3
  • mkdist ^1.5.3
  • nanoid 4.0.2
  • pinia ^2.1.7
  • prettier ^3.3.2
  • size-limit ^11.1.4
  • std-env ^3.7.0
  • tsup ^8.1.0
  • typescript ^5.5.3
  • unbuild ^2.0.0
  • uuid ^10.0.0
  • vite ^5.3.3
  • vitest ^2.0.4
  • vue ^3.4.31
  • vue-demi ^0.14.8
  • pinia ^2.1.7
  • node 20.15.0

  • Check this box to trigger a request for Renovate to run again on this repository

Allow questions in the GitHub issue tracker

What problem is this solving

There is no place to ask questions about Pinia ORM. If its supposed to replace Vuex-orm, there should be.

Proposed solution

Allow questions instead of a redirect to the Pinia repository

Describe alternatives you've considered

Use reddit

belongsToMany multiple issues

Reproduction

class Contact extends Model {
  static entity = "contacts";

  static fields() {
    return {
      id: this.uid(),
      userId: this.attr(null),
      user: this.belongsTo(User, "userId"),
    }
  }
};

class User extends Model {
  static entity = "users";

  static fields() {
    return {
      id: this.uid(),
      groups: this.belongsToMany(Group, GroupUser, "userId", "groupId"),
    }
  }
};

class Group extends Model {
  static entity = "groups";

  static fields() {
    return {
      id: this.uid(),
    }
  }
};

class GroupUser extends Model {
  static entity = "group_user";
  static primaryKey = ["groupId", "userId"];

  static fields() {
    return {
      groupId: this.uid(), // Docs say this.attr(null) which throws an error
      userId: this.uid(),
    }
  }
};

useRepo(Contact).save({
  id: 1,
  user: {
    id: 1,
    groups: [{
      id: 1
    }]
  }
});

Expected behavior

Nested relationships are normalized and saved.

Actual behavior

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'attach')
    at EntitySchema2.<anonymous> (index.mjs:1103:26)
    at EntitySchema2.getId (normalizr.es.js:137:17)
    at EntitySchema2.normalize5 [as normalize] (normalizr.es.js:151:19)
    at visit2 (normalizr.es.js:478:17)
    at ArraySchema2.normalizeValue (normalizr.es.js:251:27)
    at normalizr.es.js:384:20
    at Array.map (<anonymous>)
    at ArraySchema2.normalize5 [as normalize] (normalizr.es.js:383:19)
    at visit2 (normalizr.es.js:478:17)
    at normalizr.es.js:176:32
(anonymous)	@	index.mjs:1103
getId	@	normalizr.es.js:137
normalize5	@	normalizr.es.js:151
visit2	@	normalizr.es.js:478
normalizeValue	@	normalizr.es.js:251
(anonymous)	@	normalizr.es.js:384
normalize5	@	normalizr.es.js:383
visit2	@	normalizr.es.js:478
(anonymous)	@	normalizr.es.js:176
normalize5	@	normalizr.es.js:172
visit2	@	normalizr.es.js:478
(anonymous)	@	normalizr.es.js:176
normalize5	@	normalizr.es.js:172
visit2	@	normalizr.es.js:478
(anonymous)	@	normalizr.es.js:360
normalize2	@	normalizr.es.js:359
visit2	@	normalizr.es.js:475
normalize4	@	normalizr.es.js:515
normalize	@	index.mjs:1147
process	@	index.mjs:1142
save	@	index.mjs:1454
save	@	index.mjs:1685
read	@	db.js?t=1658970281973:38

Additional information

Issue 1. Even though the docs say the pivot model's id fields are this.attr(null), this causes an error. Setting them each to this.uid() fixes that. I'm not sure what the behavior should be because the docs are unclear.

Issue 2. (The main issue) belongsToMany appears to work one level deep, but not nested further down as reproduced via the code above.

Property 'belongsToMany' does not exist on type 'typeof ...

Thank you for creating this package!

Reproduction

I created a simple model but the .belongsToMany gives me the error Property 'belongsToMany' does not exist on type 'typeof ...

Steps to reproduce the behavior

  1. Install piniaorm
  2. Create a model (group.ts)
import { Model } from "pinia-orm";

import GroupMember from "./GroupMember";
import Member from "./Member";

export default class Group extends Model {
  static entity = "Group";

  static fields() {
    return {
      id: this.uid(),
      title: this.string(""),
      description: this.string(""),
      members: this.belongsToMany(Member, GroupMember, "group_id", "member_id"),
    };
  }
}
  1. See that your editor (Webstorm in my case) says that belongsToMany does not exist.

Expected behavior

I would expect this.belongsToMany to exist and behave just like the original docs described it. https://vuex-orm.org/guide/model/relationships.html#many-to-many

Actual behavior

It says belongsToMany does not exist.

Additional information

If you didn't implement belongsToMany it might be good to put this in the README.md

[Peer-Bug] @nuxt/kit 3.3.0 breaks nuxt v2.16

Environment

See here: nuxt/nuxt#19717

Reproduction

See here: nuxt/nuxt#19717

Describe the bug

Pinia-ORM depends on Nuxt Kit. Its last version 3.3.0 breaks Nuxt2 with Nuxt-bridge. Pinning to @nuxt/kit 3.2 solves the issue.

The root issue is here: nuxt/nuxt#19717

The work around I've used to fix this was to add this block in package.json:

  "resolutions": {
    "**/@nuxt/kit": "^3.2.0 < 3.3.0"
  }

Additional context

No response

Logs

No response

TypeScript definitions for models cause null values.

Thanks you for solving the flush thing! This is a very nice thing to have.

Now I have this other problem. I would love to add types to my models to get editor suggestions and the general benefits of Typescript. I tried to add the type definitions as outlined here: https://next.vuex-orm.org/guide/model/decorators.html. When I did this I did get the type information and nice type suggestions in my ide so that works.

But as soon as I defined a type for a field (either with or without a decorator) the field becomes null when queried.

Maybe I am missing something?

Reproduction

Use this simple model:

import { Model, Uid, Str } from "pinia-orm";

export default class Todo extends Model {
  static entity = "Todo";

  // static fields() {
  //   return {
  //     id: this.uid(),
  //     text: this.string(""),
  //     name: this.string(""),
  //   };
  // }
  //
  // id!: string;
  // text!: number;
  // name!: number;

  @Uid()
  id!: string;

  @Str("Todo Text")
  text!: string;

  @Str("Todo Name")
  name!: string;
}

You can try defining with the decorators or using the commented out fields static method and the type definitions.

Now have a component like this:

<template>
  <button @click="todo.save({text:"Fix TS support", name:"TS Todo"})">Add todo</button> 
  <button @click="todo.flush()">Clear Todos</button>
  <span>{{all_todo_text}}</span>
<template>

<script setup lang="ts">
import { computed } from "vue";
import Todo from "@/Todo";

const todo = useRepo(Todo);
const all_todo_text = computed(() => todo.all().map((t) => t.text));
</script>

Steps to reproduce the behavior

  1. Build the above code
  2. Click the add todo button
  3. Notice that the todo texts are null
  4. Comment out the decorators and comment in the static field method
  5. Notice that the todos are now the default given in the decorator (Even though I did give a value in save)
  6. Add another todo and notice that the new todos do have the value given in the .save
  7. Now if you comment in the type definitions below the field method everything goes to null again.

Expected behavior

I would expect the values of the model to not be affect (turn to null) by the type definitions.

Actual behavior

When adding type definitions to models the values of the fields turn to null and in the case of decorators the values given in .save are ignored. With this the type definitions are not useable.

Models from mapped repo instance are not reactive under certain conditions

Environment

Pinia ORM 1.5.1 in the playground

Reproduction

https://pinia-orm-play.codedredd.de/#N4IgDghgxg1hDmBTAziAXAbVAOwgW0XRADcBXRAWgBNE8BLEAGhGQHtSAnKQtEU7MDHhMQNZFA50wAFzqtsRAGrkABABFadFQAoAFhAA2AMxV1sKgGIdE2KLoCUp5CogqaxRAdZgz8FaVkDOmkATxcDLwB3ZxD2FWlWFUjJaUQVAFVsOg8OZEMVZTSAGToAIw4ISRQVI1YOAtUAJhUAMhUAZhFOAyJdaWkwZDQAemH+QXgAOihWPGGyShp6YaDS4bMaAA9JvAArVABfRhx8HhAAAQXSZERh5H1rKhE2Tm4icaERMQkpWXkiADKD0QVAaiHSN38gWCdBQky6HB6vD6AyGow+Uxmc0u5Gut3ulRB5wArJMAAyTACM62wW0mKDwk32ICOJwIRBxiDxwxm1me7C4ZwxXxQPxkcgUvAAwqwIogoH9zKwTCgbthZPlCioZXgwKxkDD5BlobIUAikSAUYMRmMBEJprNhpzubzECTyVSaXSGUzDscQLh2bxOcN3AlZcgKBAfPzXkK7cJmN9JOL-rwAJLqxAVBVJYK6eK6NJasOsCM1DizQtpSBIc29frW9EJh3YhahxDEcMGSPRujnABsk0antWwwZXsQ22ZrIDpyIPiyEFjgveCZF4hTiqIAAUzHRl8xug3UTaMa3houD+cRxTGgBOUN0ZDSS-7iD05B4CjlVjRbO+iy-qBmc5xXhAFB1HM2BQYYdAAF4cCuby8MKSailuEq7u+KgAPIAEoALIqDBHB4HBiH1sijZoraEwXmB76QWRwykeRQSIeclJUuST4vpO2x7H6bJnLgMF0FQrHyBQNxQJwhDMC8q6oeu6Gbr8WG8AAchA4lPEeiInk2dH2lirG6awEnnAALB6ZJSdgMnyvJAmAbOIELkxUHIfGEwbmK268HuS54URVGWjRZ4tmZ4HMXgXGTKS1JUM+r4bFOOwzgAuswRh0AYZpoKAACCYBgJMCzoKAqS6gYECpEQAA8KXEAAOuYKjwJIVAALytSAAB+NRRBQMwGJ10YUNZ-XtSoKhgHV3B9SAMxZuqo02Kk9TBLQkbcFmHAzR1ujLZuiA2Edc21Oqy14PIrCXSoAB8s0qM12QqFAdXIMgt1mBQkQUBg7RkmSYCbFl-UvR1c2NaQBjQ3NSNvUET14vUIEVlW5FlSCKjWHqTgkaw0j+GAVD1b4aAqMAwD+DcHDcXluTSDpBAqAcBw03T6Pcd9rOnBzByNSsdCI8jKNi+jJGC0YlZ4CRiCRAYYQSIg9V4wTiTPmTFOyNg8DU7T9PZiOzMvmzaSc9zJscCO-OW0LIuo69sNjAjr0iy10Ne9kT3PAFRB0LqdSk3TWJgAEeNc3LVYAOQLHH7XB3qHBhyb+GIHqjAqDjmd6s4MfyyocexVBSdZCHacZAzWMK3HkzDBCAH7BXKeh249WuLH9eN3rH6t+17WrS+tv54kPW59G4-INowDo+P1PNxwBz2JMC9Z6w2j2O1G96pMeQeNo-frwzyA79gw-yKPvMqJPEdR1Q2jb3fT1j5vkyREW1jaHHElxznSka9zbSG3hfEepN0bNHvrMSOqQn4vx6m-PE49tDLzXl-bMiBf7-0AcAugLMwFD2wDcaQAAVYOiB2CgMQdDYAr1RiFh1nYXSSAib6FxlkA2phzAWWkN-FQCxPqwPkJtV6edN6z3ngzReNdsyr1PtmVBa9D7YOABJamlIc4O1ONTOOpByYayoHHVe7UjgqGJKDMkF92qkIoQQahz9HBIPavQjqjD+HMP0AbNIHCwA2F8CoI0rgogqAKh4capQwjRgWiEQJ-C0jQEVK9CBts76d2kB+dGyAMBkkhh1dGkwdHs0nvowx8CVCNArnNCRBc5571YEvBmCiGnb0mOBAECQf4qIgEfYAlJqbo1MdgcxlIrHWPakBUQXdAJFRADVBaGsiABy3EQKcqdSY0CMBAeGYdXrZOphgV2NNjlzQ0SoLRpyZYED0QAKVYLobAABpABVzeldw4OmPA8B0iIj0VaWidB2kVGIB86YUBhggzJAAfmDvAHqxIADsryYZIxAZbO5DzsAoolmEiAFtdElxeYwY5RxjluNxecxoJLUVzRAnc3SiA1A4olu8zJnzvm-IMP8yKowgVgBBWCqAEKoWwu+T1ayxIWXI3RYSuOtzGXSqRsUxAei1CsEQEqg4r18kHCmcvWZ1VaCLIarwFZvwg5V3ToRVgNBxpF3jmXMiFd2rrI7lsnZBhSZfXxc4ZeKgpypFpM4G1dqTkdRfJTKAAb1TBDCKU7JLqI2ZNkNGvKngqCz0cBSpG1hpCcHMDm5G5zPHIHXhJbeNLcX0qYWWl8kgDa-zjvYKtrLQXsq+T8v5taD7SAbfAJtLarmypuT2+tvhB2tuRiq6mpbe39sHaS162qRksk5kAA

Describe the bug

(1) We have a component with a mapped repo instance and a model queried with that instance in a computed variable (user1 in the example).
(2) We have another component or part off the app with its own repo instance (first timeout in the example).
(3) We update data with this other instance.
(4) The data change is not reflected in user1.

For me, that use case is perfectly possible: I can change data from everywhere in the app and this data change should be reflected in every model. The same goes for the low level actions of the store, see second timeout.

I have found a workaround by using the useRepo method in the computed function (see user2) . But I want to be able to use the mapRepos helper.

Additional context

I assume the problem comes from the hydratedDataCache of the repo - every instance creates a new cache. Shouldn't the cache be shared between repo instances of the same model?

Logs

No response

Make .delete know about .with

Describe the feature

I have a reasonably big orm schema. Lets say it has humans with baskets that have a lot of bananas and kiwi and humans also have a hat. If I want to completely delete a human and also all their baskets and bananas and their hat it would be nice if that could happen like this:

const delete_id = 3;
const humanORM = useRepo(HumanORM);

humanORM.query()
        .whereId(delete_id)
        .with("basket", (basket) => basket.with("apples").with("kiwi"))
        .with("hats")
        .delete()

While this does return the entire query as you would expect with all the relationships it only deletes the top level object. The human in this case. The baskets and fruits and hats remain,

So that means that if you want to fully delete a Human you must do something like this:

const delete_id = 3;
const humanORM = useRepo(HumanORM);

const human = humanORM.query().whereId(delete_id).with("basket", (basket) => basket.with("apples").with("kiwi")).with("hat").delete()

if (human) {
   // human with id of 3 existed
   if (human.basket) {
      
      basketORM = useRepo(basketORM)
      deleted_baskets = basketORM.query().where("human_id", delete_id).delete()
      deleted_basket_ids = deleted_baskets.map(basked => basked.id)
    
      kiwiORM = useRepo(KiwiORM)
      bananaORM = useRepo(BananaORM)

     kiwiORM.query().whereIn("basked_id", deleted_basket_ids).delete()
     bananaORM.query().whereIn("basked_id", deleted_basket_ids).delete()
   }

   if (human.hat) {
      hatORM = useRepo(HatORM)
      hatORM.destroy(human.hat.id)
   }
}

That is quite some code to delete everything. It would be really great if there .delete would just already know about the .with that where used.

You might not want to change the behavior of .delete to not break things that depend on it behaving as it does today. You could introduce a new method that does take into account the .with. Here are some ideas for names: .deleteWith, .burn, .deleteCascade, recursiveDelete, deleteRecursive, cascadeDelete, withDelete, withBurn().delete() or another method on the delete() like .delete.cascade(), .delete.withwith(), .delete().burn(), .delete().recursive()

You could also flip it around and put the .with methods on the .delete so that would look like:

humanORM.query().whereId(delete_id).delete().with("basket", (basket) => basket.with("apples").with("kiwi")).with("hats")

Let me know what you think ๐Ÿ™‚

Another idea that I just want to throw out there is to think about defining foreign key update and delete violations on modules. That could be another way to implement this. These rules could be part of the .belongsTo method for instance.

I don't really know what you mean with modules so I don't know if this can be implemented as a module.

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

Define a field as undefined not working as expected

Environment

Vue 2 + pinia + pinia ORM

Reproduction

I'm trying to create a field that is undefined by default but it is set as null.
creationDate: this.attr(undefined),

const newExp = new Experience();

Expected
{ creationDate: undefinedย }ย 

Result
{ creationDate: nullย }ย 

Describe the bug

It should set a default value as undefined but it's null

Additional context

No response

Logs

No response

When I import a model there is a vuex error

index.mjs:1471 Uncaught (in promise) Error: [Vuex ORM] The record is missing the primary key. If you want to persist record without the primary key, please define the primary key field with the uid attribute

This is my model:

import { Model } from "pinia-orm";

export default class AlbumImage extends Model {
  static entity = "AlbumImage";
  static primaryKey = "url";

  static fields() {
    return {
      url: this.string(null),
      height: this.number(null),
      width: this.number(null),
      album_id: this.string(null), 
    };
  }
}

Then this in a vue component.

import {useRepo} from "pinia-orm";

import IMg from '/src/models/Spotify/AlbumImage'
const t = useRepo(IMg)

console.log(t.new())

It gives a vuex orm error

index.mjs:1471 Uncaught (in promise) Error: [Vuex ORM] The record is missing the primary key. If you want to persist record without the primary key, please define the primary key field with the uid attribute

Using hooks with Typescript

Describe the feature

Hi โœ‹๐Ÿผ
I'm trying to use saved(model, record) hook (docs) with TS, of which type are the args model, record ?
If I set saved(model: Post) I got the following error:
Class static side 'typeof Post' incrorrectly extends base class static side 'typeof Post

Thanks for your help

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

Buffer is not defined

Environment

โ”œโ”€โ”€ @quasar/[email protected]
โ”œโ”€โ”€ @quasar/[email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ””โ”€โ”€ [email protected]

Reproduction

useRepo(Post).with("comments").get();

Describe the bug

Uncaught (in promise) ReferenceError: Buffer is not defined
    at generateKey (pinia-orm.5b3dce23.mjs:112:66)
    at Query.get (index.mjs:462:105)
    at HasMany.match (index.mjs:1225:51)
    at Query.eagerLoadRelation (index.mjs:559:14)
    at Query.eagerLoadRelations (index.mjs:552:12)
    at Query.internalGet (index.mjs:484:12)
    at Query.get (index.mjs:461:19)
    at ReactiveEffect.fn (IndexPage.vue:26:48)
    at ReactiveEffect.run (reactivity.esm-bundler.js:185:25)
    at get value [as value] (reactivity.esm-bundler.js:1147:39)

Additional context

No response

Logs

No response

Can't make it work with Nuxt2.15.8

Reproduction

I'm currently trying to migrate our vuex-orm project to use pinia + pinia-orm. Sadly though, I haven't been able to install pinia(-orm) without getting errors.

I already tried the steps mentioned in the docs about Nuxt2, making my package.json look like:

{
  // general package.json stuff,
  "resolutions": {
    "nanoid": "3.3.4"
  },
  "dependencies": {
    "@dansmaculotte/nuxt-zendesk": "0.4.1",
    "@nuxt/types": "^2.15.8",
    "@nuxt/typescript-build": "^2.1.0",
    "@nuxtjs/auth": "^4.9.1",
    "@nuxtjs/axios": "^5.13.1",
    "@nuxtjs/composition-api": "^0.32.*",
    "@nuxtjs/style-resources": "^1.0.0",
    "@pinia-orm/nuxt": "^1.0.18",
    "@pinia/nuxt": "0.2.1",
    "@tinymce/tinymce-vue": "^2.1.0",
    "@toast-ui/vue-image-editor": "^3.14.0",
    "@tobjoern/vue-color-gradient-picker": "git+https://github.com/Tobjoern/vue-color-gradient-picker.git",
    "@vuex-orm/core": "0.31.13",
    "core-js": "^3.8.3",
    "cross-env": "^5.2.0",
    "element-ui": "^2.13.0",
    "lodash": "^4.17.20",
    "lodash.throttle": "^4.1.1",
    "messagebird": "^3.6.2",
    "nanoid": "3.3.4",
    "nuxt": "^2.15.8",
    "nuxt-dropzone": "^1.0.4",
    "nuxt-gmaps": "^1.2.10",
    "nuxt-intercom": "^1.0.8",
    "nuxt-jsonld": "^1.5.0",
    "nuxt-property-decorator": "^2.9.1",
    "nuxt-purgecss": "^1.0.0",
    "nuxt-user-agent": "^1.2.2",
    "pinia": "^2.0.18",
    "pinia-orm": "^1.0.0-rc.5",
    "tinymce": "^5.5.1",
    "vue-agile": "^1.1.3",
    "vue-cool-lightbox": "^2.6.3",
    "vue-echo": "^1.0.2",
    "vue-i18n": "^8.21.1",
    "vuex": "^3.5.1"
  },
  "devDependencies": {
    "@babel/core": "^7.18.10",
    "@babel/eslint-parser": "^7.13.10",
    "@babel/preset-env": "^7.18.10",
    "@fortawesome/fontawesome-pro": "^5.15.0",
    "@nuxtjs/eslint-config": "^5.0.0",
    "@nuxtjs/eslint-module": "^3.0.2",
    "@nuxtjs/laravel-echo": "^1.0.3",
    "@nuxtjs/tailwindcss": "^3.4.2",
    "@types/jest": "^28.1.6",
    "@vue/test-utils": "^1.0",
    "@vue/vue2-jest": "^28.0.1",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^28.1.3",
    "babel-plugin-component": "^1.1.1",
    "eslint": "^7.18.0",
    "eslint-config-prettier": "^7.2.0",
    "eslint-plugin-nuxt": "^2.0.0",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^7.5.0",
    "jest": "^28.1.3",
    "jest-environment-jsdom": "^28.1.3",
    "jest-serializer-vue": "^2.0.2",
    "nodemon": "^1.18.10",
    "prettier": "^2.2.1",
    "pusher-js": "^5.1.1",
    "ts-jest": "^28.0.7",
    "typescript": "^4.7.4",
    "vue": "2.6.14",
    "vue-jest": "^3.0.7",
    "vue-server-renderer": "2.6.14",
    "vue-template-compiler": "2.6.14"
  }
}

I still get the errors from Nuxt stating:

Module parse failed: Unexpected token (287:39) You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders | const type = model[this.morphType]; | const id = model[this.morphId]; > const related = dictionary[type]?.[id] ?? null; | model.$setRelation(relation, related); | });

Making me think the ?? operator is not supported. My nuxt.config.js is as follows as well:

import webpack from 'webpack'

export default {
  mode: 'universal',
  // Disable annoying notice if we want to send anonymous data.
  telemetry: false,
  /*
   ** Headers of the page
   */
  head: {
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
    ],
  },
  router: {
    prefetchLinks: false,
    middleware: ['Server/userAgent'],
  },

  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#f00', height: '4px' },

  /*
   ** Global CSS
   */
  css: [
    { src: '@fortawesome/fontawesome-pro/css/all.min.css', lang: 'css' },
    '@/assets/css/tailwind.css',
  ],

  /*
   ** Plugins to load before mounting the App
   */
  plugins: [
    '@/plugins/ui-store',
    '@/plugins/axios',
    '@/plugins/graphql/plugin',
    '@/plugins/vue-agile',
    '@/plugins/path-handler.js',
    '@/plugins/storage.js',
    '@/plugins/jsonld',
  ],

  /*
   ** Server middleware
   */
  serverMiddleware: ['@/middleware/Server/noSsr'],

  /*
   ** Nuxt.js modules
   */
  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/auth',
    'nuxt-user-agent',
    '@pinia-orm/nuxt',
    // '~/modules/caching/caching'
  ],
  /*
  cache: {

    key(route, context) {
      if (context.req.originalUrl.startsWith('/cms')) {
        return false
      }

      return true
    },

    store: {
      type: 'filesystem',
      max: 100,
      ttl: 60
    }
  },

  auth: {
    debug: false,
    cookie: {
      options: {
        sameSite: 'strict',
      },
    },
    rewriteRedirects: true,
    redirect: {
      login: '/login',
      logout: '/login',
      callback: false,
      home: false,
    },
    strategies: {
      local: {
        endpoints: {
          login: {
            url: '/auth/login',
            method: 'post',
            propertyName: 'token',
          },
          logout: { url: '/auth/logout', method: 'post' },
          user: { url: '/auth/user', method: 'get', propertyName: 'user' },
        },
        // tokenRequired: true,
        // tokenType: 'bearer',
      },
    },
    plugins: [
      { src: '@/plugins/i18n', mode: 'client' },
      { src: '~/plugins/echo.js', mode: 'client' },
      '@/plugins/permissions',
    ],
  },
  buildModules: [
    '@nuxtjs/tailwindcss',
    'nuxt-purgecss',
    '@nuxt/typescript-build',
    '@nuxtjs/composition-api/module',
    ['@pinia/nuxt', { disableVuex: false }],
  ],

  /*
   ** PurgeCSS
   ** https://github.com/Developmint/nuxt-purgecss
   */
  purgeCSS: {
    // enabled: process.env.NODE_ENV === 'production', // or `false` when in dev/debug mode
    enabled: false, // TEMP SET ON FALSE TO REMOVE CSS BUGS FOR NOW
    whitelist: [
      'static/css/element-ui/theme-modual/index.css',
      'vue-color-gradient-picker/dist/index.css',
      'assets/css/main.css',
      'body',
      'html',
      'nuxt-progress',
    ],
    whitelistPatternsChildren: [/^el-/, /^fa-/, /^v-modal/],
  },
  buildDir: '.nuxt/build',
  build: {
    splitChunks: {
      layout: true,
      pages: true,
    },
    optimization: {
      splitChunks: {
        // Force Webpack to split some vendor packages
        cacheGroups: {
          // https://stackoverflow.com/questions/48985780/webpack-4-create-vendor-chunk
          tinyMceVendor: {
            test: /[\\/]node_modules[\\/](tinymce)[\\/]/,
            name: 'tinymcevendor',
          },
          lodashVendor: {
            test: /[\\/]node_modules[\\/](lodash)[\\/]/,
            name: 'lodashvendor',
          },
          elementUiVendor: {
            test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
            name: 'elementuivendor',
          },
          vendor: {
            test: /[\\/]node_modules[\\/](!tinymce)(!lodash)(!element-ui)[\\/]/,
            name: 'vendor',
          },
        },
      },
    },
    transpile: ['vue-agile', 'pinia-orm'],
    /*
     ** PostCSS setup
     */
    babel: {
      plugins: [
        ['@babel/plugin-proposal-private-methods', { loose: true }],
        ['@babel/plugin-proposal-private-property-in-object', { loose: true }],
        [
          'component',
          {
            libraryName: 'element-ui',
            styleLibraryName: '~static/css/element-ui/theme-modual/',
          },
        ],
      ],
    },
    postcss: {
      // Add plugin names as key and arguments as value
      // Disable a plugin by passing false as value
      plugins: {
        'postcss-url': {},
        cssnano: {
          preset: 'default',
          discardComments: { removeAll: true },
          zIndex: false,
        },
      },
      // Change the postcss-preset-env settings
      preset: {
        stage: 0,
        autoprefixer: {
          cascade: false,
          grid: false,
        },
      },
    },
    extractCSS: { ignoreOrder: true },
    plugins: [
      new webpack.ProvidePlugin({
        mapboxgl: 'mapbox-gl',
      }),
      new webpack.NormalModuleReplacementPlugin(
        /element-ui[\/\\]lib[\/\\]locale[\/\\]lang[\/\\]zh-CN/,
        'element-ui/lib/locale/lang/en'
      ),
    ],
  },
}

Steps to reproduce the behavior

  • I've tried installing all the latest versions of vue and such
  • I've tried installing specific older versions without any luck

Expected behavior

A working Nuxt2 installation.

Actual behavior

The error mentioned above.

Dynamic default variables

Describe the feature

It would be really great if a default value for a field in on a model could be dynamic at the runtime with a function.

At the moment if you define a model all the default values are set when the JavaScript loads. You can set a default value at the runtime like this:

import { Model } from "pinia-orm";

const utcsec = () => Math.floor(Date.now() / 1000);

const randint = (low: number, max: number): number =>
  (Math.round(Math.random() * 10) % (max ?? low)) + (max ? low : 0);

export default class HUMAN extends Model {
  static entity = "Human"; # For a bit
  static primaryKey = "id";

  static fields() {
    return {
      id: this.uid(),
      hat_color: this.string(["red", "white", "blue"][randint(0,2)]), 
      name: this.string("Nameless"),
      last_noticed: this.number(utcsec()),
    };
  }

  declare id: string;
  declare hat_color: "red" | "white" | "blue";
  declare name: string;
  declare last_noticed: number;
}

Even though this takes the current time at the startup, the value of that last_noticed will not be updated because the value is calculated at the start. Similarly, one hat_color is chosen at the start and that is it. All humans will get that hat color. It would be great if the fields could take a callable and that that callable is called to provide a return value if no value is provided for the field.

It looks something like this:

import { Model } from "pinia-orm";

const utcsec = () => Math.floor(Date.now() / 1000);

const randint = (low: number, max: number): number =>
  (Math.round(Math.random() * 10) % (max ?? low)) + (max ? low : 0);

let count = 0;

export default class HUMAN extends Model {
  static entity = "Human";
  static primaryKey = "id";

  static fields() {
    return {
      id: this.uid(),
      hat_color: this.string((0 => ["red", "white", "blue"][randint(0,2)]), 
      name: this.string("Nameless"),
      last_noticed: this.number(utcsec),
      count: this.number(() => count++)
    };
  }

  declare id: string;
  declare hat_color: "red" | "white" | "blue";
  declare name: string;
  declare last_noticed: number;
}

As you can see there are already 3 different use cases for this and I think that the ability to set a default variable with a closure is really nice.

Attempted workaround

I tried to update the default value by redefining the static fields method on the model instance. Like this:

HUMAN.fields = () => {
    return {
      id: Model.uid(),
      hat_color: Model.string(0 => ["red", "white", "blue"][randint(0,2)),
      name: Model.string("Nameless"),
      last_noticed: Model.number(utcsec)
    };
  };

But replacing the static method does not seem to work. It still returns the same time and color for me.

I think this dynamic default variables are a good addition to pinia orm. Vuex orm supportes closure default values. You could also do type checking on the return type of the function. So if it is a this.number or @Number then the return type of the callable should be a number as well. Same for this.string then the return type of the function should be a string. Attr perhaps could just have any.

Alternatively, you could have like an onCreate method or something that the programmer can define on the model that can set default variables. But that would be harder to translate to the decorators I think.

Or maybe I am missing a way to do something like this?

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

multiple belongsTo relationships between 2 entities lead to unintended outcome

Environment

{
  "name": "test1",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "test:e2e": "vue-cli-service test:e2e",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@capacitor/app": "1.1.1",
    "@capacitor/core": "3.5.1",
    "@capacitor/haptics": "1.1.4",
    "@capacitor/keyboard": "1.2.2",
    "@capacitor/status-bar": "1.0.8",
    "@ionic/vue": "^6.0.0",
    "@ionic/vue-router": "^6.0.0",
    "axios": "^0.27.2",
    "core-js": "^3.6.5",
    "date-fns": "^2.28.0",
    "dayjs": "^1.11.5",
    "eslint-config-typescript": "^3.0.0",
    "install": "^0.13.0",
    "ionic-logging-service": "^14.0.0",
    "lodash": "^4.17.21",
    "npm": "^8.13.1",
    "pinia": "^2.0.14",
    "pinia-orm": "^1.0.0",
    "swiper": "^8.3.2",
    "tslint": "^6.1.3",
    "vue": "^3.2.21",
    "vue-promised": "^2.2.0",
    "vue-router": "^4.0.12"
  },
  "devDependencies": {
    "@capacitor/cli": "3.5.1",
    "@ionic/cli": "6.19.1",
    "@types/jest": "^27.0.2",
    "@types/lodash": "^4.14.182",
    "@typescript-eslint/eslint-plugin": "^5.26.0",
    "@typescript-eslint/parser": "^5.26.0",
    "@vue/cli-plugin-babel": "~5.0.0-rc.1",
    "@vue/cli-plugin-e2e-cypress": "~5.0.0-rc.1",
    "@vue/cli-plugin-eslint": "~5.0.0-rc.1",
    "@vue/cli-plugin-router": "~5.0.0-rc.1",
    "@vue/cli-plugin-typescript": "~5.0.0-rc.1",
    "@vue/cli-plugin-unit-jest": "~5.0.0-rc.1",
    "@vue/cli-service": "~5.0.0-rc.1",
    "@vue/test-utils": "^2.0.0-rc.16",
    "@vue/vue3-jest": "^27.0.0-alpha.3",
    "babel-jest": "^27.3.1",
    "cypress": "^8.7.0",
    "eslint": "^8.17.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-vue": "^9.4.0",
    "jest": "^27.3.1",
    "ts-jest": "^27.0.7",
    "typescript": "^4.3.5"
  },
  "description": "An Ionic project",
  "prettier": {
    "singleQuote": true,
    "printWidth": 120
  }
}

Reproduction


class EventItem extends Model {
  static entity = 'eventitem';
  static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      name: this.string(''),

      participants: this.belongsToMany(People, EventItemPeople, 'eventitem_id', 'people_id', 'id', 'id'),
      // providers relationship seems to overwrite participants relationship
      providers: this.belongsToMany(People, EventItemPeople2, 'eventitem_id2', 'people_id2', 'id', 'id'),
      animals: this.belongsToMany(Animal, EventItemAnimal, 'eventitem_id', 'animal_id', 'id', 'id'),
    };
  }
}

class EventItemPeople extends Model {
  static entity = 'eventitempeople';

  static primaryKey = ['eventitem_id', 'people_id'];
  //   static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      eventitem_id: this.uid(),
      people_id: this.uid(),
    };
  }
}

class EventItemPeople2 extends Model {
  static entity = 'eventitempeople2';

  //   static primaryKey = ['eventitem_id1', 'people_id1'];
  static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      eventitem_id2: this.uid(),
      people_id2: this.uid(),
    };
  }
}

class People extends Model {
  static entity = 'people';

  static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      name: this.string(''),
    };
  }
}

class Animal extends Model {
  static entity = 'animals';

  static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      name: this.string(''),
    };
  }
}

class EventItemAnimal extends Model {
  static entity = 'eventitemanimal';

  //   static primaryKey = ['eventitem_id1', 'people_id1'];
  static primaryKey = ['id'];

  static fields() {
    return {
      id: this.uid(),
      eventitem_id: this.uid(),
      animal_id: this.uid(),
    };
  }
}

export { EventItem, People };

    useRepo(EventItem).save([
      {
        id: -1,
        name: 'item 1',
        participants: [{ id: -1000, name: 'Carsten' }],
        providers: [{ id: -1001, name: 'Peter' }],
        animals: [{ id: -2000, name: 'dog 1' }],
      },
    ]);

Screenshot 2022-09-19 at 18 00 53

Describe the bug

First of all: thanks for the great work on this!

I ran across a problem with multiple n-m relationships between two entities EventItem and People.
People can be participants of EventItems and they can also be providers to EventItems.

It seems to me that the relationship that is declared last actually wins. So in the example above, there will be only the eventitempeople2 relationship. According to the vue dev-tools, the participant "Carsten" with id -1000 is inserted into the eventitempeople2 relationship.
Switching the participant and provider relationships, creates exactly the opposite effect.

I added the Animals relationship just to check whether a different m - n relationship to another entity does work - and it does.
This is a reduced example of the data model I actually used. In that model the second relationship to People ran via another entity in-between EventItem and Participant. But this caused the same issue.

Any ideas?

Additional context

No response

Logs

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.