@livequery/mongoose
v2.0.148
Published
Mongoose datasource mapping for @livequery ecosystem
Readme
@livequery/mongoose
Mongoose datasource adapter for the @livequery ecosystem.
This package maps Livequery requests to Mongoose/MongoDB operations. It now supports both:
- The legacy datasource API:
init(config, routes)andquery(req, options). - The
@livequery/corehandler API:init(routes)andhandle(ctx).
Installation
bun add @livequery/mongoose mongoose bson rxjsFor local development in this workspace, @livequery/core is installed as a dev dependency from file:../core.
Exports
export * from './MongooseDatasource.js'
export * from './DataChangePayload.js'Classes And Types
MongooseDatasource
Main datasource adapter.
It extends Subject<WebsocketSyncPayload<LivequeryBaseEntity>> and implements:
- The legacy local
LivequeryDatasource<MongooseDatasourceConfig, RouteOptions>type. - The
@livequery/coreLivequeryDatasource<RouteOptions>type, which is also aLivequeryHandler.
Supported methods:
constructor(config?): optionally receives database connections up front for the core API style.init(config, routes): legacy initialization.init(routes): core-style initialization.query(req, options): executes one Livequery request against a Mongoose model.handle(ctx): readsctx.livequery, maps it to the legacy request shape, runsquery, and writesctx.response.
MongooseDatasourceConfig
type MongooseDatasourceConfig = {
connections: { [key: string]: Connection }
databases: string[]
}connections is a map of Mongoose connection names. If route options do not specify a connection, the datasource uses the first configured connection name, then falls back to "default".
databases is kept for compatibility with existing Livequery datasource configuration.
RouteOptions<T>
type RouteOptions<T = any> = {
realtime?: boolean
schema: Schema<T>
db?: string | ((req: LivequeryRequest) => Promise<string> | string)
connection?: string | ((req: LivequeryRequest) => Promise<string> | string)
}schema is required and must define schema.options.collection, because the adapter uses it as the Mongoose collection/model name.
db and connection can be static strings or functions. Functions receive the normalized Livequery request.
DataChangePayload<T>
Type for realtime/change payloads.
type DataChangePayload<T = any> = {
id: string
type: 'added' | 'modified' | 'removed'
data: T
refs: Array<{ ref: string, old_ref: string }>
new_doc: T
}Query Behavior
MongooseDatasource.query() supports:
get: collection and document reads.post: inserts one document by mergingreq.keysandreq.body.put: updates one document by route keys.patch: updates one document by route keys.delete: deletes one document by route keys.
For collection reads, MongoQuery builds an aggregation pipeline with:
- filters from
req.optionsandreq.keys - cursor pagination through
:after,:before,:around :limitclamped from1to100- sorting through
field:sort - text search through
:search - summary aggregations through
::summaryName
For document reads, req.keys.id is converted to Mongo _id.
ObjectId fields in schema paths are normalized from valid string ids to ObjectId before querying or writing.
Usage With @livequery/core
Use this style when your request pipeline creates a LivequeryContext and calls handlers.
import mongoose, { Schema } from 'mongoose'
import { LivequeryRequestParser, type LivequeryContext } from '@livequery/core'
import { MongooseDatasource } from '@livequery/mongoose'
type Product = {
name: string
price: number
}
const connection = await mongoose.createConnection(process.env.MONGO_URL!).asPromise()
const productSchema = new Schema<Product>(
{
name: String,
price: Number,
},
{ collection: 'products' }
)
const datasource = new MongooseDatasource({
connections: { default: connection },
databases: ['main'],
})
await datasource.init([
{
method: 'GET',
path: '/livequery/products',
schema: productSchema,
},
{
method: 'GET',
path: '/livequery/products/:id',
schema: productSchema,
},
])
const ctx: LivequeryContext = {
request: {
method: 'GET',
path: '/livequery/products',
ref: '/livequery/products',
params: {},
query: { ':limit': 20, 'price:sort': 'desc' },
headers: new Map(),
},
}
new LivequeryRequestParser().handle(ctx)
await datasource.handle(ctx)
console.log(ctx.response)Core-style routes are registered by METHOD path. The datasource also keeps a path-only fallback for legacy integrations.
Legacy Usage
Use this style with older adapters that call query() directly.
import mongoose, { Schema } from 'mongoose'
import { MongooseDatasource } from '@livequery/mongoose'
const connection = await mongoose.createConnection(process.env.MONGO_URL!).asPromise()
const productSchema = new Schema(
{
name: String,
price: Number,
},
{ collection: 'products' }
)
const datasource = new MongooseDatasource()
await datasource.init(
{
connections: { default: connection },
databases: ['main'],
},
[
{
method: 'GET',
path: '/livequery/products',
options: {
schema: productSchema,
},
},
]
)
const response = await datasource.query(
{
method: 'get',
ref: 'products',
is_collection: true,
collection_ref: 'products',
schema_collection_ref: 'products',
keys: {},
options: { ':limit': 10 },
},
{
schema: productSchema,
}
)
console.log(response.items)Route Options With Dynamic Connection Or Database
await datasource.init([
{
method: 'GET',
path: '/tenant/:tenantId/products',
schema: productSchema,
connection: req => req.keys.tenantId,
db: req => `tenant_${req.keys.tenantId}`,
},
])Build
npm run buildThere is no test suite yet. npm test is still the package placeholder script.
