Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: expose orama API #161

Merged
merged 3 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ npm install fastify-orama
## Usage

This plugin adds the `orama` decorator to your Fastify application.
The decorator exposes all the methods that [the Orama class exposes](https://docs.oramasearch.com/usage/create).

The `options` object is passed directly to the `Orama.create` constructor,
so it supports [all the options that Orama supports](https://docs.oramasearch.com/usage/create).
Expand Down Expand Up @@ -56,9 +57,9 @@ This plugin supports data persistence out of the box.
You need to pass the `persistence` option to the plugin registration!

This plugin uses [`@oramasearch/plugin-data-persistence`](https://docs.oramasearch.com/plugins/plugin-data-persistence)
under the hood to allow users to `load` or `save` database instances.
under the hood to allow users to `load` or `persist` database instances.

Turning on the `persistence` option will add the `fastify.orama.save()` method to your Fastify application.
Turning on the `persistence` option will add the `fastify.orama.persist()` method to your Fastify application.
You must call this method to save the database instance to the persistence layer, otherwise your data will be lost.

### PersistenceInFile
Expand Down Expand Up @@ -103,8 +104,8 @@ app.post('/quotes', async function (req, reply) {
return { success: true }
})

app.addHook('onClose', async function save (app) {
const path = await app.orama.save()
app.addHook('onClose', async function persist (app) {
const path = await app.orama.persist()
app.log.info(`Database saved to ${path}`)
})

Expand Down Expand Up @@ -137,7 +138,7 @@ await appOne.orama.insert({
author: 'Mateo Nunez'
})

const inMemoryDb = await appOne.orama.save()
const inMemoryDb = await appOne.orama.persist()

// Close the Fastify application
await appOne.close()
Expand Down Expand Up @@ -169,7 +170,7 @@ const customPersistance = {

persist: async function persist (db) {
// Persist the database instance to the persistence layer
// Whatever this method returns will be passed to the `app.orama.save()` method
// Whatever this method returns will be passed to the `app.orama.persist()` method
}

await fastify.register(fastifyOrama, {
Expand All @@ -178,6 +179,29 @@ await fastify.register(fastifyOrama, {
})
```

## Orama Internals

Do you need to access the [Orama internals utilities](https://docs.oramasearch.com/internals/utilities)?
No problem!

```js
import { fastifyOrama, oramaInternals } from 'fastify-orama'

const app = Fastify()

// The database must exists to load it in your Fastify application
app.register(fastifyOrama, {
schema: {
quote: "string",
author: "string"
}
})

app.get('/genId', async function handler (req, reply) {
return { newId: await oramaInternals.uniqueId() }
})
```

## License

fastifyOrama is licensed under the [MIT](LICENSE) license.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ declare module 'fastify' {
orama: {
insert: (document: Document) => Promise<string>,
search: (params: SearchParams) => Promise<Results>,
save?: () => Promise<any>,
persist?: () => Promise<any>,
}
}
}
Expand Down
26 changes: 19 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import fp from 'fastify-plugin'
import { create, insert, search } from '@orama/orama' // todo we are limiting the api to the server side
import * as Orama from '@orama/orama'

import PersistenceInMemory from './lib/persistence/in-memory.js'
import PersistenceInFile from './lib/persistence/in-file.js'

const SKIP_METHODS = [
'create'
]

const oramaInternals = Orama.internals

async function fastifyOrama (fastify, options) {
if (fastify.orama) {
throw new Error('fastify-orama is already registered')
Expand All @@ -17,15 +23,20 @@ async function fastifyOrama (fastify, options) {
let db

const oramaApi = {
insert: (...args) => insert(db, ...args),
search: (...args) => search(db, ...args),
save: undefined
persist: undefined // custom
}

const oramaProxyKeys = Object.keys(Orama)
.filter((key) => typeof Orama[key] === 'function' && !SKIP_METHODS.includes(key))

for (const key of oramaProxyKeys) {
oramaApi[key] = (...args) => Orama[key](db, ...args)
}

if (persistence) {
db = await persistence.restore()

oramaApi.save = /* async */ function save () {
oramaApi.persist = /* async */ function persist () {
return persistence.persist(db)
}
}
Expand All @@ -35,7 +46,7 @@ async function fastifyOrama (fastify, options) {
throw new Error('You must provide a schema to create a new database')
}

db = await create(oramaOptions)
db = await Orama.create(oramaOptions)
}

fastify.decorate('orama', oramaApi)
Expand All @@ -49,5 +60,6 @@ export default fp(fastifyOrama, {
export {
fastifyOrama,
PersistenceInMemory,
PersistenceInFile
PersistenceInFile,
oramaInternals
}
2 changes: 1 addition & 1 deletion test/fastify-orama.test.js → test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ it('Should register correctly fastifyOrama plugin', async () => {
})

ok(fastify.orama)
ok(fastify.orama.save === undefined)
ok(fastify.orama.persist === undefined)
})

it('Should insert and retrieve data using Orama', async () => {
Expand Down
109 changes: 109 additions & 0 deletions test/orama-proxy.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
'use strict'

import { it } from 'node:test'
import { ok, strictEqual } from 'node:assert'
import Fastify from 'fastify'
import { fastifyOrama, oramaInternals } from '../index.js'

it('Should expose all the Orama APIs', async () => {
const fastify = Fastify()

await fastify.register(fastifyOrama, {
id: 'my-orama-instance',
schema: {
title: 'string',
director: 'string',
plot: 'string',
year: 'number',
isFavorite: 'boolean'
}
})

const harryPotterId = await fastify.orama.insert({
title: 'Harry Potter and the Philosopher\'s Stone',
director: 'Chris Columbus',
plot: 'Harry Potter, an eleven-year-old orphan, discovers that he is a wizard and is invited to study at Hogwarts. Even as he escapes a dreary life and enters a world of magic, he finds trouble awaiting him.',
year: 2001,
isFavorite: false
})
ok(harryPotterId, 'the id is returned')

const docs = [
{
title: 'The prestige',
director: 'Christopher Nolan',
plot: 'Two friends and fellow magicians become bitter enemies after a sudden tragedy. As they devote themselves to this rivalry, they make sacrifices that bring them fame but with terrible consequences.',
year: 2006,
isFavorite: true
},
{
title: 'Big Fish',
director: 'Tim Burton',
plot: 'Will Bloom returns home to care for his dying father, who had a penchant for telling unbelievable stories. After he passes away, Will tries to find out if his tales were really true.',
year: 2004,
isFavorite: true
}
]

const docIds = await fastify.orama.insertMultiple(docs, 500)
ok(docIds.length === 2, 'the ids are returned')

const thePrestige = await fastify.orama.getByID(docIds[0])
strictEqual(thePrestige.title, 'The prestige')

const docNumber = await fastify.orama.count()
strictEqual(docNumber, 3)

const del = await fastify.orama.remove(harryPotterId)
ok(del, 'the document was deleted')

const docNumberUpdated = await fastify.orama.count()
strictEqual(docNumberUpdated, 2)

const delMultiple = await fastify.orama.removeMultiple(docIds, 500)
strictEqual(delMultiple, 2, 'the documents were deleted')

const docEmpty = await fastify.orama.count()
strictEqual(docEmpty, 0)
})

it('Should not expose some Orama APIs', async () => {
const fastify = Fastify()

await fastify.register(fastifyOrama, {
id: 'my-orama-instance',
schema: {
title: 'string',
director: 'string',
plot: 'string',
year: 'number',
isFavorite: 'boolean'
}
})

ok(fastify.orama.create === undefined)
})

it('Should not expose Orama internals', async () => {
const fastify = Fastify()

fastify.register(fastifyOrama, {
id: 'my-orama-instance',
schema: {
title: 'string',
director: 'string',
plot: 'string',
year: 'number',
isFavorite: 'boolean'
}
})

fastify.get('/genId', async function handler () {
return { newId: await oramaInternals.uniqueId() }
})

const response = await fastify.inject('/genId')
strictEqual(response.statusCode, 200)
ok(response.json().newId, 'the id is returned')
ok(typeof response.json().newId === 'string', 'the id is a string')
})
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('PersistenceInFile', () => {
author: 'Mateo Nunez'
})

const path = await fastify.orama.save()
const path = await fastify.orama.persist()
strictEqual(path, opts.filePath)

{
Expand Down Expand Up @@ -156,7 +156,7 @@ describe('PersistenceInMemory', () => {
author: 'Mateo Nunez'
})

const inMemoryDb = await fastifyOne.orama.save()
const inMemoryDb = await fastifyOne.orama.persist()

{
const results = await fastifyOne.orama.search({ term: 'Mateo Nunez' })
Expand Down