All notable changes to this project will be documented in this file.
Live query / SSE resilience. The client no longer loses updates when the SSE stream dies while HTTP still works.
- Each server-side live query carries a version, sent with every change and returned by the keep-alive. The client refetches the snapshot on any version gap, so a dead socket, a half-open socket or a missed message is recovered within one keep-alive
SseSubscriptionClientreconnects forever with backoff (was 4 tries), reconnects onvisibilitychange/online/pageshow, and recreates a socket that stops delivering events forflags.sseStaleMsliveQueryfirstnext()no longer waits for the SSE connection- Server SSE ping every 15s (was 45s), exported as
ssePingMs - New
flags.sseStaleMs(40s),flags.liveQueryKeepAliveMs(30s),flags.liveQueryPollWhenStaleMs(1s) SubscriptionListener.reconnect?()letsSubscriptionChannelsubscribers refetch state after a dropped connectionLiveQueryChangehas an internal{ type: 'version', from, to }member, filtered out before reachingliveQuerylisteners- Breaking for custom
LiveQueryStorage:keepAliveAndReturnUnknownQueryIdsreturns{ unknownQueryIds, versions }instead ofstring[]. The keep-alive route still accepts the old array body from older clients SubscriptionClientConnectiongained optionallastServerEventandresume(force?); custom clients (Ably, ...) can ignore them- Fixed REST
_select/find({ select })serializing omitted fields throughtoApiJson, so dates and custom converters leaked as''instead of being absent - REST docs fixes
- Fixed
ArrayEntityDataProviderstoring omitted/undefinednullable fields asundefinedinstead ofnull, so filters like{ date: null }missed rows inserted without a value
- Fixed
TypeError: Cannot delete propertyon client save when a field hasincludeInApi: falseand the entity was subscribed (e.g. grid dirty tracking)
- Added support for default values without an arrow function
- Added type info in the field's function response - used for typing stuff :)
- Added a Node built-in SQLite data provider (
remult/remult-node-sqlite), using the nativenode:sqlitemodule (#1034). - Thanks to @linoch512 for their first contribution
groupBynow ignoresorderByfields that are not part of the group by (previously they were passed through to the database, producing an invalid grouped query on SQL Server / Postgres). The rest api additionally ignoresorderByfields that are not included in the api.
- Fixed a memory leak related to usage of repo(x,y) with infinite different y
- Fixed
groupBy/aggregatewithlimit/pagebut noorderByemittingOFFSET/FETCHwithout anORDER BY, which is invalid on SQL Server. A grouped query now falls back to ordering by the group columns, and a pure aggregate skips paging entirely. - The
queryapi action no longer leaks the items' paging into the aggregate, so the aggregate summarizes the whole filtered set.
- Fixed issue with auto increment in ArrayEntityDataProvider where the dbname of the auto increment field was different than the member key
- Improve Indexed db connection error further
- Change Postgres Table Alter Autoincrement to Use Serial, by @jckwik - #968
- Thanks to @jckwik for their first contribution
- Improved handling of indexed db connection close etc...
- Fixed issue with indexed db recovery after close (ios closes long open indexed db)
- Reduced npm package size by > 50%
- Added clear to indexed db database
- #874 - fix: Ensure backend methods are included directly (openApi sveltekit)
- #876 Relation should return undefined when includeInApi is false for its id field
- #865 - fix paging syntax in group by for sql server
- #864 - fixed missing transformations for min and max group by values
- Added paged query result to internals (for now)
- Expose
DataProviderPromiseWrapperin internals
- Doc update by @jycouet in #831
- Light check if admin is here (demo app) by @jycouet in #834
- #830 - changed update many to always use select none
- #829 - fixed issue with insert & knex & autoIncrement columns
- Added support for select:'none' also to
save - Fixed issue with where:'all'
- #820 - option to eliminate update/insert result to improve performance.
repo(Task).Insert({ id: 1, name: 'test' }, { select: 'none' })
- Added option for
deleteMany({where:'all'})andupdateMany({where:'all',set:{ status:0 }}) - Fixed a bunch if issues around
ValueConverter.DateOnlyString
- Fix Backend method issue #890
- Updated remult admin to manage
allowNullfields
- Export EntitySelectFields type
- Added support for
selectinfind, now you can select which fields will be part of the query and part of the result.await repo(Task).find({ select: { id: true, title: true } })
- Thanks to @delebash for their first contribution
- Minor fix for
standardSchema- require an object. - Thanks to @Nipodemos for their first contribution to the docs
- Add
standardSchemaimplementing the Standard Schema specification. Check Remult Standard Schema for more details.
- Fix by @LazyShpee for
initAsyncHookswithoutremultApi - Added support for
express 5 - Added support for
nuxt 4 - removed remult dependencies:
reflect-metadatauuid@paralleldrive/cuid2
- Minimum node version is now
18(with--experimental-global-webcryptoflag) or20(without flag) - We are introducing
@Fields.id()field (usingcrypto.randomUUID()under the hood)@Fields.uuid()is now deprecated, use@Fields.id()instead (uuid is the default id factory)- [BREAKING] Removed
@Fields.cuid()- use@Fields.id()instead and change theidFactoryto your preferred id algorithm.
You have 2 options:
First, install the @paralleldrive/cuid2 package:
npm install @paralleldrive/cuid2Then, globally, in a shared code file:
import { createId } from '@paralleldrive/cuid2'
import { Fields } from 'remult'
Fields.defaultIdFactory = () => createId()Finally, replace @Fields.cuid() with @Fields.id()
First, install the @paralleldrive/cuid2 package:
npm install @paralleldrive/cuid2Then, create your own cuid Field:
import { createId } from '@paralleldrive/cuid2'
import { Fields } from 'remult'
export function MyFields_cuid<entityType = any>(
...options: FieldOptions<entityType, string>[]
) {
return Fields.id<entityType>({ idFactory: createId }, ...options)
}Finally, replace @Fields.cuid() with MyFields_cuid()
- Added a
labeloption for field and entity that'll gradually replacecaption - Added modules to
remultApioptions. - Added
remult.context.headersto access the request headers in a framework-agnostic way. - Added D1 Support by (@taivo) Big thanks to @taivo for his first contribution
- Fixed a performance issue added in 3.0.0
- #719 Export initAsyncHooks for use of withRemult in non API projects Big thanks to @LazyShpee for his first contribution
- Fixed issue where cases when multiple
$neor$ninwere used with rest data provider and the value 0 - the 0 value would sometime not be sent to the server
- Few doc updates by @jycouet in #704
- add removeItem method to JsonEntityIndexedDbStorage by @TGlide in #703
- 🚧 UPDATE: sveltekit data is now always returning application/json by @jycouet in #706
- Fix undefined error in TestApiDataProvider with multiple relations
- Update DuckDB adapter to use new @duckdb/node-api package - #700 Big thanks to @jc955 for his first contribution
- #697 - escape backtick in migrations code Big thanks to @fapspirit for his first contribution
- Unified the function name used to setup remult api to
remultApi(Instead ofremultExpressetc...) - Added a
dataProviderfunction toEntityOptionsthat allows you to select a dataProvider per entity. - Admin UI:
- you can now add custom headers requests (
key: valueformat) - In diagram, you can visualize
ToOnerelations with the color of the entity on the left. - add
requireAuthTokento admin options to open settings dialog to set the bearer token directly. - add
disableLiveQueryto admin options to control if live query is used. (can be overwritten by local storage settings)
- you can now add custom headers requests (
- Added support for sql expression based entity to knex data provider
- Fixed bug with API Update of null with dateOnly
- Fixed admin to show json editor also for arrays
- Added
subscribeAuthto remult to support reactivity - Admin ui:
- Fixed issue where json editor was not working when the json field was an array
- Fixed issue where json field did not trigger the change detection (color green)
ValueConverters.Number.fromInput(null)now returnsnull(was undefined before).
- Fixed
wherecontaining a$notfromapito work in addition with other filters. - More fixes to remult admin
- Fixes to remult admin
- Improved error in case if undefined in
getEntityRef
- fix: sqlite - index already exists by @olragon in #599 Big thanks to @olragon for his first contribution
- Fixed issue with turning on admin breaks routing in some cases
- Fixed admin to work with authorization token as well
- Moved version decimal point to better reflect remult's stability and use in production app.
- Fixed issue where setting a value to undefined, caused an invalid update statement -
update "tasks" set where "id" = $1and an error:error: syntax error at or near "where" - Fixed issue where find options object was changed when sent to find method
- Fixed an issue where group by was accessible even if allowApiRead was not - this did not affect apiPrefilter
- Added
min,maxandrangevalidators by @YonatanKra - Quality of life improvements to admin by @jycouet & @ermincelikovic
- In the office hour with @ermincelikovic (and cursor) we :
- reduce the column size of numbers & align right
- manage keyboard navigation in the grid
- manage shortcuts
- CTRL+Enter => Save the row
- CTRL+Esc => Cancel the tow
- CTRL+SHIFT+Enter => Save all rows
- CTRL+SHIFT+Esc => Cancel all rows
- Added
EntityError- now when insert/update etc... fail they throw this specific error. - Log queries if they are greater than equals the threshold by @arikfr in #571
- Fixed an issue with decorators and optional null field
- fixed issue with aggregate in query
- Fixed issue with subscribe to entity changes and relations
- Remult create adjusted for Svelte 5 by @jycouet
- Improved support for sveltekit ssr. To configure:
-
To enable remult across all sveltekit route
// src/hooks.server.ts import { api } from './server/api' export const handle = api
-
To Use remult in ssr
PageLoad- this will leverage theevent's fetch to load data on the server without reloading it on the frontend, and abiding to all api rules even when it runs on the server// src/routes/+page.ts import { remult } from 'remult' import type { PageLoad } from './$types' export const load = (async (event) => { // Instruct remult to use the special svelte fetch to fetch data on server side page load remult.useFetch(event.fetch) return repo(Task).find() }) satisfies PageLoad
-
-
Added
upsertmethod:
Theupsertmethod allows inserting or updating an entity in a single operation. If an entity matching thewherecondition is found, it is updated; otherwise, a new entity is created. This can be used for a single entity or for batch operations with an array of options.Example:
// Single entity upsert await taskRepo.upsert({ where: { title: 'task a' }, set: { completed: true }, }) // Batch upsert await taskRepo.upsert([ { where: { title: 'task a' }, set: { completed: true } }, { where: { title: 'task b' }, set: { completed: true } }, ])
-
Now you can get data and aggregate info with a single request using the
querymethod:const result = await repo .query({ where: { completed: false }, pageSize: 50, aggregates: { sum: ['salary'], average: ['age'], }, }) .paginator() // Accessing the items from the first page console.table(result.items) // Accessing the aggregation results console.log(result.aggregates.salary.sum) // Total salary sum
-
Added
TestApiDataProviderto use in unit tests that test api rules. see tutorial -
Fixed that values that are not included will not exist in the resulting object (previously they existed with value undefined)
-
Fixed that relations that were not included, will not be enumerable in the resulting object (previously they were only set to undefined)
-
Fixed
serverExpressionto run whenever we're not using aproxydata provider (for example RestDataProvider) -
Fixed issue with
updateManywhere thesethadValueListTypeor relation. -
Fixed issue when updating relation id and relation in the same update, the last one will win
-
Fixed makeTitle to handle all caps text
-
Added experimental api for sqlRelations & sqlRelationsFilter - see Sql Relations
-
Added Origin IndexedDb Storage to store entities in the frontend:
const db = new JsonDataProvider(new JsonEntityIndexedDbStorage()) console.table(await repo(Task, db).find())
-
Fixed issue with required validation and relations
- Fixed issue with stackblitz async_hook replacer
- Added
remult.initUserthat initializes the frontend remult with the user based on the backend - Fixed issue with dual call to initRequest in some cases
- Added support for
customFilterdefined in base classes
- fixed issue with null first and group by
- fixed an error where from json returned a row that didn't have an id and could cause problems
- fixed double init request in cases where
withRemultaccidentally wraps remult server
- added
$notto value comparison:{where:{id:{ $not:1 }}}}for improved readability - removed
groupoption fromaggregate - Added unique id validations to all databases
- Verified that all databases add missing columns on
ensureSchema - Removed the deprecated behavior where if no entities array was sent to remult server, all entities were served
- Removed the deprecated web sql data provider, since no browsers support it - us the OpfsEntityDataProvider instead
- Changed id signature in EntityOptions to also allow
id:'code'&id:['company','code']for compound id columns - Fix to remult admin
- Potential breaking change change the http status code of exceptions thrown in backend method from 500 to 400
- Fix for minor typing issue regarding field | null | undefined
- Fix for minor issue in knex
- More great improvements to remult admin by jycouet
- Added
groupBy&aggregatetoRepositoryCheckout this example videorepo(Employee).groupBy({ group: ['country', 'city'], sum: ['salary'], where: { salary: { $gt: 2000, }, }, })
- Improvement to remult admin + support for bearer token in admin
- Fix to recursive sql expression
- Added support for backend method without a transaction using
transactional:false - Fixed live query, to update the subscribers asynchronously
- #474 When using knex, an id column with auto-increment that is not named id in the db gave an error
- Changed RelationOptions to be an extendable interface and not a type
- Added
requesttoremult.contextthat'll be available through the request lifecycle - to access it please extend the RemultContext type as followsimport type express from 'express' declare module 'remult' { export interface RemultContext { request?: express.Request } }
Typescript version 5.4 included many changes that cause unknown & any to behave differently breaking existing code for some project.
In this version we reviewed the external api and made sure that it matches TS 5.4 while still supporting older version of TS (4.6)
Theses change are likely to cause build errors in existing projects, but in most cases these errors represent potential bugs that should be addressed. Here's the list of significant changes:
findFirst,findOneandfindIdcan returnundefinedwhen the row is not found, if you're sure that the row exists, add a!after it, for example:let p = await repo(Person).findId(7) // p will be Person | undefined in the new version let q = (await repo(Person).findId(7))! // p will be Person
- Decorators that use entity, now require to define the entity in the generic definition.
Previously you could have the following code:
Now, that code will return an error that
@Fields.string({ validate: task => task.title.length > 2 }) title=''
titleis not a member ofunknown. To fix that add theEntitygeneric definition:@Fields.string<Task>({ validate: task => task.title.length > 2 title = '' })
FieldMetadata.keywas changed fromstringtokeyof entityTypemaking it easier to traverse the object.errorinEntityRef,FieldRefandControllerRefcan beundefinedwhen there is no error- Change
= anyto= unknownin most generic definitions
- Fixes and improvements to the admin panel
- fixed issue with prevent default and insert
- Fixed a bug with startsWith and endsWith worked like contains
- Added support for $not, $startsWith & $endsWith
- Fixed issue with recursive sqlExpression call for field
- Fixed an issue with sqlExpression without aliases - now remult automatically adds an alias in select, but not in order by or where.
- Added support for DuckDB
- Many improvements to
remult-admin - HUGE thanks to jycouet & celikovic for their amazing work on
remult-admin
- docs - svelte tuto improvement by @jycouet in #458
- Fix #460
- Fixed typescript error with KnexDataProvider
- fixed issue where migrate didn't work in commonjs
- Bump mysql2 from 3.9.7 to 3.9.8 by @dependabot in #445
- fix auth.ts import for Next.js tutorial by @LegitPanda in #446
- Update example-apps.md by @ikx94 in #447
- Bump @azure/msal-node and tedious by @dependabot in #450
- Bump braces from 3.0.2 to 3.0.3 by @dependabot in #449
- Bump braces from 3.0.2 to 3.0.3 in /examples/angular-todo-fastify by @dependabot in #451
- docs: improve swagger-ui integration guide page with nextjs specific info by @kckusal in #448
- @LegitPanda made their first contribution in #446
- @ikx94 made their first contribution in #447
- @kckusal made their first contribution in #448
- fix validators with args type-check error in ts 5.4
- Fixed an issue with stack overflow when calling
withRemultfrom withingetUser- relevant to next auth -sessionhook - The "static"
withRemultwill now use the dataProvider provided in the remultServer options by default - The "static"
withRemultnow supports promise of data provider etc... - Changed json storage to save json in a non formatted way (condensed), and added a
formattedoption to control it. By default JsonFile storage isformatted - Improved error handling in request lifecycle
- Fixed error in sqlite with reserved column names such as order etc...
- #427 - Changed the retry on error 500, to 4 times instead of 50 or infinite that was before.
- Potential breaking change #426 - Fixed to not trigger all relations to one load before saving and around read write json
- Fixed error when id was not found in ArrayEntityDataProvider to include the entity name
- Fixed filterToRaw to use the current database
wrapIdentifierwhen none is provided. - Fixed endless retry on error 500 - now it'll retry 4 times 500ms apart.
- Fixed error when sql expression sometimes translated wrongfully to a recursion error
- Added support for Turso db
- Fix order by error with multiple id columns
- Added support for
sqlite3that runs on stackblitz - Fixed issues with knex when id columns are being updated
- Fixed issues with mongo when id columns are being updated
- Fixed issue with id being empty in some cases in the saved hook
- Added
describeEntityanddescribeBackendMethodsfor better decorator-less support
- Minor fix to async_hooks fallback for running on stackblitz
- Breaking change - changed the api of
updateManyto receive asetoption, instead of second parameter for the set - Fixed primary key was not created for entities that had more than one id column using knex or postgres
- Fixed issue where
dbNamesOfin entitysqlExpressiondid not work
getValueListnow supports@Fields.literal&@Fields.enum(on top ofValueListType)
- Fixed issue with delete on Hono with session middleware
- Fixed an issue with admin not working with Hono@4.2
- Added support for SolidStart https://remult.dev/tutorials/solid-start/
- Fixed issue where 404 return an error - forbidden instead of not found
- Fixed an issue where
preventDefaultindeletingdid not work
- Added support for migrations. See Migrations.
- Added an
errorhook toRemultServerOptionsthat is called whenever there is an error in the API lifecycle. See RemultServerOptions. - Added
ForbiddenErrorto the API, you can throw it anywhere in the request lifecycle to display a forbidden 401 error. - Added
@Fields.literaland@Fields.enum. - Added support for
better-sqlite3without knex, see Connection a Database. - Added support for
bun:sqlite#387. - Added a generic implementation for
sqlitethat can be easily extended to any provider. - Added
apiPreprocessFilterandbackendPreprocessFilter, see access control. - Added a way to analyze filter and query it -
Filter.getPreciseValues, which returns aFilterPreciseValuesobject containing the precise values for each property. see access control. - Added an exception when calling
updateManyordeleteManywithout a filter - to protect against accidental deleting/updating all data. - Added updateMany and deleteMany to OpenAPI (swagger) & graphql
- Added validation for
@Fields.number&Fields.integerthat the value is a valid number. - Added "basic" supports for environments where async hooks doesn't work well - mostly for web based dev machines.
- Improved the API of
rawFilterso it can now return the SQL where to be added to the command. see Leveraging Custom Filters for Enhanced Data Filtering KnexDataProvidernow supports allexecuteandcreateCommandand can be used with anySqlDatabasefunctionality.- Changed postgres schema builder to use
timestamptzinstead oftimestamp. - Changed the default storage of
@Fields.objecttotext(varchar max) instead of string 255 inknexandsqlite.
- Added or rewrote the following articles:
- Migrations
- Access Control
- Custom/SQL Filter
- Direct Database Access
- Extensibility
- Lots of
jsdocsimprovements
- Fixed an issue with entity ids that included date.
- Fixed an issue with
repo(Entity,dataProvider)- where saving wasn't fired because of wrongisProxyinference. - Fixed an issue with chaining of validators that in some cases caused a validator to be overwritten.
- Fixed
ValueConvertersNumberfromInputhandle 0 as a valid value.
- Changed the signature of
updateManyanddeleteManyto require awhereparameter:repo(Task).delete({ where: { completed: true } }). - Changed the signature of
getDbto receiveDataProvideras a parameter instead ofRemult. - Changed the POST REST API queries to include the filter under the
wherekey in the body - previously, it included the filter as the body itself.
- Fixed issue with typing when
skipLibCheck: false
- Fixed typing issue with validators and typescript 5.4
- Added
deleteManyandupdateMany - When
insertis called in the front-end with an array of items, a single POST call is made to the server - Renamed
addParameterAndReturnSqlTokentoparam.addParameterAndReturnSqlTokenwill be deprecated in future versions - Default number storage in knex, previously was decimal(8,2) now, decimal(18,2)
- Fixed issue where exception throws in
initRequestorgetUsercaused server to crash, instead of return a bad request error - Changed required to allow 0 as a value - so only null, undefined and empty strings are considered invalid for a required field
- Fixed an issue where
backendPrefilterwas not applied to id basedupdate,saveordeletein the backend
- Added support for
orderByNullsFirstinPostgresDataProviderto change the default postgres behavior where nulls are last - Added support for
tableNameoption argument fordbNamesOfthat'll add the table name to each field Before:Now:const orders = await dbNamesOf(Order) return `(select count(*) from ${orders} where ${orders}.${orders.id}=1)
const orders = await dbNamesOf(Order, { tableNames:true }) return `(select count(*) from ${orders} where ${orders.id}=1)
- improved dbNamesOf of to use by default the wrapIdentifier of the current data provider if no wrap identifier was provided
- Added support for using dbNamesOf in an sql expression for that same entity
- Improved performance of dbNamesOf
- Added support for Hono web framework
- Improved support for Mono repo scenario #355
- Added
withRemultto next js page router - Fixed custom message to some validators (in etc...)
- Improved support for union string fields
- Added
adminoption to servers, enabling the/api/adminroute with a built in entity explorer - Fixed multiple issues with GraphQL and relations
- Improved support for esm/cjs in same process scenario
- Enabled json storage type for mysql & mysql2 knex adapters
- Fixed issue in case of missing
reflect-metadata - Added a recommended way to use remult in
sveltekitusingapi/[...remult]/+server.tsroute instead of a hook - Added ArrayEntityDataProvider to the external api
- Fixed issue where a new row that was saved, changed again and saved again - provide wrong
isNew:truevalue for field validate
- Fixed #320, dbReadonly columns are not created in the db
- Fix the
defaultMessageof validators - Added Validators.minLength
- Fixed issue where
defaultGetLimitcaused issues with include queries
- Added
requiredas aFieldOption - Added validation for
maxLengthinStringFieldOptions - Added the following validators to the
Validatorsclass:- regex
- url
- in
- notNull
- enum
- relationExists,
- maxLength
- Added support for return value for validations - true || undefined are valid, string will provide the message. For example:
@Fields.string({ validate:(task)=> task.title.length > 5 || "too short" })
- Added the
valueValidatorhelper function:@Fields.string({ validate: valueValidator(value => value.length > 5) })
- Added helper functions to create validators,
createValueValidator,createValueValidatorWithArgs,createValidator&createValidatorWithArgs - Changed signature of
FieldOptions.validatethe receiveValidateFieldEventobject as the second parameter instead ofFieldRef - Updated Signature of
requiredanduniquebased on api change - Adjusted the
uniquevalidator to only run on the backend
- Added Origin Private File System Storage to store entities in the front end
const db = new JsonDataProvider(new JsonEntityOpfsStorage()) repo(Task, db) .find() .then((tasks) => console.table(tasks))
- Added
SqlJsDataProviderfor use with front end sqlite implementation sql.jsconst db = new SqlDatabase( new SqlJsDataProvider(initSqlJs().then((x) => new x.Database())), ) repo(Task, db) .find() .then((tasks) => console.table(tasks))
- Added
clonetoEntityRef - Fixed issue where
findOnedidn't work - Fixed issue where exception
XXX is not a known entity, did you forget to set @Entity() or did you forget to add the '@' before the call to Entity?was thrown in cases where multiple instances of remult were in memory - Issue #314 resolved by @itamardavidyan in #315
- Improved JsonDataProvider to support promise for load and save, useful in all sorts of cases
- Fixed issue with ESM on NodeJS - Module '"remult/postgres"' has no exported member 'createPostgresDataProvider'.
- BREAKING CHANGE: PostgresDataProvider: Column & table names are now quoted (e.g.,
"firstName") to enforce specific casing in PostgreSQL.- To revert to the old (version < 0.24) case-insensitive identifiers, set
caseInsensitiveIdentifiers: truewhen usingcreatePostgresDataProvider.
- To revert to the old (version < 0.24) case-insensitive identifiers, set
- ESM support for NodeJS
- Support for nuxt Fullstack framework
- Support for the
sqlExpressionfield option in entities using theknexdata provider. schemaparameter toPostgresDataProvider&createPostgresDataProvider.findOnemethod inRepositorywith a unifiedoptionsparameter for simplicity.withRemultAsyncfunction inremultExpressfor contexts outside the normal request lifecycle.withRemultfunction for obtaining a valid remult context in server scenarios.- Inclusion of
EntityMetadatainCaptionTransformer.transformCaptionmethod. dbNameattribute inEntityMetadata&FieldMetadata.wrapIdentifieroptional parameter indbNamesOffunction.dbNamesas an optional parameter in thefilterToRawmethod ofSqlDatabase.wrapIdentifiermethod inSqlDatabasefor wrapping identifiers before sending to the database.
getDbNamemethod inEntityMetadata&FieldMetadata(to be removed in future versions).
runmethod fromRemult.
withRemultPromisetowithRemultAsyncinRemultServer.
- Fixed issue where delete by id on the backend, didn't go through the deleting hook
- Fixed
toOnerelation filter null for non nullable fields to work - Fixed
toOnerelation filter on $id:0 failed to work - Fixed wrongful loading of
toManyrelation on api withdefaultIncluded
- Fixed Live query to also work in init api #306
- Added support for notContains filter option
- Fixed case insensitivity in contains for mongo db
-
Added Relations - see Relations
-
Added LifecycleEvent info for saving,saved,deleting,deleted - see Entity Lifecycle Hooks
-
Saving, Saved, Deleting, Deleted all run only on the backend now
-
include in api now supports expressions that use the current row
- Breaking change - instead of
if(repo.fields.name.includedInApi)you now needif(repo.fields.name.includedInApi(instance))
- Breaking change - instead of
-
Changed the way an entity id is defined see Entity id's doc Example:
@Entity<OrderDetails>("orderDetails", { id: { orderId: true, productCode: true } })
-
added repo function which is A convenient shortcut function to quickly obtain a repository for a specific entity type in Remult.
await repo(Task).find()
-
Added support for (Hapi api server)[https://hapi.dev/]
-
Fixed exception with toRawFilter
-
Fixed json db to support db names
-
Fixed issue with sort result after live query
-
Fix issue with compound id on middleware based servers
-
Added with remult for sveltekit for usage before the remult hook
-
Fixed issue with requireId not respecting in statement #290
-
findIdwas changed to no longer use cache by default
- #297 - Crash on ensure schema failure
- Improved support for Mongo
ObjectIdfield type #295
- Fixed issue with
repo.validatewithout specifying fields
- Fixed issue with Entity Backend Method and fields with allow api false #255
- Fixed an issue with rest call that had both and & or
- Fixed an issue regarding the usage of ManyToOne fields as part of the id
- Fixed max stack reached in case of reference to self
- Improved graphql one to many relations
- Fixed live-query issue with complex filters
- Refactored tests to use vitest, and latest typescript version
- Fixed issue with postgres schema builder
- Fixed schema build to support table name with schema name
- Cleaned up code and removed angular dependency
- Implemented $contains for mongo
- Implemented contains for graphql
- Fixed issue #220
- Fixed an issue where an update with only a few fields, would update all other fields to their default values.
- Fixed an issue with the many-to-one relation where the 'many' table did not store the ID as a
stringin cases where the 'one' table's ID column was not an integer - Added tests for MariaDB and fixed issues
- Fixed #216 wrong date type saved on update
- Fixed issue #215 support for mongo without transactions
- Added
ToJsonandFromJsonmethods the theRepositoryobject. These are extremely useful in the context of SSR (next etc...) where you need to send plain json over the wire, but still want to have dates and other cool stuff in your app - Fixed an issue with the many-to-one relation where the 'many' table did not store the ID as an 'integer' in cases where the 'one' table's ID column was an integer
- Fixed issue where using displayValue or validate on a spread object, marked it as new, and always triggered a post call
- Added Remult.run
- isBackend will return true or false based on dataProvider.isProxy equal false or runningOnServer member
- Backend method will call backend based on isBackend method,
- Replaced deprecated cuid with
paralleldrive/cuid2 - Fixed an issue where when
getDbwas called without aremultparameter, it wouldn't use the default remult - Fixed liveQuery's apply changes to also support state that it's initial value is undefined.
- Typescript 5 style decorators are now supported in development, but to deploy you still need
experimentalDecorators.- Also, the decorators now do type checking, so if you put @Fields.string() on a number, it'll give you an error
- And - no longer need for the Generics in the decorators setting.
@Entity<Task>(...)is now@Entity(...)@Fields.string<Task>(...)is now@Fields.string(...)
- Why didn't we implement typescript 5 decorators in runtime? the implementation for that is not yet fully supported with tools such as esbuild etc... so implementing it is trying to hit a moving target.
At this time we recommend using
experimentalDecorator:falsefor development, to get the typing, butexperimentalDecorator:truefor deploying and functionality.
- Added 404 on missing route for next app router - issue #211
- Fixed an issue where live query would not unsubscribe automatically to a query that failed to fetch.
- Fixed an issue where, when using the cache with findId or findFirst, and requesting to load fields, if the cache contained a row without those fields, it would return the cached row without those fields.
- Fixed an issue where in a filter that contained multiple instances of the same custom filter, with an 'and' condition did not work correctly
- Graphql Mutations now display validation errors in the graphql way
- Fixed issue with
Field.Jsonfails to insert in case of array
- Major improvements to the GraphQL support:
- Better Query support
- Mutation Support
- Improved compatibility to standard GraphQL structures
- Breaking Change Note that the GraphQL Schema has changed, and client code needs to be adjusted. If you run into any issues, please open a github issue or reach out to us on discord.
- Improved SQL Log to Console see PR #204,
- to jycouet for his first two pull requests, and his help forming the GraphQL Schema according to best practices.
- to talmosko for his help and improvements for the tutorials and documentation.
- Fixed an issue when apiPrefilter was an arrow function, it did not affect get of a specific resource
- fixed issue #200 transactions on mongo db
- fixed issue with columns in postgres with casing in the db - sa
createdAt - Issue #196 fixed - load options in live query
- Fixed issue with
apiReadAllowed:falsewhenapiUpdateAllowedis set to undefined
- Improved Open API Support
- createdAt & updatedAt are by default
allowApiUpdatefalse - Added
apiPrefixtoBackendMethodoptionsto allow more control over backend method routes. #189
- Improved support for compound id entity
- Minor bug fixes
- Improved memory usage
- Added
handlemethod for using remult innext.jsapi handlers. see using remult in a next.js api handler - Added
remult-sveltekitsee Add remult to your project - Added support for
next.jsApp Router. See Add remult to your project
Repository- Added a
validatemethod that returns anErrorInfoobject if invalid. - Added a
fieldsmember that can be used to access the metadata of specific fields, for example:repo.fields.title.caption //or repo.fields.title.inputType
- The
insert,validate,create,saveandupdatevalue will now runfromJsonandtoJsonfor field values that do not match their type - for consistent behavior with theapi
- Added a
FieldMetadata- Added
apiUpdateAllowedto query ifupdateis allowed for this field - Added
includedInApito query of this field would be returned from the backend as part of the api - Added
displayValuethat can be used to achieve a consistent way a field is displayed. - Added
toInputandfromInputmethods that'll help with translating values from and to inputs.
- Added
getIdmethod added toIdMetadatato enable extracting the id from immutable objects, this is mainly useful for entities where theidcolumn is not calledid:)repo.metadata.idMetadata.getId(task)
- In
EntityMetadatatheapiUpdateAllowed,apiDeleteAllowedandapiInsertAllowedthat previously were boolean fields, are now methods that accepts item and return true or false. This is useful for cases where the apiAllowed rules refer to the specific values of an entity.// Previously if (repo.metadata.apiDeleteAllowed) { } // Now if (repo.metadata.apiDeleteAllowed(task)) { }
- The
validatemethod inEntityRefandControllerRefthat previously returned true if valid, now returnsundefinedif valid andErrorInfoif invalid FieldMetadata'sValueConverterfield's members are now mandatory and no longer optional - it's expected that they'll be implemented