Releases: BJNSTNKVC/js-db
Release list
2.4.0
Added
- Columns can be changed inside Schema.table with change(), as in table.string('nickname').nullable().change(). The new declaration replaces the old one where it stands, so a modifier left out is removed, including an index or unique index over that column alone.
- A change may toggle nullable, add, change or remove a default, change the values an enum accepts, and add or remove index() and unique().
- Existing rows are checked in the same migration. A column becoming required gives its default to rows without a value, and fails when it has no default. An enum dropping a value fails while rows still hold it. A new default fills rows missing the column. A unique index fails over repeated values. Any failure throws SchemaException naming the table, the column and the number of rows, and rolls the whole migration back.
- Changing the key path, the type of a column or the scale of a decimal is refused with SchemaException.
Changed
- Adding a unique index with table.unique() inside Schema.table over values that already repeat now throws SchemaException naming the columns, instead of IndexedDB's ConstraintError.
2.3.0
Added
- Query inside
json()columns with->paths, as inwhere('settings->theme', 'dark'). A path works in every constraint and inorderBy, including table-qualified paths in joined queries. A missing path reads asnull. whereJsonContains,whereJsonDoesntContainandwhereJsonLength, withorforms:orWhereJsonContains,orWhereJsonDoesntContainandorWhereJsonLength.select,pluckandvalueread JSON paths. An unaliased path is named after its last step, soselect('settings->theme')returnstheme, andasnames it anything else.
Changed
- A column is read only from a record's own keys. A column named after a built-in object property, such as
constructor, now reads as missing instead of reaching the prototype.
2.2.1
Fixed
- A comparison against a null column inside a negated group now stays unknown, as in SQL, so the record is excluded.
whereNot((query) => query.where('age', '>', 26))andwhereNone(['age'], '>', 26)no longer match a record whoseageisnull. whereNotInwith anullin the list no longer matches values missing from the list, since comparing against thatnullis unknown.whereNotBetweenwith anullbound now matches only values the other bound rules out, andwhereBetweenwith anullbound no longer treats that bound as a real limit.whereNotLikeandnot likeno longer match a value that is not a string, such as a number or a date. Only strings are matched by either form.- A date part constraint such as
whereYearagainst a value that holds no date is now unknown rather than false, so negating it inside a group no longer matches. - Comparing against
nullwith any operator other than equality or inequality, such aswhere('age', '>', null), is now unknown and matches nothing, including when negated.
Changed
where('age', null)is now short forwhereNull('age'), andwhere('age', '!=', null)forwhereNotNull('age'). This covers=,==,===,!=,<>and!==, treatsundefinedlikenull, andwhereNotflips the check. Previouslywhere('age', null)matched nothing.- Constraints now follow SQL's three-valued logic through nested groups, negation,
inlists,betweenbounds andlikepatterns. Queries that relied on these matching null or non-string values will return fewer records. UsewhereNull,whereNotNullororWhereNullto ask for null values explicitly.
2.2.0
Added
reorder(column?, direction?)removes existing orders, including a random one, and can set a new one.inRandomOrder()returns records shuffled. It applies toget,first,chunk,each,lazyand joined queries. With alimitoroffset,update,delete,incrementanddecrementpick their records at random.whereTime(column, operator?, value)constrains the time of day of a date column, read in local time.HH:MMis treated asHH:MM:00.whereAny,whereAllandwhereNoneapply one comparison across several columns.
Changed
dump()output now includes arandomfield.
2.1.1
Changed
dump()now prints the query's joins and transaction as well, so a joined query no longer dumps as if it read a single table.
Fixed
chunk,eachandlazyno longer deliver records that stopped matching the query after the walk began. The records that match are still decided when the walk starts, and each page is still fetched fresh. What's new is that a record changed so it no longer matches is now left out, the same as a deleted record already was. As a result, any page may be shorter than the requested size.chunknever passes an empty page to its callback, and its page numbers count only the pages delivered.
2.1.0
Added
database-version-changedevent, dispatched when another tab upgrades or deletes the database a
connection holds open. Previously the connection closed its handle silently, and the application
only found out when its next query failed withMigrationMismatchException. The event carries
databaseandversion, whereversionis the version the other tab is opening, ornullwhen
it is deleting the database.DB.onDatabaseVersionChanged()to listen for it, and theDatabaseVersionChangedclass exported
from the package.
The event is dispatched after the connection has closed its handle, so the other tab's upgrade is
never blocked while listeners run. Reloading the page is the right response. Querying again reopens
the database at the older version and fails:
DB.onDatabaseVersionChanged((event: DatabaseVersionChanged): void => {
if (confirm('A new version is available. Reload now?')) {
location.reload();
}
});
2.0.2
Fixed
update,delete,incrementanddecrementwith anorderByand alimitoroffsetnow touch the records that order selects. Before, when no index served the order, they picked records by key instead.- A limited write through several keys, such as
whereIn('id', [1, 2, 3]).limit(1).delete(), now stops at the limit instead of touching every match.
Upgrading
Ordered writes with a limit or offset may now change or delete different records than they did in 2.0.1. Check any code that relied on the old behavior.
2.0.1
Fixed
where,orWhere,whereNot,havingandorHavingnow keep an explicit operator when the value passed isundefined. Previouslywhere('role', '!=', undefined)was read asrole = '!='.
Changed
- Operators are now type checked.
where,having,whereColumn,join,leftJoin,rightJoinandJoin.onsuggest the supported operators, and a call with an unsupported operator, or one typed as a plainstring, no longer compiles. - The README now covers events and the query log in separate sections, with a table listing every event key, its class and the properties it carries.
2.0.0
Breaking
-
A migration's default name is now its class name in snake case, the way Laravel names a migration file.
CreateUsersTableis recorded ascreate_users_tableinstead ofCreateUsersTable. -
A database migrated with 1.0.0 recorded the old class names, so it will throw
MigrationMismatchExceptionon its next boot. To keep an existing database working, overridename()on each migration that already ran and return the name it was recorded under:class CreateUsersTable extends Migration { override name(): string { return 'CreateUsersTable'; } }
-
An overridden
name()is still used as is.
Changed
DB.status(),DB.migrate(),DB.fresh()and the migration events now report migration names in snake case.