All notable changes to this project will be documented in this file.
- 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
wrapIdentifier
when 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
sqlite3
that 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
describeEntity
anddescribeBackendMethods
for better decorator-less support
- Minor fix to async_hooks fallback for running on stackblitz
- Breaking change - changed the api of
updateMany
to receive aset
option, 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
dbNamesOf
in entitysqlExpression
did not work
getValueList
now 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
preventDefault
indeleting
did not work
- Added support for migrations. See Migrations.
- Added an
error
hook toRemultServerOptions
that is called whenever there is an error in the API lifecycle. See RemultServerOptions. - Added
ForbiddenError
to the API, you can throw it anywhere in the request lifecycle to display a forbidden 401 error. - Added
@Fields.literal
and@Fields.enum
. - Added support for
better-sqlite3
without knex, see Connection a Database. - Added support for
bun:sqlite
#387. - Added a generic implementation for
sqlite
that can be easily extended to any provider. - Added
apiPreprocessFilter
andbackendPreprocessFilter
, see access control. - Added a way to analyze filter and query it -
Filter.getPreciseValues
, which returns aFilterPreciseValues
object containing the precise values for each property. see access control. - Added an exception when calling
updateMany
ordeleteMany
without a filter - to protect against accidental deleting/updating all data. - Added updateMany and deleteMany to OpenAPI (swagger) & graphql
- Added validation for
@Fields.number
&Fields.integer
that 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
rawFilter
so it can now return the SQL where to be added to the command. see Leveraging Custom Filters for Enhanced Data Filtering KnexDataProvider
now supports allexecute
andcreateCommand
and can be used with anySqlDatabase
functionality.- Changed postgres schema builder to use
timestamptz
instead oftimestamp
. - Changed the default storage of
@Fields.object
totext
(varchar max) instead of string 255 inknex
andsqlite
.
- Added or rewrote the following articles:
- Migrations
- Access Control
- Custom/SQL Filter
- Direct Database Access
- Extensibility
- Lots of
jsdocs
improvements
- Fixed an issue with entity ids that included date.
- Fixed an issue with
repo(Entity,dataProvider)
- where saving wasn't fired because of wrongisProxy
inference. - Fixed an issue with chaining of validators that in some cases caused a validator to be overwritten.
- Fixed
ValueConverters
Number
fromInput
handle 0 as a valid value.
- Changed the signature of
updateMany
anddeleteMany
to require awhere
parameter:repo(Task).delete({ where: { completed: true } })
. - Changed the signature of
getDb
to receiveDataProvider
as a parameter instead ofRemult
. - Changed the POST REST API queries to include the filter under the
where
key 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
deleteMany
andupdateMany
- When
insert
is called in the front-end with an array of items, a single POST call is made to the server - Renamed
addParameterAndReturnSqlToken
toparam
.addParameterAndReturnSqlToken
will 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
initRequest
orgetUser
caused 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
backendPrefilter
was not applied to id basedupdate
,save
ordelete
in the backend
- Added support for
orderByNullsFirst
inPostgresDataProvider
to change the default postgres behavior where nulls are last - Added support for
tableName
option argument fordbNamesOf
that'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
withRemult
to next js page router - Fixed custom message to some validators (in etc...)
- Improved support for union string fields
- Added
admin
option to servers, enabling the/api/admin
route 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
sveltekit
usingapi/[...remult]/+server.ts
route 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:true
value for field validate
- Fixed #320, dbReadonly columns are not created in the db
- Fix the
defaultMessage
of validators - Added Validators.minLength
- Fixed issue where
defaultGetLimit
caused issues with include queries
- Added
required
as aFieldOption
- Added validation for
maxLength
inStringFieldOptions
- Added the following validators to the
Validators
class:- 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
valueValidator
helper function:@Fields.string({ validate: valueValidator(value => value.length > 5) })
- Added helper functions to create validators,
createValueValidator
,createValueValidatorWithArgs
,createValidator
&createValidatorWithArgs
- Changed signature of
FieldOptions
.validate
the receiveValidateFieldEvent
object as the second parameter instead ofFieldRef
- Updated Signature of
required
andunique
based on api change - Adjusted the
unique
validator 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
SqlJsDataProvider
for 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
clone
toEntityRef
- Fixed issue where
findOne
didn'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: true
when 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
sqlExpression
field option in entities using theknex
data provider. schema
parameter toPostgresDataProvider
&createPostgresDataProvider
.findOne
method inRepository
with a unifiedoptions
parameter for simplicity.withRemultAsync
function inremultExpress
for contexts outside the normal request lifecycle.withRemult
function for obtaining a valid remult context in server scenarios.- Inclusion of
EntityMetadata
inCaptionTransformer.transformCaption
method. dbName
attribute inEntityMetadata
&FieldMetadata
.wrapIdentifier
optional parameter indbNamesOf
function.dbNames
as an optional parameter in thefilterToRaw
method ofSqlDatabase
.wrapIdentifier
method inSqlDatabase
for wrapping identifiers before sending to the database.
getDbName
method inEntityMetadata
&FieldMetadata
(to be removed in future versions).
run
method fromRemult
.
withRemultPromise
towithRemultAsync
inRemultServer
.
- Fixed issue where delete by id on the backend, didn't go through the deleting hook
- Fixed
toOne
relation filter null for non nullable fields to work - Fixed
toOne
relation filter on $id:0 failed to work - Fixed wrongful loading of
toMany
relation 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
-
findId
was changed to no longer use cache by default
- #297 - Crash on ensure schema failure
- Improved support for Mongo
ObjectId
field type #295
- Fixed issue with
repo.validate
without 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
string
in 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
ToJson
andFromJson
methods the theRepository
object. 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
getDb
was called without aremult
parameter, 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:false
for development, to get the typing, butexperimentalDecorator:true
for 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.Json
fails 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:false
whenapiUpdateAllowed
is set to undefined
- Improved Open API Support
- createdAt & updatedAt are by default
allowApiUpdate
false - Added
apiPrefix
toBackendMethod
options
to allow more control over backend method routes. #189
- Improved support for compound id entity
- Minor bug fixes
- Improved memory usage
- Added
handle
method for using remult innext.js
api handlers. see using remult in a next.js api handler - Added
remult-sveltekit
see Add remult to your project - Added support for
next.js
App Router. See Add remult to your project
Repository
- Added a
validate
method that returns anErrorInfo
object if invalid. - Added a
fields
member 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
,save
andupdate
value will now runfromJson
andtoJson
for field values that do not match their type - for consistent behavior with theapi
- Added a
FieldMetadata
- Added
apiUpdateAllowed
to query ifupdate
is allowed for this field - Added
includedInApi
to query of this field would be returned from the backend as part of the api - Added
displayValue
that can be used to achieve a consistent way a field is displayed. - Added
toInput
andfromInput
methods that'll help with translating values from and to inputs.
- Added
getId
method added toIdMetadata
to enable extracting the id from immutable objects, this is mainly useful for entities where theid
column is not calledid
:)repo.metadata.idMetadata.getId(task)
- In
EntityMetadata
theapiUpdateAllowed
,apiDeleteAllowed
andapiInsertAllowed
that 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
validate
method inEntityRef
andControllerRef
that previously returned true if valid, now returnsundefined
if valid andErrorInfo
if invalid FieldMetadata
'sValueConverter
field's members are now mandatory and no longer optional - it's expected that they'll be implemented