codedredd / pinia-orm Goto Github PK
View Code? Open in Web Editor NEWThe Pinia plugin to enable Object-Relational Mapping access to the Pinia Store.
Home Page: https://pinia-orm.codedredd.de/
License: MIT License
The Pinia plugin to enable Object-Relational Mapping access to the Pinia Store.
Home Page: https://pinia-orm.codedredd.de/
License: MIT License
(I don't use Nuxt)
https://codesandbox.io/s/wizardly-wood-cq6t5f?file=/src/App.vue
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 !
No response
No response
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.
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 = {}
?
Originally posted by nicooprat December 6, 2022
Hi there,
Thanks for your work.
We're about to finish our migration from Vuex to Pinia. Looks like relations are still not supported though: https://github.com/CodeDredd/pinia-orm#migration-from-vuex-orm
Any plan to support it? Are you following vuex-orm-next development timeline (so I should ask there)?
Thanks!
Darwin
v14.20.0
3.0.0-rc.11
0.5.4
[email protected]
vite
-
-
-
https://stackblitz.com/edit/github-hrsy4e?file=app.vue
Error "Cannot read properties of undefined (reading 'newRawInstance')" on models with one-to-many relations
This error threw only in SSR
No response
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.
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:
However:
(1) when querying the participants including their related formfields
(2) when querying the formfields including their related participants (thus the other way round)
Any ideas on this?
Is my definition wrong?
Thanks in advance!
No response
No response
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?
Recreated in the pinia-orm playground. Same issue when setting up locally.
Pinia-ORM playground demo of issue
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
No response
No response
https://pinia-orm.codedredd.de/guide/repository/deleting-data#deleting-data-1
In a code example you write const user = await useRepo(User).destroy(2)
...
... but the method is not returning a promise. I have logged and I have looked in the code.
The code example might be wrong and misleading.
No response
No response
Versions:
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.
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. :/
โ 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
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.
"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"
},
https://codesandbox.io/s/young-cloud-odi2kr?file=/src/App.vue
if calling new
from repository the hooks for creating
and created
not getting called.
Click on "console" and afterwards on the buttons. you will see, that "new" wouldnt trigger these hooks
No response
No response
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>;
}
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:
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 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()
}
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?
Darwin
v16.16.0
3.0.0
1.0.0
[email protected]
vite
app
, hooks
, build
, runtimeConfig
, css
, postcss
, modules
, http
, auth
@nuxt-alt/[email protected]
, @pinia/[email protected]
, @pinia-orm/[email protected]
, @vueuse/[email protected]
-
difficult to reproduce this since i'm migrating a large project
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
No response
No response
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?
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
Web browser: Microsoft Edge, Version 110.0.1587.63 (Official build) (64-bit)
Attempt to load any page on the documentation site:
https://pinia-orm.codedredd.de/
404 error is returned
No response
No response
Darwin
v16.15.0
0.0.0
-
[email protected]
webpack
-
-
-
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.
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.
If there is some caching strategy, we can remove the cache on server restart or on some sort of watchdog event.
No response
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:
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>)
.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
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
If relationship fields sent from a backend are null - or in the case of a many to many relationship - the contents of an array have changed, pinia-orm does not appear to keep track of these changes by updating the id fields and/or pivot tables.
Please see https://github.com/salcedo/pinia-orm-relationship-unlinking for reproduction of this issue.
For more details look at this discussion on discord
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.
Windows_NT
v18.13.0
3.0.0
1.0.0
[email protected]
vite
ssr
, modules
@pinia/[email protected]
, @pinia-orm/[email protected]
-
https://github.com/reramjiawan/pinia-orm-bug
Querying models with belongsToMany relation are extremely slow.
No response
No response
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.
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
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;
}
vue3/pinia/pinia-orm/typescript
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()
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
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?
No response
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
latest npm/vue3/pinia/pinia-orm
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;
}
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
My question would be why this function:
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?
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]);
}
}
` 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`
{
"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"
}
}
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 |
These updates are awaiting their schedule. Click on a checkbox to get an update now.
@nuxtjs/plausible
, yarn
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@antfu/eslint-config
, @iconify/json
, @lerna-lite/cli
, @lerna-lite/run
, @nuxt/eslint-config
, @nuxt/kit
, @nuxt/schema
, @pinia/nuxt
, @pinia/testing
, @types/node
, @typescript-eslint/parser
, @vitejs/plugin-vue
, @vitest/coverage-v8
, @vitest/ui
, @vue/compiler-sfc
, @vue/runtime-core
, @vue/runtime-dom
, @vue/shared
, @vueuse/core
, @vueuse/integrations
, @vueuse/shared
, actions/setup-node
, axios
, core-js
, eslint
, immutable
, lint-staged
, mkdist
, node
, pinia
, pinia-orm
, pnpm
, prettier
, semver
, sponsorkit
, theme-vitesse
, tsup
, typescript
, unplugin-icons
, unplugin-vue-components
, vite
, vite-plugin-pwa
, vitest
, vue
, vue-demi
, vue-tsc
, yarn
).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
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
There is no place to ask questions about Pinia ORM. If its supposed to replace Vuex-orm, there should be.
Allow questions instead of a redirect to the Pinia repository
Use reddit
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
}]
}
});
Nested relationships are normalized and saved.
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
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.
Thank you for creating this package!
I created a simple model but the .belongsToMany gives me the error Property 'belongsToMany' does not exist on type 'typeof ...
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"),
};
}
}
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
It says belongsToMany does not exist.
If you didn't implement belongsToMany it might be good to put this in the README.md
See here: nuxt/nuxt#19717
See here: nuxt/nuxt#19717
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"
}
No response
No response
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?
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>
save
).save
I would expect the values of the model to not be affect (turn to null) by the type definitions.
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.
Your great doc site https://pinia-orm.codedredd.de/ sadly returns a 404 error at the moment.
Go to https://pinia-orm.codedredd.de/ and see the 404.
The doc site returns a 404.
No response
No response
Pinia ORM 1.5.1 in the playground
(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.
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?
No response
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.
Vue 2 + pinia + pinia ORM
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ย }ย
It should set a default value as undefined
but it's null
No response
No response
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
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
โโโ @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]
useRepo(Post).with("comments").get();
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)
No response
No response
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'
),
],
},
}
A working Nuxt2 installation.
The error mentioned above.
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?
{
"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
}
}
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' }],
},
]);
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?
No response
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.