mythix-orm 1.11.6 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,106 @@
1
1
  # mythix-orm
2
2
 
3
- ORM for Mythix framework
3
+ Mythix ORM aims to replace Sequelize and the few other terrible solutions that the poor destitute Node community has to work with. Mythix ORM has been designed to replace all current ORMs for Node, with a focus on what is lacking in the community, namely good engineering, good documentation, and ease of use.
4
4
 
5
- Mythix ORM aims to replace Sequelize and the few other terrible solutions that the poor destitute Node community has to work with. Mythix ORM is not yet quite ready for prime time however, so please check back soon!
6
-
7
- What to expect while you are waiting:
8
- 1. Advanced, seamless, and powerful (yet simple) query engine that is easy to use, and works across database drivers, even for No-SQL databases. Here is a simple example to fetch users and their roles: `let users = await User.where.id.EQ(Role.where.userID).firstName.EQ('Mythix').lastName.EQ('ORM').Roles.name.EQ('superuser').PROJECT('User', 'Role').all();`
5
+ Mythix ORMs feature set includes:
6
+ 1. An advanced, seamless, and powerful (yet simple) query engine that is easy to use, and works across database drivers, even for No-SQL databases.
9
7
  2. Powerful model classes and helpers that don't violate good design patterns, stay out of your face, and have no undocumented auto-magic built in. The model system is also designed to work seamlessly across different databases, including No-SQL databases.
10
8
  3. Simple, clean, and slim... Mythix ORM isn't intended to be a sledge hammer, nor a 'batteries included' framework. Instead, it is designed to be a useful tool, and was designed to be easily extended. It can be used for large enterprise applications, or it can be used as a simple slim layer to interact with different databases in a human-friendly way.
11
- 4. Mythix ORM is modular by design. Instead of being a large bloated library that attempts to handle every database and every type of operation, it instead only provides exactly what you need. Mythix ORM is itself just a base connection, a query engine, and a model and type system. That is all. To interact with databases you can choose between any number of drivers for Mythix ORM, and can use community built plugins for adding features (or simply write your own!).
12
- 5. Mythix ORM is designed from the ground-up to be extended/modified. Want to change the nature of the Query Engine? Just extend from it and away you go! Want to change the way models behave? No problem! Want to make your own connection? Go for it! Want to add your own custom data types for models? Super easy. Every part of Mythix ORM is designed to be swapped out in a non-global way so that its feature set can be extended and added onto.
13
- 6. Has complete feature parity (and soon greater functionality) then all existing ORMs for Node. Model validation, hooks, model attributes and data types, model relations, support for multiple databases, an advanced query engine, transactions, transactions inside transactions, useful utility methods, an extensible type system, virtual types, an extensible query generator, support for older Node versions, support for multiple connections and multiplex connections (at the same time), and more!
9
+ 4. A modular design. Instead of being a large bloated library that attempts to handle every database and every type of operation, it instead only provides exactly what you need. Mythix ORM is itself just a base connection, a query engine, and a model and type system. That is all. To interact with databases you can choose between any number of drivers for Mythix ORM (coming soon!), and can use community-built plugins for adding features (or simply write your own!).
10
+ 5. A deliberate design to be extended and added onto. Easily modify the Query Engine to add more features, create your own database driver, modify how models behave, or add your own custom data types. The sky is the limit!
11
+ 6. Complete feature parity (and soon greater functionality) then all existing ORMs for Node. Model validation, hooks, model attributes and data types, model relations, support for multiple databases, an advanced query engine, transactions, transactions inside transactions, useful utility methods, an extensible type system, virtual types, an extensible query generator, support for older Node versions, support for multiple connections and multiplex connections (at the same time), and more!
12
+
13
+ Mythix ORM is still in its very early stages, and is looking for users! It is stable, and currently has native support for SQLite and PostgreSQL. A mongo driver will be added next, and after that MySQL. If you want to help then drop me a line! All help is welcome.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm i --save mythix-orm mythix-orm-sqlite
19
+ ```
20
+
21
+ ## Documentation
22
+
23
+ Check out the [WIKI](https://github.com/th317erd/mythix-orm/wiki) for documentation.
24
+
25
+ ## Getting started
26
+
27
+ Just start creating models!
28
+
29
+ ```javascript
30
+ const { Model, Types } = require('mythix-orm');
31
+ const SQLiteConnection = require('mythix-orm-sqlite');
32
+
33
+ class User extends Model {
34
+ static fields = {
35
+ id: {
36
+ type: Types.XID(),
37
+ defaultValue: Types.XID.Defaults.XID,
38
+ allowNull: false,
39
+ primaryKey: true,
40
+ },
41
+ email: {
42
+ type: Types.STRING(128),
43
+ allowNull: false,
44
+ index: true,
45
+ unique: true,
46
+ },
47
+ firstName: {
48
+ type: Types.STRING(64),
49
+ allowNull: false,
50
+ index: true,
51
+ },
52
+ lastName: {
53
+ type: Types.STRING(64),
54
+ allowNull: false,
55
+ index: true,
56
+ },
57
+ };
58
+ }
59
+
60
+ // Entry point
61
+ (async function() {
62
+ // Define a connection, and "bind" our models to it
63
+ let connection = new SQLiteConnection({
64
+ models: [
65
+ User,
66
+ ],
67
+ });
68
+
69
+ // Fire up our connection
70
+ await connection.start();
71
+
72
+ // Create our tables needed for our User
73
+ // model in SQLite
74
+ await connection.createTables([ User ]);
75
+
76
+ // Now we can store and load a user
77
+ let user = new User({
78
+ email: 'test@example.com',
79
+ firstName: 'Test',
80
+ lastName: 'User',
81
+ });
82
+
83
+ // Store user
84
+ await user.save();
85
+
86
+ // Reload user by querying on the
87
+ // user's email address
88
+ user = await User.where.email.EQ('test@example.com').first();
89
+
90
+ // Serialize to JSON
91
+ console.log('My user: ', JSON.stringify(user, undefined, 2));
92
+
93
+ // Shutdown our connection
94
+ await connection.stop();
95
+ })();
96
+ ```
97
+
98
+ ## Notes
99
+
100
+ 1. The [WIKI](https://github.com/th317erd/mythix-orm/wiki) is still being worked on. Most of the documentation is complete, but there is still a lot more to write. Documentation is the main focus right now. There is a lot more to write. If you have any questions, feel free to drop a line, or open an issue! We will be happy to answer any questions. We aren't "done" until our documentation is pristine.
101
+ 2. Right now there are only database drivers for [SQLite](https://www.npmjs.com/package/mythix-orm-sqlite) and [PostgreSQL](https://www.npmjs.com/package/mythix-orm-postgresql). More are planned, with a Mongo driver likely to land next, followed by MySQL. Help wanted!
102
+ 3. Check out the [Mythix](https://www.npmjs.com/package/mythix) web-app framework. It is also still in active development, and the documentation is poor (to say the least), but it is up and coming, and will soon have fantastic documentation, and even though still in active development is fully functional. To get started try `npx mythix-cli create 'Test App'`
103
+
104
+ ## Goals
14
105
 
15
- Stay tuned! Mythix ORM should be released and fully documented by Q1 of 2023!
106
+ The `Mythix` suite of technologies are being developed to give a rock-solid full-stack to build web-apps on Node. I got tired of the piecemeal garbage that currently exist in the Node ecosystem for building apps. My end goal is to have `Mythix` technologies take the Node community by storm, providing top-notch technologies for developers to create amazing things. Get involved with me, and let's change the world for the better!
@@ -3,7 +3,6 @@
3
3
  const { DateTime } = require('luxon');
4
4
  const EventEmitter = require('events');
5
5
  const Nife = require('nife');
6
- const SqlString = require('sqlstring');
7
6
  const { QueryEngine } = require('../query-engine');
8
7
  const Utils = require('../utils');
9
8
  const { Model: ModelBase } = require('../model');
@@ -230,6 +229,8 @@ class ConnectionBase extends EventEmitter {
230
229
 
231
230
  if (!options.queryGenerator)
232
231
  options.queryGenerator = this.createQueryGenerator(options);
232
+ else
233
+ options.queryGenerator.setConnection(this);
233
234
 
234
235
  Object.defineProperties(this, {
235
236
  'dialect': {
@@ -280,6 +281,39 @@ class ConnectionBase extends EventEmitter {
280
281
  return new QueryGeneratorBase(this);
281
282
  }
282
283
 
284
+ /// An `Object.assign` type of operation... with a twist.
285
+ ///
286
+ /// `stackAssign` works kinda like `Object.assign`. It has
287
+ /// the same interface, and accomplishes the same result.
288
+ /// What it does differently however is that it uses
289
+ /// `Object.create` on the first argument to create a new
290
+ /// object, using the first argument as a prototype. It then
291
+ /// merges all remaining `object` arguments into this newly
292
+ /// created object.
293
+ ///
294
+ /// This is used quite heavily in the underlying Mythix ORM engine.
295
+ /// It's purpose is to modify `options` arguments as they pass through
296
+ /// the engine. For example, a `destroy` operation might want to inform
297
+ /// the projection engine that we don't want any field aliases... and
298
+ /// so it will `stackAssign` the `options`, setting `noProjectionAliases: true`
299
+ /// for the "stacked options" object. Javascript--being the prototypical language
300
+ /// that it is--will *behave* like the objects in question have been
301
+ /// passed through `Object.assign`, because all the original `options` to
302
+ /// any operation are still accessible in the prototype, but may have been
303
+ /// overridden like in our example of a `destroy` operation. This allows the
304
+ /// engine to easily and quickly override options without mutating the original
305
+ /// `options` object provided, and still be able to access provided options,
306
+ /// even if they are not enumerable.
307
+ ///
308
+ /// Arguments:
309
+ /// obj: object
310
+ /// The object to set as the prototype of the newly created object,
311
+ /// using `Object.create` on it.
312
+ /// ...args: Array<object>
313
+ /// The other objects to merge into this object, using `Object.assign`.
314
+ ///
315
+ /// Return: object
316
+ /// The newly "stacked" and merged object.
283
317
  stackAssign(obj, ..._args) {
284
318
  let newObj = Object.create(obj || {});
285
319
  let args = _args.filter(Boolean);
@@ -347,12 +381,14 @@ class ConnectionBase extends EventEmitter {
347
381
  }
348
382
 
349
383
  /// Get the default order for selecting rows
350
- /// from the database. This will call the
351
- /// Model's <see name="Model.defaultOrder">Model.static defaultOrder</see> method
352
- /// first to see if the model specifies a default order
353
- /// for itself. If it doesn't, then the connection
384
+ /// from the database. The connection
354
385
  /// driver itself might specify a default order for
355
- /// each table.
386
+ /// each table, if one isn't specified by the user.
387
+ ///
388
+ /// Note:
389
+ /// To specify a default order for each model, use
390
+ /// the <see>Model.static defaultScope</see> method
391
+ /// instead.
356
392
  ///
357
393
  /// Arguments:
358
394
  /// Model: class <see>Model</see>
@@ -408,6 +444,35 @@ class ConnectionBase extends EventEmitter {
408
444
  return true;
409
445
  }
410
446
 
447
+ /// A convenience method to get from "model cache".
448
+ ///
449
+ /// Model Cache is a simple system to cache
450
+ /// random results from model methods. This is used
451
+ /// for things that should never change, for example
452
+ /// the models fields, the models name, the table
453
+ /// name for the model, etc... Some of these values
454
+ /// are initially computed, and then cached using this
455
+ /// system so operations later on return much quicker.
456
+ ///
457
+ /// Note:
458
+ /// The underlying cache system uses the `Map` type,
459
+ /// so any value can be used as a cache key.
460
+ ///
461
+ /// Note:
462
+ /// This cache is never cleared or marked as stale, so
463
+ /// if using dynamic cache keys, make sure that you
464
+ /// properly remove them later to prevent memory leaks.
465
+ ///
466
+ /// Arguments:
467
+ /// Model: class <see>Model</see>
468
+ /// The model class we a caching for.
469
+ /// key: any
470
+ /// The key to use for our cache.
471
+ /// defaultValue?: any
472
+ /// The default value to return if no cache entry was found.
473
+ ///
474
+ /// Return: any
475
+ /// Any value found in the cache.
411
476
  _getFromModelCache(Model, key, defaultValue) {
412
477
  let cache = this._modelCache.get(Model);
413
478
  if (!cache)
@@ -420,6 +485,35 @@ class ConnectionBase extends EventEmitter {
420
485
  return value;
421
486
  }
422
487
 
488
+ /// A convenience method to set to the "model cache".
489
+ ///
490
+ /// Model Cache is a simple system to cache
491
+ /// random results from model methods. This is used
492
+ /// for things that should never change, for example
493
+ /// the models fields, the models name, the table
494
+ /// name for the model, etc... Some of these values
495
+ /// are initially computed, and then cached using this
496
+ /// system so operations later on return much quicker.
497
+ ///
498
+ /// Note:
499
+ /// The underlying cache system uses the `Map` type,
500
+ /// so any value can be used as a cache key.
501
+ ///
502
+ /// Note:
503
+ /// This cache is never cleared or marked as stale, so
504
+ /// if using dynamic cache keys, make sure that you
505
+ /// properly remove them later to prevent memory leaks.
506
+ ///
507
+ /// Arguments:
508
+ /// Model: class <see>Model</see>
509
+ /// The model class we a caching for.
510
+ /// key: any
511
+ /// The key to use for our cache.
512
+ /// value: any
513
+ /// The value to cache.
514
+ ///
515
+ /// Return: any
516
+ /// The `value` provided.
423
517
  _setToModelCache(Model, key, value) {
424
518
  let cache = this._modelCache.get(Model);
425
519
  if (!cache) {
@@ -493,6 +587,51 @@ class ConnectionBase extends EventEmitter {
493
587
  return queryEngine;
494
588
  }
495
589
 
590
+ /// Finalize a query before using it for database operations.
591
+ ///
592
+ /// `finalizeQuery` is called on **every** query immediately
593
+ /// before it is used for a database operation. Its only purpose
594
+ /// is to potentially modify the query before the database operation
595
+ /// occurs. This can be extremely useful for things like "row level permissions",
596
+ /// or ensuring that a certain type of query always has certain conditions.
597
+ ///
598
+ /// Because it is asynchronous by design, it is possible to finalize the
599
+ /// query using other asynchronous operations; for example validating
600
+ /// authentication tokens, or fetching user roles from the database.
601
+ ///
602
+ /// It works by walking the provided query, and calling <see>Model.static finalizeQuery</see>
603
+ /// on every model it encounters that is used in the query. It will also recursively
604
+ /// call itself for every new query it encounters that is part of the query,
605
+ /// for example sub-queries. In this way, you can take on extra conditions to any
606
+ /// part of a query, throw a "Forbidden" exception if the user is disallowed from querying
607
+ /// certain data, or whatever you want.
608
+ ///
609
+ /// Note:
610
+ /// "With great power comes great responsibility." Use `finalizeQuery` intelligently. It can
611
+ /// cause a noticeable performance hit, and can really make things hard to debug and
612
+ /// understand if you don't clearly document.
613
+ ///
614
+ /// Note:
615
+ /// `'create'` isn't actually currently supported, since no queries are
616
+ /// ever used in an `INSERT` operation. It is reserved for future use.
617
+ ///
618
+ /// Arguments:
619
+ /// crudOperation: 'create' | 'read' | 'update' | 'delete'
620
+ /// The Mythix ORM reports what "type" of operation is being executed
621
+ /// using this argument. This is used so one can know if the operation
622
+ /// that is about to be executed is a `read`, `update`, or `delete` operation.
623
+ /// query: <see>QueryEngine</see>
624
+ /// The query to operate upon. This will be walked, calling <see>Model.static finalizeQuery</see>
625
+ /// for each unique model encountered, and also recursively walking any sub-queries.
626
+ /// options?: object
627
+ /// Random options for the operation. These are not used by this method, but instead are
628
+ /// the `options` provided to the database operation when it was requested, and are also
629
+ /// available for use for any user needs.
630
+ ///
631
+ /// Return: <see>QueryEngine</see>
632
+ /// The query provided, possibly altered.
633
+ ///
634
+ /// See: Model.static finalizeQuery
496
635
  async finalizeQuery(crudOperation, queryEngine, options) {
497
636
  if (!QueryEngine.isQuery(queryEngine))
498
637
  return queryEngine;
@@ -613,7 +752,7 @@ class ConnectionBase extends EventEmitter {
613
752
  /// it was created.
614
753
  ///
615
754
  /// Arguments:
616
- /// Model: Array<class <see>Model</see>> | { [key: string]: class <see>Model</see> }
755
+ /// models: Array<class <see>Model</see>> | { [key: string]: class <see>Model</see> }
617
756
  /// The model classes to register with this connection. If no models are bound, then
618
757
  /// they will simply exist in the model pool for this connection. If bound, then
619
758
  /// this connection will bind itself to every model being registered.
@@ -623,13 +762,14 @@ class ConnectionBase extends EventEmitter {
623
762
  /// provided to the connection when it was created. If you specify either of these
624
763
  /// options they simply override the connection's default.
625
764
  ///
626
- /// Return: class <see>Model</see>
765
+ /// Return: { [key: string]: class <see>Model</see> }
627
766
  /// The registered model classes, **which may have changed during registration**.
628
767
  /// It is not uncommon for the connection driver itself to modify the model
629
768
  /// classes, or to return a new model classes that inherit from your model classes.
630
769
  /// The classes that are returned should be the classes that you use for this connection,
631
770
  /// and will be the same classes returned by a call to <see>Connection.getModel</see>,
632
- /// or <see>Connection.getModels</see>.
771
+ /// or <see>Connection.getModels</see>. An object is returned, where each key is
772
+ /// a model name, and each value is a model class.
633
773
  registerModels(models, options) {
634
774
  if (!models)
635
775
  return;
@@ -916,7 +1056,14 @@ class ConnectionBase extends EventEmitter {
916
1056
  /// Return the <see>QueryGenerator</see> for this connection,
917
1057
  /// or return `null` if none is defined for this connection.
918
1058
  getQueryGenerator() {
919
- return this.queryGenerator;
1059
+ let queryGenerator = this.queryGenerator;
1060
+ if (queryGenerator) {
1061
+ let connection = queryGenerator.getConnection();
1062
+ if (!connection)
1063
+ queryGenerator.setConnection(this);
1064
+ }
1065
+
1066
+ return queryGenerator;
920
1067
  }
921
1068
 
922
1069
  /// Set the <see>QueryGenerator</see> instance for this
@@ -940,15 +1087,10 @@ class ConnectionBase extends EventEmitter {
940
1087
  }
941
1088
 
942
1089
  /// The low-level DB interface for escaping a
943
- /// value. By default this function uses the
944
- /// [sqlstring](https://www.npmjs.com/package/sqlstring)
945
- /// module to escape values. However, the `escape`
946
- /// method for whatever database the connection is
947
- /// using should be used instead of this. This is
948
- /// a "default implementation" that is meant as a
949
- /// fallback when a connection doesn't provide its
950
- /// own, but each connection should provide its own
951
- /// when it is able.
1090
+ /// value. By default this function simply returns
1091
+ /// the value it is provided. It is up to the
1092
+ /// database driver itself to provide a proper
1093
+ /// implementation of this method.
952
1094
  ///
953
1095
  /// Note:
954
1096
  /// This method escapes "values" that are given in
@@ -957,8 +1099,7 @@ class ConnectionBase extends EventEmitter {
957
1099
  /// instead.
958
1100
  ///
959
1101
  /// Return: string
960
- /// The value provided, escaped for the specific
961
- /// underlying database driver.
1102
+ /// The value provided.
962
1103
  ///
963
1104
  /// Arguments:
964
1105
  /// value: any
@@ -966,10 +1107,7 @@ class ConnectionBase extends EventEmitter {
966
1107
  /// a string, or anything else that can be provided to your
967
1108
  /// specific database.
968
1109
  _escape(value) {
969
- if (Nife.instanceOf(value, 'string'))
970
- return `'${value.replace(/'/g, '\'\'')}'`;
971
-
972
- return SqlString.escape(value);
1110
+ return value;
973
1111
  }
974
1112
 
975
1113
  /// Unlike <see>ConnectionBase._escape</see> --which is
@@ -1060,22 +1198,18 @@ class ConnectionBase extends EventEmitter {
1060
1198
  /// provides as a "fallback" to database drivers that don't
1061
1199
  /// supply their own.
1062
1200
  ///
1063
- /// It works by first stripping all quotes (single `'`, double `"`, and backtick `` ` ``)
1064
- /// from the provided `value`. After this, it will split on the period (dot) character
1065
- /// `.`, and then will map each resulting part through [sqlstring](https://www.npmjs.com/package/sqlstring)
1066
- /// `escapeId` method, finally re-joining the parts with a period `.` character.
1067
- ///
1068
- /// The extra processing is to allow for already escaped identifiers to not be double-escaped.
1201
+ /// This method simply returns the value provided. It is
1202
+ /// expected that each database driver will properly overload
1203
+ /// this method to provide the correct escaping for identifiers.
1069
1204
  ///
1070
1205
  /// Return: string
1071
- /// The provided identifier, escaped for the underlying database.
1206
+ /// The provided identifier.
1072
1207
  ///
1073
1208
  /// Arguments:
1074
1209
  /// value: string
1075
1210
  /// The identifier to escape.
1076
1211
  _escapeID(value) {
1077
- let parts = value.replace(/['"`]/g, '').split(/\.+/g);
1078
- return parts.map((part) => SqlString.escapeId(part).replace(/^`/, '"').replace(/`$/, '"')).join('.');
1212
+ return value;
1079
1213
  }
1080
1214
 
1081
1215
  /// This method is very similar to <see>ConnectionBase._escapeID</see>,
@@ -1382,10 +1516,10 @@ class ConnectionBase extends EventEmitter {
1382
1516
  /// will be database specific. The database driver connection
1383
1517
  /// is free to override this method.
1384
1518
  ///
1385
- /// This method will convert a <see>AverageLiteral</see>, a
1386
- /// <see>CountLiteral</see>, a <see>DistinctLiteral</see>,
1387
- /// a <see>FieldLiteral</see>, a <see>MaxLiteral</see>, a
1388
- /// <see>MinLiteral</see>, a <see>SumLiteral</see>, or a
1519
+ /// This method will convert an <see>AverageLiteral</see>,
1520
+ /// <see>CountLiteral</see>, <see>DistinctLiteral</see>,
1521
+ /// <see>FieldLiteral</see>, <see>MaxLiteral</see>,
1522
+ /// <see>MinLiteral</see>, <see>SumLiteral</see>, or a
1389
1523
  /// <see>Literal</see> to a string. If the provided literal
1390
1524
  /// is not one of these types, than an exception will be thrown.
1391
1525
  ///
@@ -2651,7 +2785,7 @@ class ConnectionBase extends EventEmitter {
2651
2785
  /// Create a table/bucket using the provided model class.
2652
2786
  ///
2653
2787
  /// The provided `options` are database specific,
2654
- /// but might contain things like `ifExists`, for
2788
+ /// but might contain things like `ifNotExists`, for
2655
2789
  /// example.
2656
2790
  ///
2657
2791
  /// Return: any
@@ -2,11 +2,78 @@
2
2
 
3
3
  const LiteralFieldBase = require('./literal-field-base');
4
4
 
5
+ /// Define an "average" literal for the underlying database.
6
+ ///
7
+ /// Literals are special types in Mythix ORM that are used to
8
+ /// define "literal values" for the underlying database.
9
+ ///
10
+ /// This literal defines an "average" operation across a single
11
+ /// column. It is used by <see>Connection.average</see> to get
12
+ /// the average across all rows for a single column in the underlying
13
+ /// database. When serialized using the <see>QueryGenerator</see>
14
+ /// for the connection, it will turn into a database method that
15
+ /// is appropriate for the underlying database. For example, with
16
+ /// SQL type databases this would turn into `AVG(column)`. This is
17
+ /// often used by the projection engine, to project it as a column
18
+ /// to be selected. For example `SELECT AVG(column) ...`. It can
19
+ /// be used in other places in the query however, such as `ORDER`,
20
+ /// `GROUP BY`, and `HAVING` clauses.
21
+ ///
22
+ /// There are two primary ways to access literals in Mythix ORM. The
23
+ /// first is to simply import them. The second way literals can be
24
+ /// accessed is via the connection class itself. All Mythix ORM connection
25
+ /// classes export all literals on the `static Literals` attribute of
26
+ /// the class. So for example, you could access literals like `SQLiteConnection.Literals.AverageLiteral`.
27
+ ///
28
+ /// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
29
+ /// as their first argument. This field can be a fully qualified field name, an actual
30
+ /// <see>Field</see> instance, or another literal. The second argument to all literal constructors
31
+ /// is an `options` object, that generally contains connection-specific (and operation-specific) options...
32
+ /// however, there are common options that can be supplied, such as `as: string;` which allows you to
33
+ /// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
34
+ /// the column alias entirely.
35
+ ///
36
+ /// Example:
37
+ /// const { Literals } = require('mythix-orm');
38
+ /// const { SQLiteConnection } = require('mythix-orm-sqlite');
39
+ /// let literal1 = new Literals.AverageLiteral('User:age');
40
+ /// let literal2 = new SQLiteConnection.Literals.AverageLiteral('User:age');
41
+ ///
42
+ /// See: LiteralFieldBase
43
+ ///
44
+ /// See: LiteralBase
5
45
  class AverageLiteral extends LiteralFieldBase {
46
+ /// Return `true`, letting the caller know that
47
+ /// this is an "aggregating literal".
48
+ ///
49
+ /// Return: boolean
50
+ /// Return `true`, informing the caller that this literal is used for aggregate operations.
6
51
  static isAggregate() {
7
52
  return true;
8
53
  }
9
54
 
55
+ /// Convert this literal to a string to be used in a database query.
56
+ ///
57
+ /// This method proxies the conversion of this literal to the connection
58
+ /// by calling <see>Connection.literalToString</see>. If no connection
59
+ /// is provided when this is called, then the literal will be converted
60
+ /// to a string representing it for debugging, i.e. `'AverageLiteral {}'`.
61
+ ///
62
+ /// Note:
63
+ /// Ultimately, for most connections, this will end up calling
64
+ /// <see>QueryGenerator._averageLiteralToString</see>.
65
+ ///
66
+ /// Arguments:
67
+ /// connection?: <see>Connection</see>
68
+ /// The connection to use to stringify this literal. If none is provided,
69
+ /// then a string representing this object will be returned instead.
70
+ /// options?: object
71
+ /// A connection and operation specific set of options that can be provided.
72
+ /// This might for example be `{ as: 'name' }` to provided a field alias, or
73
+ /// `{ isProjection: true }` to define that this is being stringified for use
74
+ /// as a field in the query projection. Normally the end-user won't care about
75
+ /// any literal options, except `as`, which is commonly used to give your literal
76
+ /// an alias.
10
77
  toString(connection, options) {
11
78
  if (!connection)
12
79
  return `${this.constructor.name} {}`;
@@ -2,15 +2,95 @@
2
2
 
3
3
  const LiteralFieldBase = require('./literal-field-base');
4
4
 
5
+ /// Define a "count" literal for the underlying database.
6
+ ///
7
+ /// Literals are special types in Mythix ORM that are used to
8
+ /// define "literal values" for the underlying database.
9
+ ///
10
+ /// This literal defines a "count" operation across all matching
11
+ /// rows. It is used by <see>Connection.count</see> to get
12
+ /// the number of matching rows for a query. When serialized using
13
+ /// the <see>QueryGenerator</see> for the connection, it will turn
14
+ /// into a database method that is appropriate for the underlying database.
15
+ /// For example, with SQL type databases this would turn into `COUNT(column)`,
16
+ /// our `COUNT(*)`. This is often used by the projection engine, to project
17
+ /// it as a column to be selected. For example `SELECT COUNT(column) AS count ...`.
18
+ /// It can be used in other places in the query however, such as `ORDER`,
19
+ /// `GROUP BY`, and `HAVING` clauses.
20
+ ///
21
+ /// Note:
22
+ /// If no field is provided to `CountLiteral`
23
+ /// then all fields (`*`) is assumed.
24
+ ///
25
+ /// Note:
26
+ /// It is common to use the `{ as: 'count' }` option to give the count
27
+ /// literal an alias (name).
28
+ ///
29
+ /// There are two primary ways to access literals in Mythix ORM. The
30
+ /// first is to simply import them. The second way literals can be
31
+ /// accessed is via the connection class itself. All Mythix ORM connection
32
+ /// classes export all literals on the `static Literals` attribute of
33
+ /// the class. So for example, you could access literals like `SQLiteConnection.Literals.CountLiteral`.
34
+ ///
35
+ /// All built-in Mythix ORM literals--except `Literal` and `LiteralBase`--accept a field
36
+ /// as their first argument. This field can be a fully qualified field name, an actual
37
+ /// <see>Field</see> instance, or another literal. The second argument to all literal constructors
38
+ /// is an `options` object, that generally contains connection-specific (and operation-specific) options...
39
+ /// however, there are common options that can be supplied, such as `as: string;` which allows you to
40
+ /// define an alias for the defined field, and `noProjectionAliases: boolean;`, which allows you to disable
41
+ /// the column alias entirely.
42
+ ///
43
+ /// Example:
44
+ /// const { Literals } = require('mythix-orm');
45
+ /// const { SQLiteConnection } = require('mythix-orm-sqlite');
46
+ /// let literal1 = new Literals.CountLiteral('*', { as: 'count' });
47
+ /// let literal2 = new SQLiteConnection.CountLiteral.CountLiteral('*', { as: 'count' });
48
+ ///
49
+ /// See: LiteralFieldBase
50
+ ///
51
+ /// See: LiteralBase
5
52
  class CountLiteral extends LiteralFieldBase {
53
+ /// Return `false`, informing the engine that
54
+ /// a field is not required for this literal type.
55
+ ///
56
+ /// Return: boolean
57
+ /// Return `false`, informing the caller that this literal
58
+ /// does not require a field.
6
59
  static isFieldRequired() {
7
60
  return false;
8
61
  }
9
62
 
63
+ /// Return `true`, letting the caller know that
64
+ /// this is an "aggregating literal".
65
+ ///
66
+ /// Return: boolean
67
+ /// Return `true`, informing the caller that this literal is used for aggregate operations.
10
68
  static isAggregate() {
11
69
  return true;
12
70
  }
13
71
 
72
+ /// Convert this literal to a string to be used in a database query.
73
+ ///
74
+ /// This method proxies the conversion of this literal to the connection
75
+ /// by calling <see>Connection.literalToString</see>. If no connection
76
+ /// is provided when this is called, then the literal will be converted
77
+ /// to a string representing it for debugging, i.e. `'CountLiteral {}'`.
78
+ ///
79
+ /// Note:
80
+ /// Ultimately, for most connections, this will end up calling
81
+ /// <see>QueryGenerator._countLiteralToString</see>.
82
+ ///
83
+ /// Arguments:
84
+ /// connection?: <see>Connection</see>
85
+ /// The connection to use to stringify this literal. If none is provided,
86
+ /// then a string representing this object will be returned instead.
87
+ /// options?: object
88
+ /// A connection and operation specific set of options that can be provided.
89
+ /// This might for example be `{ as: 'name' }` to provided a field alias, or
90
+ /// `{ isProjection: true }` to define that this is being stringified for use
91
+ /// as a field in the query projection. Normally the end-user won't care about
92
+ /// any literal options, except `as`, which is commonly used to give your literal
93
+ /// an alias.
14
94
  toString(connection, options) {
15
95
  if (!connection)
16
96
  return `${this.constructor.name} {}`;