mythix-orm
Advanced tools
Comparing version 1.4.7 to 1.5.0
@@ -5,3 +5,3 @@ # Mythix ORM associations | ||
I many other ORMs you need to define how two models are related... and what fields are related on those models, and if the relation ship is polymorphic, and if it should load related models while accessing the relation, and if there is a default scope that should be applied, and... | ||
In many other ORMs you need to define how two models are related... and what fields are related on those models, and if the relationship is polymorphic, and if it should load related models while accessing the relation, and if there is a default scope that should be applied, and... | ||
@@ -537,5 +537,5 @@ Lame. | ||
2. "But, what if I am using two, three, or more through-tables?" you ask. Well, you are in luck! Nothing described above changes. You simply define a more complex primary query using the query provider, and Mythix ORM will be smart enough to recursively walk the relationships in the query, join as many tables as it needs to to get the job done, and do the right thing. | ||
3. Mythix forces you to manually define all table/model fields. Yes, this is extra overhead, but it comes with the benefit of not needing to painstakingly manually define all *relationships*. This design pattern was also decided upon so that there aren't any table columns that are ambiguously "hidden" from developers. By forcing the user to always define all columns/fields manually, it simplifies seeing what fields exist on the table, removes down-stream dependencies, and prevents the user from needing to go look-up documentation to understand how things are working and why. Feel free to write your own helper methods that will automatically inject fields into your schema for you! | ||
3. Mythix forces you to manually define all table/model fields. Yes, this is extra overhead, but it comes with the benefit of not needing to painstakingly lookup fields that have been "magically" defined somewhere deep in the library. By forcing the user to always define all columns/fields manually, it simplifies seeing what fields exist on the table, removes down-stream dependencies, and prevents the user from needing to go look-up documentation to understand how things are working and why. Feel free to write your own helper methods that will automatically inject fields into your schema for you! | ||
4. When pulling related models, Mythix ORM will always put them in a plural {model name} key... i.e. if you noticed above, `UserRole` models that were fetched were placed into `.UserRoles`. This is true for all relationship operations. If you opt-in to loading other relationships during an operation, the related models will always be placed on the loaded model instances, under their plural name (always as an array of models). | ||
Happy coding! |
@@ -16,37 +16,40 @@ # Welcome to the Mythix ORM wiki | ||
## What Mythix ORM is (and is not) | ||
## What Mythix ORM **is** | ||
Mythix ORM was designed and created to replace all the terrible other options that currently exist for Node. I mean, have you ever looked at the source code for some of the other popular ORM libraries out there? It is the stuff of nightmares! | ||
Mythix ORM has been designed to fix the "situation" found today with other ORMs for Node. Namely, it focuses on being bloat-free, having a clean usable interface, a simple to use yet advanced query interface, no hidden auto-magic, clean code, and finally, fantastic documentation. These are all points that are shockingly lacking, or extremely poorly handled in other ORMs currently available for Node, and I wanted to do something about it. | ||
I was tired of daily having to deal with malarky spewed by the other ORM libraries and their very poorly designed interfaces, their bloat, and their difficulty to setup and use (to say it mildly). | ||
Mythix ORM is **not** a batteries-included, do everything-under-the-sun type of library. Instead, the authors have deliberately chosen to make it as small, fast, and focused, while remaining extremely extensible. It is the hope of the authors that the community will build new features onto Mythix ORM via community supported third-party modules. The reasons for this are 1) Mythix ORM doesn't want to be bloat, and instead would like developers to be able to pick and choose which features they want to use, and 2) We feel it is better if the community decides the path forward. We will support and cheer the community on, and possibly even backport community modules into the core Mythix ORM feature set if there is widely adopted community support and demand for them. | ||
Though I firmly believe ORMs are--in nature--a poor and terrible fix for the plethora if crap us developers must go through daily trying to work with outdated and non-standard databases, they do still have their place in our world (until the database "situation" is resolved). So, while ORMs are still needed, why not at least use the best one available? | ||
Mythix ORM has been designed to be modified and added onto. There are no private or global variables used in Mythix ORM by design. It is the intent of the authors that you will modify the library for your specific use case, add onto it as you see fit, or completely change how it works to meet your needs. We don't play into the fallacy that we should lock everything down just so you don't shoot yourself in the foot. Instead, we open everything up to be modified, and if you shoot yourself in the foot, well, that is on you. We would rather enable you, as the developer, to do what you need to do to get your job done, instead of restricting what you can do for fear that you might cause yourself trouble. In short, hack away! Mythix ORM should serve you and your needs, not the other way around. | ||
Meet Mythix ORM. It was designed from the ground-up to replace *all* other existing ORMs, forever. As part of the design, a few key decisions were made to make Mythix ORM a far better solution than the other "solutions" out there. | ||
Mythix ORM intends to conquer the world through a modular design. Though we deliberately avoid bloat, and therefor don't have every possible feature baked into the core libraries, we do hope to provide--and hope the community will provide--a large selection of useful modules and plugins for Mythix technologies. It is our hope that in the coming years Mythix ORM will be able to interact with every database on the planet, and have many other useful libraries for developers to use. Feel free to contribute! We would love to see your custom database driver, how you have added onto and improved the query interface, or other improvements you come up with. | ||
Let's go over those key design decisions real quick so we are all on the same page: | ||
Mythix ORM deliberately tries to abstract everything it can away from the database. Because of this, you will often find cases where you might need to do things differently then you are used to, or you might find some of our design decisions a little strange. ORMs are *supposed* to be an abstraction layer, so it makes me shudder when I see other ORMs recommending database specific code, or providing database specific interfaces. Obviously there are times where this can not be avoided, and Mythix ORM does its best to handle these cases in an abstract way. However, there may be times where you just need to make a direct query to do something with your database, use a custom literal, or modify how Mythix ORM works by overloading its internal methods. One area that you will immediately notice this abstraction is the field types. There is a shockingly small number of field types available in Mythix ORM, and this is deliberate. Mythix ORM will *never* supply database specific field types... if you need those, you can use literals, or you can define your own field types to suit your needs. The situation also isn't as bad as you might initially think. Take the `INTEGER` type for example. It is designed such that it can receive as an optional parameter the "number of bytes" needed to store a certain integer type--and then it is up to the specific connection you are using to decide how to implement said type. For example, Mythix ORM does not supply the MySQL specific types like `TINYINT`, `SMALLINT`, or `MEDIUMINT`. Instead, you always simply use `INTEGER`, and specify the number of bytes you need, and the MySQL connection will take care of the rest for you. Field types are just one example. Mythix ORM will abstract away everything it can by deliberate design. | ||
1. Mythix ORM will never be bloated. It has a specific purpose, and it will stick to that purpose. It is an abstraction layer between different database types. It doesn't intend or pretend to be anything else. Mythix ORM is *bare bones*, just what you need, and nothing more. It is the intent and hope of the authors that Mythix ORM will grow a thriving community, and it was a deliberate design decision that the community would build extra libraries to add features to Mythix ORM. The motto over here in Mythix land is "take what you need, and nothing more". | ||
2. Mythix ORM is very extensible. Nearly every part of Mythix ORM can be overloaded, hijacked, or replaced entirely. Again, the intent is that the community will provide many cool features through extra libraries that *add* to Mythix ORM's feature set. It was also the intent of the authors who designed Mythix ORM to have it so developers could work with it *the way they like to*, without any of the mandates, and the "world **should** work this way" shenanigans. Mythix ORM is very powerful, and absolutely *will* allow you to shoot yourself in the foot--if you, as the developer, decide that is what you want to do. | ||
3. The primary author of this library--Wyatt Greenway--doesn't like the "black box" mentality. Encapsulation is absolutely a must for clean and stable code, but "black box"? Never. For this reason Mythix ORM was designed with no private variables, and nearly every method exists on a class, with the deliberate intent that methods could (and should) be overloaded to provide extra functionality. Please *do* overload methods, and change the behavior of Mythix ORM to fit your team needs. But *please* be a good citizen, and read and understand what you are doing and why before you do it. Mythix ORM will naturally change its interfaces over time (with appropriate versioning applied to each release), and it is up to the downstream developers to update and manage their custom code. | ||
4. Mythix ORM deliberately tries to abstract everything it can away from the database. Because of this, you will often find cases where you might need to do things differently then you are used to, or you might find some of our design decisions a little strange. ORMs are *supposed* to be an abstraction layer, so when I see other ORMs suggesting database specific code in their documentation it makes me shudder. Obviously there are times where this can not be avoided, and Mythix ORM does its best to handle these cases in an abstract way. However, there may be times where you just need to make a direct query to do something with your database, or use a custom literal, and that is okay. One area that you will immediately notice this abstraction is the field types. There is a shockingly small number of field types available in Mythix ORM, and this is deliberate. Mythix ORM will *never* supply database specific field types... if you need those, you can use literals, or you can define your own field types to suit your needs. The situation also isn't as bad as you might initially think. Take the `INTEGER` type for example. It is designed such that it can receive as an optional parameter the "number of bytes" needed to store a certain integer type--and then it is up to the specific connection you are using to decide how to implement said type. For example, Mythix ORM does not supply the MySQL specific types like `TINYINT`, `SMALLINT`, or `MEDIUMINT`. Instead, you always simply use `INTEGER`, and specify the number of bytes you need, and the MySQL connection will take care of the rest for you. Field types are just one example. Mythix ORM will abstract away everything it can by deliberate design. | ||
5. Mythix ORM and its API were deliberately designed to be as simple as possible, with all the complexity required tucked neatly away in the modular connection drivers. Deliberate intent and lots of thinking went into making the interface simple, yet flexible and powerful. For these reasons Mythix ORM is broken into many pieces, so the developer can pick and choose only what they want. Mythix ORM was also deliberately designed so that it could be run inside a browser. "Why in the heck would I ever do that?" I hear you asking. Well, Mythix ORM has more to offer than just being a layer between databases. Its model system, and especially its query system, are slick, and useful outside the context of server-only. I hope to one day see "browser based" connections that allow developers to use the same powerful query interface built into Mythix ORM inside the browser. I mean, how cool would it be to use the powerful built in query-engine inside the browser? Maybe to generate GraphQL? Or a custom query interface over HTTP? Let's think big and outside the box. | ||
6. SQL/NoSQL, who cares? From the ground up Mythix ORM was designed to support SQL and NoSQL (or even completely custom) databases. Connection drivers are painless to create, and the horizon is the limit. Currently Mythix ORM officially only has drivers for `PostgreSQL` and `SQLite`, but in the future it plans (and intends) to support every database on the planet, including file storage systems, and in-memory databases. If you don't see the database driver you are looking for, be patient, or better yet, help out! Before Mythix ORM is considered "done" it will have drivers for `MySQL`, `Microsoft SQL`, `Mongo`, `Snowflake`, `SOLR`, `ElasticSearch`, and many more. | ||
## What Mythix ORM **is not** | ||
Now let's take a little moment to discuss what Mythix ORM **is not**: | ||
Mythix ORM **is not** bloated, and it never intends to be. We want to keep our library focused on a single task, and we want it to do that task well. We plan to rely on the community and support from third-party modules to add to the feature set of the library. All optional features (such as database drivers) will remain modules, enabling the developer to pick and choose only what they need. | ||
1. Mythix ORM **is not** bloated, and it never intends to be. We will continue with the modular architecture, giving developers the ability to choose what they want to include (and what they don't want to include). This also means that you, as the developer, need to pay a little more attention. You can't just install Mythix ORM and away you go. You also need to select which database driver you need, and install it manually beside Mythix ORM. | ||
2. Mythix ORM **is not** "magical". In fact, we despise "magic" and won't have any of it. Everything must be clearly defined, and must visibly exist somewhere. Mythix ORM will not automatically create fields for you (i.e. `created_at` and `updated_at`), not even for relationships, polymorphic or not. The tedium you may come across was also considered, and accounted for. For example, if you *want* everyone of your models to have a `created_at`, and `updated_at` field, then simply create a base model that all of your other models inherit from, and on the base model itself you can define these "common" fields. The intent is to give the developer full control, while keeping all "magic" off the table. | ||
3. Mythix ORM **is not** opinionated. It is actually the opposite. It is the intent of the authors that developers will use and modify this library *exactly how they want to*. We don't make glaring statements like "We won't include a `toSQL` method because no one *should* ever use such a thing!", or silly statements like "You *should* do things our way... because we obviously know best". Ha! Whatever! No, we don't know what is best, and we openly admit it. You, **the developer**, know what is best, and we support you. Do want you want to do, and do it well. Make your mommy proud! Just remember that when you shoot yourself in the foot, it is *your foot*, not ours. | ||
4. Mythix ORM **is not** a swiss-army knife, batteries included, does everything under the sun type of library. It can do everything you need it to do however, and it does so in a modular, community supported way. If you want extra features, build them, or rely on what the community builds. Mythix ORM will deliberately always remain small, slim, sleek, and do exactly what it does the best it can, and nothing more. | ||
5. We--the authoring team of Mythix ORM--do **not** always know what is best. We know this, and are humble enough to admit it. This is one of the prime reasons behind deciding to lean heavily on the community for support and extra features. When the community builds something that thousands of people are using regularly, then--and only then--will we consider adding it as a core feature to Mythix ORM. In short, we want the community to drive the bus. We will take a back seat and see where it goes, cheering and supporting the entire trip. | ||
Mythix ORM **is not** magical. It won't ever have built-in support for standard fields, such as `created_at`, or `updated_at`, it won't add fields to your tables behind the scenes, it won't mangle names to try and fit someone else's convention, and it won't hide interfaces or features via some stupid and pointless "black box" principle. What You See Is What You Get is a core design principle of ours. Without the magic we have accounted for what developers need. For example, if you need a `created_at` and `updated_at` field on every model of yours, simply create a base model with these fields, and then have all your other models inherit from this base model. | ||
Mythix ORM **is not** opinionated--unless you consider the desire for clean code, simple interfaces, and fantastic documentation opinionated. We do not inform the developer for example that we have no `toSQL` method, and won't be adding one, "because developers should never use such a thing". Instead, we side with Journey, and openly state "anyway you want it is the way you need it". As a community we are here to support developers, not tell them how to live their lives. | ||
## Mythix certifications | ||
Mythix, as a community of libraries, has a certification program. We will certify third party libraries, and we recommend that you select certified libraries first. Why are we doing this? Part of the mission Mythix has is to reengage engineers to actually be engineers, instead of StackOverflow monkeys. We can not even begin to tell you how many times we have wept over the stank we have seen in open source libraries. We would prefer that Mythix, as a community, not be involved in the stank of the rest of the world. | ||
Mythix, as a community of libraries, has a certification program. We will certify third party libraries, and we recommend that you select certified libraries first. We will also maintain a blacklist of libraries that we feel aren't fitting to be used, or that damage our name. We have seen far too many examples of smelly, hacked together, thoughtless code floating around in the open source community, and would prefer our community doesn't devolve to such "standards". Indeed, Mythix ORM was born because of this problem, and we would like to push the engineering community in a positive direction, and not continue supporting the devolving of good engineering practices. We take pride in our name and what we do, and would like to be in a spot where people are confident and excited when they see the "Mythix" brand... not horrified and disappointed. | ||
For this reason we will maintain a list of "certified" libraries, whose code bases have been groomed for cleanliness and correctness. We will also maintain a "black list" of libraries that use Mythix technologies, but that have severe stank. We welcome all developers, and hope to build a thriving community around Mythix technologies... but be warned, if you are a poor engineer and poop out poor code, then your project might end up on a blacklist... | ||
### How can I get my Mythix library certified? | ||
The above statements are intended to inspire all developers to become better versions of themselves. Our world is a train wreck of smelly broken code (that is often popular, unfortunately). Mythix hopes to take a hand in changing the landscape, by lifting developers up and supporting good engineers, helping them standout as pillars of hope against the background noise. | ||
You can get your Mythix library certified by opening a pull request against this wiki, adding your library to the list of certifications. This will notify our team that you wish to have your library certified. Our team will then review your entire library, your design decisions, and the quality of your code and your documentation. We may request changes to meet our standards. When your library meets our standards, we will accept your pull request, and your library will then be certified. By using Mythix libraries you accept and understand that Mythix ORM reserves the right to certify or blacklist any library at any time, for any reason. | ||
We won't be rude, unfair, or bigoted. We will be precise, keen-eyed, care about what we build, and drive engineers to be better engineers. We like the word "accountable", and would like to hold ourselves and our community of engineers to a higher standard. Let's build great things together, not smelly things that everyone hates. Our certification and blacklists will simply serve as a means to try and prod engineers to do a better job, and to aspire to a higher standard. | ||
Our standards focus on 1) The quality of your code in general, 2) How many dependencies you use, the quality of those dependencies, and why you have chosen to use them, 3) The quality, correctness, and completeness of your documentation, and 4) The design decisions you made, why you made them, and how clean and simple your interface is, and 5) How well your code is covered by tests. | ||
We expect prompt communication when we ask clarifying questions or request changes. If we don't receive prompt responses from you, we will simply close your PR, and you will need to restart the process. | ||
### How can I get my Mythix library off the blacklist? | ||
The Mythix team will regularly groom [NPM](https://npmjs.com/) for Mythix libraries published to the community. If any are found that don't meet our standards, we will immediately add that library to our blacklist and notify the author. If you would like your library removed from our blacklist, then you will need to contact our team, and notify them that you have resolved the issues, and that you are ready to have your library certified. If for whatever reason you feel we are being unfair, then please open an issue on github under the `mythix-orm` repository describing your concerns. At this point, we, along with the community, will review your concerns, and decide how to proceed. | ||
### Certification list | ||
Our list of certified and blacklisted libraries can be found on our [Certifications](./Certifications) page. |
@@ -102,2 +102,6 @@ 'use strict'; | ||
getDefaultOrder(rootModel, options) { | ||
return rootModel.getDefaultOrder.call(rootModel, options); | ||
} | ||
_getFromModelCache(Model, key, defaultValue) { | ||
@@ -231,2 +235,5 @@ let cache = this._modelCache.get(Model); | ||
_escape(value) { | ||
if (Nife.instanceOf(value, 'string')) | ||
return `'${value.replace(/'/g, '\\\'')}'`; | ||
return SqlString.escape(value); | ||
@@ -387,3 +394,8 @@ } | ||
// eslint-disable-next-line no-unused-vars | ||
_floatTypeToString(type) { | ||
_numericTypeToString(type) { | ||
return `NUMERIC(${type.precision}, ${type.scale})`; | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
_realTypeToString(type) { | ||
return 'FLOAT'; | ||
@@ -445,4 +457,6 @@ } | ||
return this._datetimeTypeToString(type, options); | ||
else if (Types.FloatType.isSameType(type)) | ||
return this._floatTypeToString(type, options); | ||
else if (Types.NumericType.isSameType(type)) | ||
return this._numericTypeToString(type, options); | ||
else if (Types.RealType.isSameType(type)) | ||
return this._realTypeToString(type, options); | ||
else if (Types.IntegerType.isSameType(type)) | ||
@@ -883,4 +897,79 @@ return this._integerTypeToString(type, options); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async insert(Model, models, _options) { | ||
throw new Error(`${this.constructor.name}::insert: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async upsert(Model, models, _options) { | ||
throw new Error(`${this.constructor.name}::upsert: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async update(Model, models, _options) { | ||
throw new Error(`${this.constructor.name}::update: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async updateAll(_queryEngine, model, _options) { | ||
throw new Error(`${this.constructor.name}::updateAll: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async destroyModels(Model, _models, _options) { | ||
throw new Error(`${this.constructor.name}::destroyModels: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async destroy(_queryEngineOrModel, modelsOrOptions, _options) { | ||
throw new Error(`${this.constructor.name}::destroy: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars, require-yield | ||
async *select(_queryEngine, _options) { | ||
throw new Error(`${this.constructor.name}::select: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async aggregate(_queryEngine, _literal, options) { | ||
throw new Error(`${this.constructor.name}::aggregate: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async average(_queryEngine, _field, options) { | ||
throw new Error(`${this.constructor.name}::average: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async count(_queryEngine, _field, options) { | ||
throw new Error(`${this.constructor.name}::count: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async min(_queryEngine, _field, options) { | ||
throw new Error(`${this.constructor.name}::min: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async max(_queryEngine, _field, options) { | ||
throw new Error(`${this.constructor.name}::max: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async sum(_queryEngine, _field, options) { | ||
throw new Error(`${this.constructor.name}::sum: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async pluck(_queryEngine, _fields, _options) { | ||
throw new Error(`${this.constructor.name}::pluck: This operation is not supported for this connection type.`); | ||
} | ||
// eslint-disable-next-line no-unused-vars | ||
async exists(queryEngine, options) { | ||
throw new Error(`${this.constructor.name}::exists: This operation is not supported for this connection type.`); | ||
} | ||
} | ||
module.exports = ConnectionBase; |
@@ -729,2 +729,7 @@ 'use strict'; | ||
if (Nife.isEmpty(order)) { | ||
if (options && options.selectStatement === true) | ||
order = this.connection.getDefaultOrder(rootModel, options); | ||
} | ||
if (Nife.isNotEmpty(order) && !LiteralBase.isLiteral(order)) { | ||
@@ -762,5 +767,2 @@ let allModels = this.getAllModelsUsedInQuery(queryEngine, options); | ||
}); | ||
} else if (Nife.isEmpty(order)) { | ||
if (options && options.selectStatement === true) | ||
order = this.connection.getDefaultOrder(rootModel, options); | ||
} | ||
@@ -767,0 +769,0 @@ |
@@ -29,7 +29,7 @@ 'use strict'; | ||
castToType({ value }) { | ||
castToType({ value, connection }) { | ||
if (value == null) | ||
return value; | ||
let dateTime = this.deserialize(value); | ||
let dateTime = this.deserialize(value, connection); | ||
if (!dateTime.isValid()) | ||
@@ -64,3 +64,4 @@ throw new TypeError(`DateType::castToType: Value provided ("${value}") can not be cast into a date.`); | ||
deserialize(_value) { | ||
// eslint-disable-next-line no-unused-vars | ||
deserialize(_value, connection) { | ||
let value = _value; | ||
@@ -67,0 +68,0 @@ if (value == null) |
@@ -30,7 +30,7 @@ 'use strict'; | ||
castToType({ value }) { | ||
castToType({ value, connection }) { | ||
if (value == null) | ||
return value; | ||
let dateTime = this.deserialize(value); | ||
let dateTime = this.deserialize(value, connection); | ||
if (!dateTime.isValid()) | ||
@@ -69,3 +69,4 @@ throw new TypeError(`DateTimeType::castToType: Value provided ("${value}") can not be cast into a date.`); | ||
deserialize(_value) { | ||
// eslint-disable-next-line no-unused-vars | ||
deserialize(_value, connection) { | ||
let value = _value; | ||
@@ -72,0 +73,0 @@ if (value == null) |
@@ -9,5 +9,7 @@ 'use strict'; | ||
const { DATETIME, DateTimeType } = require('./datetime-type'); | ||
const { FLOAT, FloatType } = require('./float-type'); | ||
const { FOREIGN_KEY, ForeignKeyType } = require('./foreign-key-type'); | ||
const { INTEGER, IntegerType } = require('./integer-type'); | ||
const { NUMERIC, NumericType } = require('./numeric-type'); | ||
const { REAL, RealType } = require('./real-type'); | ||
const { SERIALIZED, SerializedType } = require('./serialized-type'); | ||
const { STRING, StringType } = require('./string-type'); | ||
@@ -28,5 +30,7 @@ const { TEXT, TextType } = require('./text-type'); | ||
DateType, | ||
FloatType, | ||
NumericType, | ||
RealType, | ||
ForeignKeyType, | ||
IntegerType, | ||
SerializedType, | ||
StringType, | ||
@@ -45,5 +49,7 @@ TextType, | ||
DATETIME, | ||
FLOAT, | ||
NUMERIC, | ||
REAL, | ||
FOREIGN_KEY, | ||
INTEGER, | ||
SERIALIZED, | ||
STRING, | ||
@@ -50,0 +56,0 @@ TEXT, |
@@ -15,5 +15,7 @@ 'use strict'; | ||
DateType, | ||
FloatType, | ||
NumericType, | ||
RealType, | ||
ForeignKeyType, | ||
IntegerType, | ||
SerializedType, | ||
StringType, | ||
@@ -32,5 +34,7 @@ TextType, | ||
DATETIME, | ||
FLOAT, | ||
NUMERIC, | ||
REAL, | ||
FOREIGN_KEY, | ||
INTEGER, | ||
SERIALIZED, | ||
STRING, | ||
@@ -64,5 +68,7 @@ TEXT, | ||
DateType, | ||
FloatType, | ||
NumericType, | ||
RealType, | ||
ForeignKeyType, | ||
IntegerType, | ||
SerializedType, | ||
StringType, | ||
@@ -81,5 +87,7 @@ TextType, | ||
DATETIME, | ||
FLOAT, | ||
NUMERIC, | ||
REAL, | ||
FOREIGN_KEY, | ||
INTEGER, | ||
SERIALIZED, | ||
STRING, | ||
@@ -86,0 +94,0 @@ TEXT, |
@@ -232,2 +232,8 @@ 'use strict'; | ||
isDirty() { | ||
} | ||
onSetFieldValue() { | ||
} | ||
serialize(value) { | ||
@@ -234,0 +240,0 @@ return value; |
@@ -84,28 +84,48 @@ 'use strict'; | ||
function sortModelNamesByDependencyOrder(connection, modelNames, dependencyHelper) { | ||
let modelOrderMap = {}; | ||
for (let i = 0, il = modelNames.length; i < il; i++) { | ||
let modelName = modelNames[i]; | ||
let Model = connection.getModel(modelName); | ||
let dependentModelNames = dependencyHelper(Model, modelName); | ||
function sortModelNamesByDependencyOrder(connection, _modelNames, dependencyHelper) { | ||
const recursiveAdd = (modelName, _depth) => { | ||
if (modelNames.indexOf(modelName) < 0) | ||
return; | ||
modelOrderMap[modelName] = dependentModelNames; | ||
} | ||
let depth = _depth || 0; | ||
let sortedModelNames = modelNames.sort((a, b) => { | ||
if (a === b) | ||
return 0; | ||
// eslint-disable-next-line no-magic-numbers | ||
if (depth > 10) | ||
throw new Error(`ModelUtils::sortModelNamesByDependencyOrder: Cyclic dependency detected with model "${modelName}".`); | ||
let orderA = modelOrderMap[a]; | ||
let orderB = modelOrderMap[b]; | ||
if (finalOrder.has(modelName)) | ||
return; | ||
if (orderA.indexOf(b) >= 0) | ||
return 1; | ||
let dependentModelNames = modelOrderMap[modelName]; | ||
if (dependentModelNames == null) { | ||
let Model = connection.getModel(modelName); | ||
dependentModelNames = modelOrderMap[modelName] = (dependencyHelper(Model, modelName) || []); | ||
} | ||
if (orderB.indexOf(a) >= 0) | ||
return -1; | ||
if (dependentModelNames.length === 0) { | ||
finalOrder.set(modelName, dependentModelNames); | ||
return; | ||
} | ||
return Math.sign(orderA.length - orderB.length); | ||
}); | ||
for (let j = 0, jl = dependentModelNames.length; j < jl; j++) { | ||
let dependentModelName = dependentModelNames[j]; | ||
recursiveAdd(dependentModelName, depth + 1); | ||
} | ||
finalOrder.set(modelName, dependentModelNames); | ||
}; | ||
let modelOrderMap = {}; | ||
let modelNames = Nife.toArray(_modelNames).slice().sort(); | ||
let finalOrder = new Map(); | ||
for (let i = 0, il = modelNames.length; i < il; i++) { | ||
let modelName = modelNames[i]; | ||
if (!modelName) | ||
continue; | ||
recursiveAdd(modelName); | ||
} | ||
let sortedModelNames = Array.from(finalOrder.keys()); | ||
return sortedModelNames; | ||
@@ -112,0 +132,0 @@ } |
{ | ||
"name": "mythix-orm", | ||
"version": "1.4.7", | ||
"version": "1.5.0", | ||
"description": "ORM for Mythix framework", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is too big to display
399984
80
8535