diff --git a/README.md b/README.md index 2582931..7b079ec 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,58 @@ app.get('/genId', async function handler (req, reply) { }) ``` +## Typescript + +This plugin comes with Typescript support out of the box. +Using the `withOrama` helper, you can access the `orama` decorator in your Fastify application with the correct schema. + +```ts +import Fastify from 'fastify' + +import { PersistenceInMemory, fastifyOrama } from 'fastify-orama' + +const app = Fastify() + +const mySchema = { + quote: 'string', + author: 'string' +} as const + +await app.register(fastifyOrama, { + schema: mySchema, + persistence: new PersistenceInMemory() +}) + +const appWithOrama = app.withOrama() +const id = await appWithOrama.orama.insert({ quote: 'Hello', author: 'World' }) + +appWithOrama.get('/hello', async () => { + + const {orama} = appWithOrama + const result = await orama.search({ term: 'hello' }) + + return { + hello: result.hits + } +}) +``` + +Usage with `fastify-plugin`: + +```ts +import fp from 'fastify-plugin' + +fp(function plugins(fastify) { + const fastifyWithOrama = fastify.withOrama() + + expectType<{ + insert: (document: PartialSchemaDeep>>) => Promise, + search: (params: SearchParams>, typeof mySchema>) => Promise>>, + persist?: () => Promise, + }>(fastifyWithOrama.orama) +}) +``` + ## License fastifyOrama is licensed under the [MIT](LICENSE) license. diff --git a/index.d.ts b/index.d.ts index 834c7a7..b70c7a9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,42 +1,47 @@ import type { FastifyPluginCallback } from 'fastify' -import type { Document, Orama, ProvidedTypes, Results, SearchParams, create } from '@orama/orama' +import type { TypedDocument, insert, Orama, Results, SearchParams, create, AnyOrama, PartialSchemaDeep, Schema } from '@orama/orama' -interface OramaPersistence { - restore: () => Promise | null> - persist: (data: ReturnType) => Promise +interface FastifyOramaPersistence { + restore: () => Promise | null> + persist: (data: Orama) => Promise } -declare class PersistenceInMemory implements OramaPersistence { + +declare class PersistenceInMemory implements FastifyOramaPersistence { constructor(options?: { jsonIndex?: string, }) - restore: () => Promise> | null> - persist: (data: Promise>) => Promise + restore: () => Promise | null> + persist: (data: Orama) => Promise } -declare class PersistenceInFile implements OramaPersistence { +declare class PersistenceInFile implements FastifyOramaPersistence { constructor(options?: { filePath?: string, format?: string, mustExistOnStart?: boolean }) - restore: () => Promise> | null> - persist: (data: Promise>) => Promise + restore: () => Promise | null> + persist: (data: Orama) => Promise } -type OramaPluginOptions = { - persistence?: OramaPersistence +type FastifyOramaPluginOptions = { + persistence?: FastifyOramaPersistence } & Partial[0]> -declare const fastifyOrama: FastifyPluginCallback +declare const fastifyOrama: FastifyPluginCallback + +interface OramaApi { + insert: (document: PartialSchemaDeep>>) => Promise, + search: (params: SearchParams>, T>) => Promise>>, + persist?: () => Promise, +} declare module 'fastify' { interface FastifyInstance { - orama: { - insert: (document: Document) => Promise, - search: (params: SearchParams) => Promise, - persist?: () => Promise, - } + withOrama(): this & { + orama: OramaApi + }; } } diff --git a/index.js b/index.js index 206ced7..71db171 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,10 @@ -import fp from 'fastify-plugin' -import * as Orama from '@orama/orama' +'use strict' -import PersistenceInMemory from './lib/persistence/in-memory.js' -import PersistenceInFile from './lib/persistence/in-file.js' +const fp = require('fastify-plugin') +const Orama = require('@orama/orama') + +const PersistenceInMemory = require('./lib/persistence/in-memory.js') +const PersistenceInFile = require('./lib/persistence/in-file.js') const SKIP_METHODS = [ 'create' @@ -49,17 +51,20 @@ async function fastifyOrama (fastify, options) { db = await Orama.create(oramaOptions) } + function withOrama () { + return this + } + fastify.decorate('orama', oramaApi) + fastify.decorate('withOrama', withOrama) } -export default fp(fastifyOrama, { +module.exports = fp(fastifyOrama, { fastify: '4.x', name: 'fastify-orama' }) -export { - fastifyOrama, - PersistenceInMemory, - PersistenceInFile, - oramaInternals -} +module.exports.fastifyOrama = fastifyOrama +module.exports.PersistenceInMemory = PersistenceInMemory +module.exports.PersistenceInFile = PersistenceInFile +module.exports.oramaInternals = oramaInternals diff --git a/index.test-d.ts b/index.test-d.ts deleted file mode 100644 index 465815d..0000000 --- a/index.test-d.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { expectType } from 'tsd' - -import Fastify from 'fastify' -import { Result } from '@orama/orama' - -import { fastifyOrama, PersistenceInMemory, PersistenceInFile } from '.' - -const app = Fastify() - -app.register(fastifyOrama, { - schema: { - quote: 'string', - author: 'string' - }, - prefix: '/api/orama', - language: 'en' -}) - -app.register(fastifyOrama, { - persistence: new PersistenceInMemory() -}) - -app.register(fastifyOrama, { - persistence: new PersistenceInMemory({ - jsonIndex: 'index.json' - }) -}) - -app.register(fastifyOrama, { - persistence: new PersistenceInFile() -}) -app.register(fastifyOrama, { - persistence: new PersistenceInFile({ - filePath: 'index.json', - format: 'json', - mustExistOnStart: true - }) -}) - -app.orama.insert({ quote: 'Hello', author: 'World' }) - -app.get('/hello', async () => { - const result = await app.orama.search({ term: 'hello' }) - - expectType(result.hits) - - return { - hello: result.hits - } -}) diff --git a/lib/persistence/in-file.js b/lib/persistence/in-file.js index 25ca9af..804803b 100644 --- a/lib/persistence/in-file.js +++ b/lib/persistence/in-file.js @@ -1,6 +1,8 @@ -import path from 'node:path' -import { existsSync } from 'node:fs' -import { restoreFromFile, persistToFile } from '@orama/plugin-data-persistence/server' +'use strict' + +const path = require('node:path') +const { existsSync } = require('node:fs') +const { restoreFromFile, persistToFile } = require('@orama/plugin-data-persistence/server') class PersistenceInFile { constructor (options = {}) { @@ -30,4 +32,4 @@ class PersistenceInFile { } } -export default PersistenceInFile +module.exports = PersistenceInFile diff --git a/lib/persistence/in-memory.js b/lib/persistence/in-memory.js index 88c05fa..90d0b41 100644 --- a/lib/persistence/in-memory.js +++ b/lib/persistence/in-memory.js @@ -1,4 +1,6 @@ -import { restore, persist } from '@orama/plugin-data-persistence' +'use strict' + +const { restore, persist } = require('@orama/plugin-data-persistence') class PersistenceInMemory { constructor (options) { @@ -18,4 +20,4 @@ class PersistenceInMemory { } } -export default PersistenceInMemory +module.exports = PersistenceInMemory diff --git a/package.json b/package.json index 0157fcc..fc9bba6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "version": "0.7.0", "description": "Orama search-engine plugin for Fastify", "main": "index.js", - "type": "module", "types": "index.d.ts", "author": { "name": "Mateo Nunez", @@ -14,7 +13,7 @@ "lint": "standard | snazzy", "lint:fix": "standard --fix | snazzy", "pretest": "npm run clean", - "test": "npm run lint && npm run unit && npm run typescript", + "test": "npm run lint && npm run unit && npm run typescript && ts-node test/types/index.ts", "posttest": "npm run clean", "typescript": "tsd", "prepare": "husky install", @@ -51,10 +50,14 @@ "husky": "^8.0.3", "snazzy": "^9.0.0", "standard": "^17.1.0", + "ts-node": "^10.9.1", "tsd": "^0.29.0", "typescript": "^5.2.2" }, "publishConfig": { "access": "public" + }, + "tsd": { + "directory": "test/types" } } diff --git a/test/index.test.js b/test/index.test.js index 50bc6d2..5869f33 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,9 +1,9 @@ 'use strict' -import { it } from 'node:test' -import { ok, strictEqual } from 'node:assert' -import Fastify from 'fastify' -import fastifyOrama from '../index.js' +const { it } = require('node:test') +const { ok, strictEqual } = require('node:assert') +const Fastify = require('fastify') +const fastifyOrama = require('../index.js') it('Should register correctly fastifyOrama plugin', async () => { const fastify = Fastify() @@ -72,3 +72,18 @@ it('Should throw when trying to register multiple instances without giving a nam strictEqual(error.message, 'fastify-orama is already registered') } }) + +it('Expose a withOrama function', async () => { + const fastify = Fastify() + + await fastify.register(fastifyOrama, { + schema: { + quote: 'string', + author: 'string' + } + }) + + const withOrama = fastify.withOrama() + + strictEqual(fastify.orama, withOrama.orama) +}) diff --git a/test/orama-proxy.test.js b/test/orama-proxy.test.js index 83fe080..2a5c336 100644 --- a/test/orama-proxy.test.js +++ b/test/orama-proxy.test.js @@ -1,9 +1,9 @@ 'use strict' -import { it } from 'node:test' -import { ok, strictEqual } from 'node:assert' -import Fastify from 'fastify' -import { fastifyOrama, oramaInternals } from '../index.js' +const { it } = require('node:test') +const { ok, strictEqual } = require('node:assert') +const Fastify = require('fastify') +const { fastifyOrama, oramaInternals } = require('../index.js') it('Should expose all the Orama APIs', async () => { const fastify = Fastify() diff --git a/test/persistence.test.js b/test/persistence.test.js index 50043f3..0b9a3a3 100644 --- a/test/persistence.test.js +++ b/test/persistence.test.js @@ -1,9 +1,11 @@ -import { describe, it } from 'node:test' -import { strictEqual, match } from 'node:assert' -import Fastify from 'fastify' -import { fastifyOrama, PersistenceInMemory, PersistenceInFile } from '../index.js' -import { create, insert } from '@orama/orama' -import { persistToFile } from '@orama/plugin-data-persistence/server' +'use strict' + +const { describe, it } = require('node:test') +const { strictEqual, match } = require('node:assert') +const Fastify = require('fastify') +const { fastifyOrama, PersistenceInMemory, PersistenceInFile } = require('../index.js') +const { create, insert } = require('@orama/orama') +const { persistToFile } = require('@orama/plugin-data-persistence/server') async function buildFakeDb (filePath, format) { const db = await create({ diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts new file mode 100644 index 0000000..024488d --- /dev/null +++ b/test/types/index.test-d.ts @@ -0,0 +1,76 @@ +import { expectType } from 'tsd' + +import { InternalTypedDocument, Orama, PartialSchemaDeep, Results, Schema, SearchParams, TypedDocument } from '@orama/orama' +import Fastify from 'fastify' +import fp from 'fastify-plugin' + +import { PersistenceInFile, PersistenceInMemory, fastifyOrama } from '../..' + +const app = Fastify() + +const mySchema = { + quote: 'string', + author: 'string' +} as const +type MySchema = Schema + + +app.register(fastifyOrama, { + schema: mySchema, + prefix: '/api/orama', + language: 'en' +}) + +app.register(fastifyOrama, { + persistence: new PersistenceInMemory() +}) + +app.register(fastifyOrama, { + persistence: new PersistenceInMemory({ + jsonIndex: 'index.json' + }) +}) + +app.register(fastifyOrama, { + persistence: new PersistenceInFile() +}) +app.register(fastifyOrama, { + persistence: new PersistenceInFile({ + filePath: 'index.json', + format: 'json', + mustExistOnStart: true + }) +}) + +const appWithOrama = app.withOrama() +const id = await appWithOrama.orama.insert({ quote: 'Hello', author: 'World' }) +expectType(id) + +appWithOrama.get('/hello', async () => { + + const {orama} = appWithOrama + const result = await orama.search({ term: 'hello' }) + + expectType>>(result) + expectType(result.hits[0].document.author) + + return { + hello: result.hits + } +}) + +expectType<{ + insert: (document: PartialSchemaDeep>>) => Promise, + search: (params: SearchParams>, typeof mySchema>) => Promise>>, + persist?: () => Promise, +}>(appWithOrama.orama) + +fp(function(fastify) { + const fastifyWithOrama = fastify.withOrama() + + expectType<{ + insert: (document: PartialSchemaDeep>>) => Promise, + search: (params: SearchParams>, typeof mySchema>) => Promise>>, + persist?: () => Promise, + }>(fastifyWithOrama.orama) +}) \ No newline at end of file diff --git a/test/types/index.ts b/test/types/index.ts new file mode 100644 index 0000000..a62fd55 --- /dev/null +++ b/test/types/index.ts @@ -0,0 +1,30 @@ +import Fastify from 'fastify' + +import { PersistenceInMemory, fastifyOrama } from '../..' + +(async function () { + const app = Fastify() + + const mySchema = { + quote: 'string', + author: 'string' + } as const + + await app.register(fastifyOrama, { + schema: mySchema, + persistence: new PersistenceInMemory() + }) + + const appWithOrama = app.withOrama() + const id = await appWithOrama.orama.insert({ quote: 'Hello', author: 'World' }) + + appWithOrama.get('/hello', async () => { + + const {orama} = appWithOrama + const result = await orama.search({ term: 'hello' }) + + return { + hello: result.hits + } + }) +})(); \ No newline at end of file