Skip to content

Commit

Permalink
Add test to types (#508)
Browse files Browse the repository at this point in the history
  • Loading branch information
allevo authored Oct 5, 2023
1 parent 60ba68e commit 545ba4b
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 7 deletions.
4 changes: 3 additions & 1 deletion packages/orama/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"test": "c8 -c tests/config/c8-local.json tap --rcfile=tests/config/tap.yml tests/*.test.ts",
"test:ci": "c8 -c tests/config/c8-ci.json tap --rcfile=tests/config/tap.yml --no-color tests/*.test.ts",
"test:smoke": "tap --rcfile=tests/config/tap.yml tests/smoke/*.test.ts",
"ci": "npm run build && npm run test:ci && npm run test:smoke"
"test:types": "tsc --emitDeclarationOnly; tsd --files tests/type/",
"ci": "npm run build && npm run test:ci && npm run test:types"
},
"keywords": [
"full-text search",
Expand Down Expand Up @@ -98,6 +99,7 @@
"tap-mocha-reporter": "^5.0.3",
"tape": "^5.6.1",
"tcompare": "^6.0.0",
"tsd": "^0.29.0",
"tsx": "^3.12.1",
"typescript": "^5.0.0",
"vite": "^4.1.4"
Expand Down
2 changes: 1 addition & 1 deletion packages/orama/src/methods/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export async function search<T extends AnyOrama, ResultDocument = TypedDocument<
}
}

propertiesToSearch = propertiesToSearch.filter((prop: string) => properties.includes(prop))
propertiesToSearch = propertiesToSearch.filter((prop: string) => (properties as string[]).includes(prop))
}

// Create the search context and the results
Expand Down
33 changes: 32 additions & 1 deletion packages/orama/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,33 @@ export type SingleOrArray<T> = T | T[]

export type SyncOrAsyncValue<T = void> = T | PromiseLike<T>

// Given a type T, return a new type with:
// - the concatenation of nested properties as key
// - the type of the nested property as value
export type Flatten<T extends object> = object extends T
? object
: {
[K in keyof T]-?: (
x: NonNullable<T[K]> extends infer V
? V extends object
? V extends readonly any[]
? Pick<T, K>
: Flatten<V> extends infer FV
? {
[P in keyof FV as `${Extract<K, string | number>}.${Extract<P, string | number>}`]: FV[P]
}
: never
: Pick<T, K>
: never,
) => void
} extends Record<keyof T, (y: infer O) => void>
// eslint-disable-next-line @typescript-eslint/no-unused-vars
? O extends infer U
? { [K in keyof O]: O[K] }
: never
: never


export type SchemaTypes<Value> = Value extends 'string'
? string
: Value extends 'string[]'
Expand Down Expand Up @@ -195,6 +222,10 @@ export type SorterParams<T extends AnyOrama> = {
order?: 'ASC' | 'DESC'
}


export type FlattenSchema<T extends AnyOrama> = Flatten<T['schema']>
export type FlattenSchemaProperty<T extends AnyOrama> = T['schema'] extends object ? keyof FlattenSchema<T> : string

export type SortByParams<T extends AnyOrama, ResultDocument> = SorterParams<T> | CustomSorterFunction<ResultDocument>

export type SearchParams<T extends AnyOrama, ResultDocument = TypedDocument<T>> = {
Expand All @@ -205,7 +236,7 @@ export type SearchParams<T extends AnyOrama, ResultDocument = TypedDocument<T>>
/**
* The properties of the document to search in.
*/
properties?: '*' | LiteralUnion<T['schema']>[]
properties?: '*' | FlattenSchemaProperty<T>[]
/**
* The number of matched documents to return.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/orama/tests/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ t.test('search method', t => {
() =>
search(db, {
term: 'foo',
properties: ['bar'],
properties: ['bar'] as unknown as ('foo' | 'baz')[],
}),
{
code: 'UNKNOWN_INDEX',
Expand Down Expand Up @@ -416,7 +416,7 @@ t.test('search method', t => {
() =>
search(db, {
term: 'foo',
properties: ['bar'],
properties: ['bar'] as unknown as ('foo' | 'baz')[],
}),
{
code: 'UNKNOWN_INDEX',
Expand Down
37 changes: 37 additions & 0 deletions packages/orama/tests/type/basic.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { expectType } from 'tsd'
import type { InternalTypedDocument, Orama, Results, Schema } from '../../src/types.d.ts'
import { create, insert, search } from '../../src/index.js'

const movieSchema = {
title: 'string',
year: 'number',
actors: 'string[]',
isFavorite: 'boolean',
stars: 'enum'
} as const
type MovieSchema = Schema<typeof movieSchema>
type MovieDocument = InternalTypedDocument<MovieSchema>

const movieDBP = create({
schema: movieSchema,
})
expectType<Promise<Orama<typeof movieSchema>>>(movieDBP)
const movieDB = await movieDBP

const idP = insert(movieDB, {
title: 'The Godfather',
year: 1972,
actors: ['Marlon Brando', 'Al Pacino'],
isFavorite: true,
})
expectType<Promise<string>>(idP)

const resultP = search(movieDB, {
term: 'godfather',
})
expectType<Promise<Results<MovieDocument>>>(resultP)
const result = await resultP
expectType<string>(result.hits[0].document.title)


32 changes: 32 additions & 0 deletions packages/orama/tests/type/search.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { expectAssignable, expectNotAssignable } from 'tsd'
import type { SearchParams, Orama } from '../../src/types.d.ts'

const movieSchema = {
title: 'string',
year: 'number',
actors: 'string[]',
isFavorite: 'boolean',
stars: 'enum',
meta: {
foo: 'string'
}
} as const

// Test search properties type
{
type MovieSearchParamsProperties = SearchParams<Orama<typeof movieSchema>>['properties']

expectAssignable<MovieSearchParamsProperties>('*')
expectAssignable<MovieSearchParamsProperties>(['title'])
expectAssignable<MovieSearchParamsProperties>(['meta.foo'])
expectNotAssignable<MovieSearchParamsProperties>(['meta.unknown'])
expectNotAssignable<MovieSearchParamsProperties>(['unknown'])

// Test search properties type with unknown schema
{
type MovieSearchParamsProperties = SearchParams<Orama<any>>['properties']
expectAssignable<MovieSearchParamsProperties>('*')
expectAssignable<MovieSearchParamsProperties>(['title'])
}
}
Loading

1 comment on commit 545ba4b

@vercel
Copy link

@vercel vercel bot commented on 545ba4b Oct 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.