Giter Site home page Giter Site logo

vuex-orm-next's Introduction

vuex-orm-next Unit Test Build codecov

Status: Draft

This repo is for the next iteration of Vuex ORM. It’s in an active development state and we are hoping it is going to be the foundation of the version 1.0.0 release. Any and all feedback is welcome!

In addition, new documentation is ongoing and can be found at https://next.vuex-orm.org.

Join us on our Slack Channel for any questions and discussions.

Vite Integration

Make sure to disable useDefineForClassFields in tsconfig.json when using vite >= 2.5.0. See this issue for more details.

...
"useDefineForClassFields": false,
...

Contribution

Community contributions will be applicable as soon as this repo reaches alpha stage.

License

Vuex ORM is open-sourced software licensed under the MIT License.

vuex-orm-next's People

Contributors

abraxxa avatar cuebit avatar dependabot[bot] avatar gu3 avatar innovate-invent avatar kiaking avatar m3psipax avatar ryandialpad avatar zenthae 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuex-orm-next's Issues

Has Many By relation not working

Describe the bug

Hello, i'm not sure if i miss something, Has Many By isn't in the doc but there is closed issue about it : 6c8cce5

I have a "Tag" class and i am trying to retrieve many "Runs" items from it :

import { Model } from '@vuex-orm/core'
import Run from './Run'

export default class Tag extends Model {
    static entity = 'tag'
    static fields() {
        return {
            id: this.uid(),
            value: this.string(''),
            runs_ids: this.attr([]),
            runs: this.hasManyBy(Run, 'runs_ids'),
        }
    }
}

When i attach "runs" to a tag it works, for exemple i have 3 "runs" ids attached to "test1" tag, but the "runs" field from "Tag" class remains empty (it doesn't even exists) as you can see in Vue debug tool (vuex mode) :

image

The "runs" ids are good and this is the primary key, this is the runs repo :
image

Steps to reproduce the bug

  1. Define models [...]
  2. Create data [...]
  3. Retrieve data [...]
  4. See error

Expected behaviour

Retrieve "runs" from the "tags"

Versions

  • Vuex ORM: 1.0.0-draft.14
  • Vue: 2.6.11

Add MorphOne relationship

Let's add MorphOne relationship.

For example, a blog Post and a User may share a polymorphic relation to an Image model. Using a one-to-one polymorphic relation allows you to have a single list of unique images that are used for both blog posts and user accounts.

Below is the model definition for such models.

class User extends Model {
  static entity = 'users'

  @Num(0) id!: number
  @Str('') name!: string

  @MorphOne(() => Image, 'imageableId', 'imageableType' )
  image!: Image | null
}

class Post extends Model {
  static entity = 'posts'

  @Num(0) id!: number
  @Str('') title!: string

  @MorphOne(() => Image, 'imageableId', 'imageableType' )
  image!: Image | null
}

class Image extends Model {
  static entity = 'images'

  @Num(0) id!: number
  @Str('') url!: string
  @Num(0) imageableId!: number
  @Str(0) imageableType: string
}

Then, we fetch models like so:

userRepo.with('image').find(1)

/*
  {
    id: 1,
    name: 'John Doe',
    image: {
      id: 1,
      url: '/profile.jpg',
      imageable_id: 1,
      imageable_type: 'users'
    },
  }
*/

Cannot find module `'@/database/Database'`

Describe the bug

Both tsc and vue-tsc throw because Database is imported incorrectly by Interpreter. Causes Vite project builds to fail.

Steps to reproduce the bug

Run tsc --noEmit in a Vue 3 project root.

Expected behavior

No error.

Versions

  • Vuex ORM: 1.0.0-draft.14
  • Vue: 3.1.1

Lazy loading after draft 15

For some use-cases in our apps we need to use a lot of relations. For some of those cases we'd like the guarantee of having the relations loaded and made use of a way of lazy loading those relations.

import {Model} from "@vuex-orm/core";
import Post from "./Post";

export default class User extends Model {
    static entity = 'User';

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

    get lazyPosts() {
        if (this.posts === undefined) {
            this._database.store.$repo(User).with('posts').load([this]);
        }

        return this.posts;
    }

    get lazyComments() {
        return this.lazyPosts.reduce((carry, post) => carry.concat(post.lazyComments), []);
    }
}

We are aware that lazy loading brings a bit of overhead and should be avoided by lots of data, but we do have some usecases were we'd still like the guarantee of having the relation loaded or else loading.

How should we deal with these types of situations?
Will this be suported (in the future)?

Is this abandoned?

I've been searching for a data layer separation for vue and came across vue orm. it's a neat little library but looks like haven't received any updates in over 2 years.. is this project abandoned? do we have a perhaps better solution?

Understanding problem

Hi dear vuex-orm-next team,

to decide using this project or not I need to clarify one question:

I am currently writing my own ERP+CRM+Email+... system.
For the frontend I will be using the quasar framework.
The plan is to use vuex-orm-next + the axios plugin.
The user can travel around different components like email, fax, offer, order, ...
This will be different pages with tabbed components/pages, where the first tab is always the list of all items with dynamic scroll (content loaded from server as needed), and each detail item will be a new tab with a detail form.
Of course I want to keep the current states when user is travelling to other modules, so I will be using massively vue's keep-alive directive.

Now the question is, what will happen with vuex-orm-next ?
In worst case will it end up that the whole database is loaded into memory of the browser, or do I need to handle switch between different views and need to reload the data from the server ?

Sorry, for potentially stupid question, but just started with vue, vuex, ...

Many thanks for your answer,
Mike

VueX getter caching in combination with VueX-ORM

Additional context

I'm not totally sure wether I'm posting this in the right repo, but I thought it might be usefull for everyone here to know.

Describe the bug / Expected behaviour

It seems that when querying VueX-ORM models inside a VueX store getter, the getter can't cache the result properly.
I have a store getter that contains a query that can take up to a full second to return the requested data (yes, lots of data).
When I call this getter twice from inside a component, the render time needed will be 2 seconds instead of 1.
If I would refactor this getter to be a state property and be updated everytime the corresponding repo's would be updated, The render time will be reduced to an instant and the time to mutate the repo's will take 1 second longer.
I would expect in my first scenario that the render time wouldn't increase no matter how many times the getter would be called from within that component. (For as far as I understand, this behaviour would be the same as store getter caching where getters only refer to store state.)

Steps to reproduce the bug

// Template inside component
<template>
   <section v-for="post in posts">{{post.name}}</section>
   <section v-for="post in posts">{{post.name}}</section>
</template>

// Computed property inside component
posts() {
    return this.$store.getters.posts;
}

// Store
getters: {
    posts() {
        return store.$repo(Post).all();
    }
}

API Composition and TypeScript

Hi !
First of all : awesome project !
Do you have any tips to include vuex-orm-next with api composition and typescript ?

I saw an old issue :

`import { useRepo } from '@vuex-orm/core'
import User from '@/models/User'

export default {
setup() {
const useRepo = useRepo(User)
}
}`

Any news about this ?
Thank you !

Uncaught TypeError: Cannot read properties of undefined (reading 'data')

Describe the bug

Uncaught error at src/connection/Connection.ts:45 in the source code:

vuex-orm.esm-bundler.js:2298 Uncaught TypeError: Cannot read properties of undefined (reading 'data')
    at Connection.get (vuex-orm.esm-bundler.js:2298:62)
    at eval (eval at cashRows (cash.ts:1:1), <anonymous>:1:53)
    at cashRows (cash.ts:504:5)
    at wrappedGetter (vuex.esm.js:881:12)
    at Vue.<anonymous> (vuex.esm.js:140:12)
    at Watcher2.get (vue.runtime.esm.js:4473:25)
    at Watcher2.evaluate (vue.runtime.esm.js:4578:21)
    at Vue.computedGetter [as cash/cashRows] (vue.runtime.esm.js:4830:17)
    at Object.get [as cash/cashRows] (vuex.esm.js:671:39)
    at VueComponent.mappedGetter (vuex.esm.js:1026:26)

It's calling return this.database.store.state[connection][entity].data in src/connection/Connection.ts:45.

We currently have five models in VuexORM and at the point in time where this method was called, only four of them existed on state[connection] - I know that at least one of them had data stored in it at the time, and I'm almost sure the other three had too, since they are populated from network requests that load initial state. But the cashRow model is only used in frontend, and it wasn't populated with any data yet.

Steps to reproduce the bug

I cannot even reproduce it myself anymore. I suspected that the problem was caused by a Vue.$watch called from within a created hook (options API), but I'm not sure. It was not set to { immediate: true } either. It is watching a vuex getter which returns store.$repo(models.cashRow).all()

Expected behaviour

I expected this.$repo(model).all() to always be callable and return an empty array if no data is found

Versions

  • "@vuex-orm/core": "^1.0.0-draft.16"
  • "vue": "2.6.10"

Heterogenous data lists

Is your feature request related to a problem? Please describe...

The backend I interact with returns a heterogenous list of objects. This can't currently be processed by VuexORM. Each object has an attribute declaring its type.

{
  "type":"container",
  "elements": [
    { "id": 1, "type":"type1", "type1param":"", "common_param":"" },
    { "id": 2, "type":"type1", "type1param":"", "common_param":"" },
    { "id": 3, "type":"type2", "type2param":"", "common_param":"" },
  ]
}

or simply a fetch response can be

[
  { "id": 1, "type":"type1", "type1param":"", "common_param":"" },
  { "id": 2, "type":"type1", "type1param":"", "common_param":"" },
  { "id": 3, "type":"type2", "type2param":"", "common_param":"" },
]

Describe the solution you'd like

Provide a relation that keys on the object type attribute and handles it accordingly.
The relation should accept a mapping of type attribute values to ORM models.

Describe alternatives you've considered

I am currently transforming the data using a request hook to split the lists.

Model exposes the store which is a cyclic object value

Describe the bug

The _store property becomes a cyclic object value due to the $database property already existing in the store which in turn references the store. In layman, a Vuex store should not be exposed as an instance property.

This leads to undesired side-effects when using JSON.stringify and v-bind in components.

Steps to reproduce the bug

Component definition:

export default {
  computed: {
    ...mapRepos({ user: User }),
    users: (vm) => vm.user.all()
  }
}

JSON.stringify(...)

A circular structure error is thrown when stringifying anything that references a model instance.

// Throws circular structure error.
JSON.stringify(users)

// Not preferred methods, but do not throw.
JSON.stringify(users.map((user) => user.$toJson()))
JSON.stringify(users, (key, value) => key === '_store' ? undefined : value)

Moreover, Vue's native transform of template syntax variables uses JSON.stringify.

<!-- SFC template throws circular structure error. -->
<template>
  <pre>{{ users }}</pre>
</template>

v-bind

v-bind will resolve _store subsequently it becoming an attribute if no prop is absorbing it and pollutes the DOM.

<v-component v-for="user in users" :key="user.id" v-bind="user" />

Expected behaviour

  • JSON.stringify should have no problem stringifying and instance.
  • v-bind should not see "private" instance properties.

Model `$delete` method should be synchronous

Describe the bug

Model method $delete returns a promise despite all API methods now being synchronous.

Expected behavior

The method should be synchronous.

Versions

  • Vuex ORM: 1.0.0-draft.14

Event API Implementation

This topic is open to consider implementation of the Event API, how best to proceed in designing such implementation that will continue to endure through future releases while being supportive of authors of the Vuex ORM ecosystem.

Global Events

As it stands, the @latest release observes selection and mutation hooks. These hooks are triggered on a singleton (the Query class) and accumulated from the models by way of declarative static methods.

The behaviour for event handling will need to change considering Query is no longer a singleton and potentially out-of-scope for such a requirement. However, global hooks still require a singleton for global event listening/broadcasting.

One suggestion being that the database instance, given it is a singleton in instance form and easily accessible, could be a point of listening/emitting. For example:

store.$database.on('query:beforeSelect', handler)

The benefit of this pattern enables event scoping by prefix (in string representation). This is purely for emitting and subscribing to an event. Models can still declare static methods.

Naming Convention

The subject of normalizing or changing the naming convention for these hooks internally are also up for debate. By internally we mean the name of events emitted rather than the method names bound to a model since these model methods do not subscribe to events directly, rather they are declared as reference handlers.

Selection Hooks

The current selection hooks are: beforeSelect, afterWhere, afterOrderBy and afterLimit.

Selection hooks pass a collection of models tappable for mutation to which a query instance is currently processing.

Mutation Hooks

The current mutation hooks are: beforeCreate, afterCreate, beforeUpdate, afterUpdate, beforeDelete and afterDelete.

Mutation hooks pass the model in the current iteration queue for persistence. Should a models handler return false, the model is skipped and not persisted.

Design Limitations

The crux with event handling is that it is stateless therefore a broadcasted event shouldn't be required to read, let alone expect, a response from subscribers – which proves problematic if events such as beforeCreate or beforeSelect may be required to return. The overhead caused by evaluating a response on each model that's listening inclusive of any additional subscribers to the event is cause for concern. In addition, the @latest release already possesses quantitive performance degradation and @next, at the time of writing, has no performance tests in place to verify any improvement on that front. So it's debatable how taxing this may still be.

For that reason, it's worth considering how to proceed with an idiomatic and synchronous Event API. For example, we may well continue to support return values from event handlers, consequently taking the natural hit on performance. Or we decide to cut ties with this approach and leave it down to user-land logic to process data before asking Vuex ORM to persist it.

Ecosystem

The Event API in its current form also works in favour of plugin authors. Not only can the Events API be integrated on objects that extend it, emitting internal events can enable plugin authors to tap into points for plugin logic. This isn't something we necessarily need to give too much thought, since plugin authors will often circumvent default behaviours through monkey-patching, but can grow as required for non-public logic.

Adding to this, plugins can leverage and adapt the Event API for its own use, rather than “bring your own” functionality which further bears weight on an application using assistive plugins.

Discuss.

Creating a models collection

Hi!

Can your please add support array of objects for make function?

const users = store.$repo(User).make([{
  name: 'John Doe',
  age: 30
},{
  name: 'John Walker',
  age: 36
}]);

Loading all relationships on a Model

I'd like to be able to load all relations when fetching the Model. Old vuex-orm could do it like this: model.query().withAllRecursive().

From what I can see in the docs, this is no longer or not yet possible.

Are there plans to implement this in this version or is there another way to do this?

Wrong type inside template

Describe the bug

missing types when using a model as a type for relationships

Steps to reproduce the bug

  1. Define models Post & User following the getting started page
  2. Create data
  3. try using auto completion

Expected behavior

we should get the attributes of User when accessing post.author?. but it only show the Model properties

// Post model
export class Post extends Model {
  static entity = 'posts';

  @Attr(null)
  id!: number | null;

  @Attr(null)
  userId!: number | null;

  @Attr('')
  title!: string;

  @Attr('')
  body!: string;

  // Wrongly typed attr
  @BelongsTo(() => User, 'userId')
  author!: User | null;
}

export default Post;

image
should looks like that (different attrs name)
image

Versions

  • "@vuex-orm/core": "^1.0.0-draft.9"
  • "vue": "^3.0.5",
  • "vuex": "^4.0.0"

model.$entity is not a function

We are using vuex4 and vue3 and just moved from @vuex-orm/core 0.36.4 to the 1.0.0-draft.16 version and getting this error when trying to register model with Database.register method.

The old @vuex-orm/core 0.36.4 version was working with vue3 and vuex4, though we are experiencing what appears to be a minor bug so keen to try the new version. Thanks.

vuex-orm.esm-browser.js?d318:2174 Uncaught TypeError: model.$entity is not a function
    at Database.register (vuex-orm.esm-browser.js?d318:2174:1)
    at eval (index.js?c97f:57:1)
    at Module../resources/js/database/index.js (app.js:50:1)
    at __webpack_require__ (manifest.js:31:42)
    at eval (store.js:4:67)
    at Module../resources/js/state/store.js (app.js:633:1)
    at __webpack_require__ (manifest.js:31:42)
    at eval (auth.js:8:70)
    at Module../resources/js/includes/auth.js (app.js:61:1)
    at __webpack_require__ (manifest.js:31:42)

database/index.js

import VuexORM from '@vuex-orm/core'
import { Database } from '@vuex-orm/core'
import VuexORMLocalForage from 'vuex-orm-localforage'

import AuditObjectHazard from '@/models/audit_object_hazard'
import auditObjectHazard from '@/state/audit_object_hazard'

import AuditObjectSign from '@/models/audit_object_sign'
import auditObjectSign from '@/state/audit_object_sign'

// Create a new database instance.
const database = new Database()

// Register Models to the database.
database.register(AuditObjectHazard, auditObjectHazard)
database.register(AuditObjectSign, auditObjectSign)

VuexORM.use(VuexORMLocalForage, {
  database,
  localforage: {
    name: 'vuex',
    version: 1.0,
  },
  actions: {
    $get: '$getFromLocal',
    $fetch: '$fetchFromLocal',
    $create: '$createLocally',
    $update: '$updateLocally',
    $delete: '$deleteFromLocal'
  }
})

// Create Vuex database plugin
const ormStore = VuexORM.install(database)

export default ormStore

store

import { createStore } from 'vuex'
import createPersistedState from "vuex-persistedstate";
import ormStore from '@/database'

import auth from '@/state/auth'
import system from '@/state/system'

const vuexPersisted = new createPersistedState({
  key:'slsa-bm-v1',
  storage: window.localStorage,
  reducer: state => ({
    auth: state.auth,
    system: state.system,
    loading: state.loading,
    location: state.location
  })
})

export default createStore ({
  modules: {
    auth,
    system
  },
  plugins: [ormStore, vuexPersisted],
})

models

// Audit Model
import { Model } from '@vuex-orm/core'
export default class AuditObjectHazard extends Model {
  static entity = 'auditObjectHazard'
  static primaryKey = ['audit_object_id', 'hazard_object_id']

  static fields () {
    return {
      audit_object_id: this.attr(null),
      hazard_object_id: this.attr(null),
    }
  }
}

using the store the vue 3 way

const app = createApp({
  ...
})
app.use(store)

Inserting Data With Default Values

https://next.vuex-orm.org/guide/repository/inserting-data.html#inserting-data-with-default-values

The new method will create a record with all fields filled with default values defined in the model.

const user = store.$repo(User).new()

// { id: '$uid1', name: '' }

that's what's written on the doc, but the new() method doesn't exist in practice ? so how i'm supposed to add data ?

this.$store.$repo(User).insert(new User()); ? that's what i'm using at the moment, but i'm not sure if it's the right way to do it

Make model $ getters functions

When $ prefixed properties are defined as getters, it prevents from passing model instance to child component via v-bind directive.

Let's change those to functions instead.

Rethinking a way to handle API response

OK I'm getting excited about the API handling. What do you guys think about this idea.

So, currently, we return models from the persistent methods such as insert. But it's not reactive, since it's a plain return value. Therefore, in almost all cases, users should refetch the models by querying the data after persisting records.

For example, let's say we have this api that it returns a user with posts.

const user = api('/api/users/1')
/*
  {
    id: 1,
    name: 'John Doe',
    posts: [
      { id: 1, title: 'Title 1' },
      { id: 2, title: 'Title 2' }
    ]
  }
*/

Now to use this API with Vuex ORM properly, you should define your component like this.

export default {
  setup() {
    const store = useStore()
    const userRepo = store.$repo(User)

    const user = computed(() => {
      return userRepo.with('posts').where('id', 1).first()
    })

    api('/api/users/1').then((user) => {
      userRepo.insert(user)
    })

    return {
      user
    }
  }
}

At first step, it would be nice if we can reuse the api response to query the Vuex Store. In the above case, we're assuming that we know what id to query (it's 1). But we might not know that. And also we lose any order of the items (in this case posts order could be different from the api response).

So, how about we let insert method return ids of created records...? This is easy since Normalizr package already handles this.

const schema = userRepo.insert(user)
/*
  {
    id: 1,
    posts: [1, 2]
  }
*/

Then, we add a new method to query the store based on this schema. Something like revive maybe.

const user = userRepo.revive(schema)
/*
  {
    id: 1,
    name: 'John Doe',
    posts: [
      { id: 1, title: 'Title 1' },
      { id: 2, title: 'Title 2' }
    ]
  }
*/

The revive method should be pretty fast since we can directly lookup the index ID to retrieve all data.

With this new method, we could refactor our setup hook like this.

export default {
  setup() {
    const store = useStore()
    const userRepo = store.$repo(User)

    const schema = ref()

    const user = computed(() => {
      // Fetch user based on schema. If api is not yet called,
      // schema is null, once it get set, we get the user.
      return schema.value && userRepo.revive(schema.value)
    })

    api('/api/users/1').then((user) => {
      // Save created schema.
      schema.value = userRepo.insert(user)
    })

    return {
      user
    }
  }
}

Now, we may wrap these to composable and make it clean.

export default {
  setup() {
    const { pending, user } = useUser(() => {
      return api('/api/users/1')
    })

    return {
      user
    }
  }
}

The useUser composable will first call the callback API, insert the response to the store, then query the store based on the result schema, and set it to the user variable, which is computed.

I think we can easily integrate this with SWRV if we want hande API caches. All we need to do is let SWRV call the api, then insert/update the result data using Vuex ORM.

vue3 / vuex4

Hi there,

nice to see how the project developed.

Just one question:
is it already made for vue3 / vuex4 ?
Planning to use it with quasar2.

Many thanks.
Mike

Add explicit type in attributes instances to allow introspection

Sometimes, we need introspection on models and extract the type of each field.

Unfortunately, we can't trust field.constructor.name to get VuexORM field class because uglifying change the class name in many transpilers. We can use instanceof but in some cases, the test is wrong (after updating prototype by example).

It would be really useful if the types instances returns explicitly their type like this :

export class Boolean extends Type {
    constructor(model: Model, value: boolean | null) {
        super(model, value)
        this.type = 'Boolean';
    }

    // ...
}

So instead of Model.fields()[myfield].constructor.name (which don't works with uglify), we could write Model.fields()[myfield].type to know the type in every context.

Alpha release

Sorry for this post, it's not a real issue or feature request, the question is more about the general development of vuex-orm. Will there be an alpha-release or is the development kind of shut down and there won't be releases anymore? We managed to upgrade our project to vue3 using vuex-orm-next, but there where quite some workarounds necessary to be able to use it. So the question is now, does it have a future or will it die sooner or later and it makes sense to get rid of it and rewrite the code?

Throw error when trying to access unloaded relationship

Currently, when relationships are not loaded, it becomes undefined. How about we throw an error when accessing unloaded relationships?

const user = userRepo.find(1)

user.posts // Error('relationship is not loaded')

This might make it easier to catch errors where people forget to load them, and try to access it 🤔

Updating nested data

Is your feature request related to a problem? Please describe...

I'm wondering if there is currently a way to partially update a nested value with an entry. It seems like I have to recreate the entire object from the top-level down to update i.e. a simple string.

Describe the solution you'd like

Ideally this.$store.$repo(Module).update({}) would check if a given key is already nested somewhere within the entry.

Describe alternatives you've considered

Maybe working with dot notation could be possible? E.g. this.$store.$repo(Module).update({ id: 1, 'parent.child.name' : value })

It seems like this was already possible via using a function in earlier versions: https://vuex-orm.org/guide/data/inserting-and-updating.html#updates

Stricter field type, and nullable by default

This is still just an idea, so looking for feedback.

What do you think about making model attributes more strict? Currently, we have several fields with primitive types, such as string, number. etc. At the moment, these fields will cast values rather than restrict them. So passing true to string field will make it 'true'.

The idea is to make them fail instead of casting.

class User extends Model {
  static entity = 'users'

  @Str() name!: string
}

new User({ name: true }) // <- Error('name is not string')

In addition to this, how about if we make all the fields nullable by default. Because in the frontend, usually many fields are going to be nullable.

So instead of having nullable option, we'll add NonNullable decorator (if this is possible).

class User extends Model {
  static entity = 'users'

  // This field is number, and not nullable.
  @Num()
  @NonNullable()
  id!: number

  // This field is string, or null.
  @Str()
  name!: string | null
}

The default value should behave the same,

class User extends Model {
  static entity = 'users'

  // This field is nullable, but if we pass `null`, it becomes `John Doe`.
  // so technically it wouldn't be `null`.
  @Str('John Doe')
  name!: string
}

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.