feathers-solr
Advanced tools
Comparing version 3.0.5 to 3.0.6
@@ -1,14 +0,1 @@ | ||
/* | ||
👋 Hi! This file was autogenerated by tslint-to-eslint-config. | ||
https://github.com/typescript-eslint/tslint-to-eslint-config | ||
It represents the closest reasonable ESLint configuration to this | ||
project's original TSLint configuration. | ||
We recommend eventually switching this configuration to extend from | ||
the recommended rulesets in typescript-eslint. | ||
https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FAQs.md | ||
Happy linting! 💖 | ||
*/ | ||
module.exports = { | ||
@@ -149,3 +136,3 @@ "env": { | ||
"radix": "error", | ||
"space-before-function-paren": "error", | ||
"space-before-function-paren": 0, | ||
"spaced-comment": [ | ||
@@ -152,0 +139,0 @@ "error", |
@@ -1,49 +0,25 @@ | ||
import { NullableId, Id } from '@feathersjs/feathers'; | ||
import { AdapterService, ServiceOptions, InternalServiceMethods, AdapterParams } from '@feathersjs/adapter-commons'; | ||
import { SolrClient } from './client'; | ||
export declare const escapeFn: (key: string, value: any) => { | ||
key: string; | ||
value: any; | ||
}; | ||
export interface SolrServiceOptions extends ServiceOptions { | ||
host: string; | ||
core: string; | ||
commit?: { | ||
softCommit?: boolean; | ||
commitWithin?: number; | ||
overwrite?: boolean; | ||
}; | ||
queryHandler?: string; | ||
updateHandler?: string; | ||
defaultSearch?: any; | ||
defaultParams?: any; | ||
createUUID?: boolean; | ||
escapeFn?: (key: string, value: any) => { | ||
key: string; | ||
value: any; | ||
}; | ||
requestOptions: { | ||
timeout: 10; | ||
}; | ||
import type { AdapterParams, PaginationOptions } from '@feathersjs/adapter-commons'; | ||
import type { Paginated, ServiceMethods, Id, NullableId } from '@feathersjs/feathers'; | ||
import { SolrAdapter } from './adapter'; | ||
export * from './adapter'; | ||
export declare class SolrService<T = any, D = Partial<T>, P extends AdapterParams = AdapterParams> extends SolrAdapter<T, D, P> implements ServiceMethods<T | Paginated<T>, D, P> { | ||
find(params?: P & { | ||
paginate?: PaginationOptions; | ||
}): Promise<Paginated<T>>; | ||
find(params?: P & { | ||
paginate: false; | ||
}): Promise<T[]>; | ||
find(params?: P): Promise<Paginated<T> | T[]>; | ||
get(id: NullableId, params?: P): Promise<T>; | ||
get(id: Id, params?: P): Promise<T>; | ||
create(data: D, params?: P): Promise<T>; | ||
create(data: D[], params?: P): Promise<T[]>; | ||
update(id: Id, data: D, params?: P): Promise<T>; | ||
update(id: NullableId, data: D, params?: P): Promise<T>; | ||
patch(id: NullableId, data: Partial<D>, params?: P): Promise<T>; | ||
patch(id: Id, data: Partial<D>, params?: P): Promise<T>; | ||
patch(id: null, data: Partial<D>, params?: P): Promise<T[]>; | ||
remove(id: Id, params?: P): Promise<T>; | ||
remove(id: NullableId, params?: P): Promise<T>; | ||
remove(id: null, params?: P): Promise<T[]>; | ||
} | ||
export declare class Service<T = any, D = Partial<T>> extends AdapterService<T, D> implements InternalServiceMethods<T> { | ||
options: SolrServiceOptions; | ||
client: SolrClient; | ||
queryHandler: string; | ||
updateHandler: string; | ||
constructor(options: Partial<SolrServiceOptions>); | ||
_getOrFind(id: Id, params: AdapterParams): Promise<any>; | ||
_get(id: Id, params?: AdapterParams): Promise<any>; | ||
_find(params?: AdapterParams): Promise<any[] | { | ||
QTime: number; | ||
total: number; | ||
limit: any; | ||
skip: number; | ||
data: any[]; | ||
}>; | ||
_create(data: Partial<T> | Partial<T>[], params?: AdapterParams): Promise<T | T[]>; | ||
_update(id: NullableId, data: T, params?: AdapterParams): Promise<any>; | ||
_patch(id: NullableId, data: Partial<T>, params?: AdapterParams): Promise<any>; | ||
_remove(id: NullableId, params?: AdapterParams): Promise<T | T[]>; | ||
} | ||
export default function service(options: Partial<SolrServiceOptions>): Service<any, Partial<any>>; |
121
lib/index.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Service = exports.escapeFn = void 0; | ||
const errors_1 = require("@feathersjs/errors"); | ||
const commons_1 = require("@feathersjs/commons"); | ||
const adapter_commons_1 = require("@feathersjs/adapter-commons"); | ||
const client_1 = require("./client"); | ||
const response_1 = require("./response"); | ||
const query_1 = require("./query"); | ||
const escapeFn = (key, value) => { | ||
return { key, value }; | ||
}; | ||
exports.escapeFn = escapeFn; | ||
class Service extends adapter_commons_1.AdapterService { | ||
constructor(options) { | ||
const { host, core, requestOptions, ...opts } = options; | ||
super(commons_1._.extend({ | ||
id: 'id', | ||
commit: { | ||
softCommit: true, | ||
commitWithin: 10000, | ||
overwrite: true | ||
}, | ||
queryHandler: '/query', | ||
updateHandler: '/update/json', | ||
defaultSearch: {}, | ||
defaultParams: { echoParams: 'none' }, | ||
createUUID: true, | ||
escapeFn: exports.escapeFn | ||
}, opts)); | ||
this.queryHandler = `/${core}${this.options.queryHandler}`; | ||
this.updateHandler = `/${core}${this.options.updateHandler}`; | ||
this.client = (0, client_1.solrClient)(host, requestOptions); | ||
exports.SolrService = void 0; | ||
const adapter_1 = require("./adapter"); | ||
__exportStar(require("./adapter"), exports); | ||
class SolrService extends adapter_1.SolrAdapter { | ||
async find(params) { | ||
return this._find(params); | ||
} | ||
_getOrFind(id, params) { | ||
if (id !== null) | ||
return this._get(id, params); | ||
return this._find(Object.assign(params, { | ||
paginate: false | ||
})); | ||
async get(id, params) { | ||
return this._get(id, params); | ||
} | ||
async _get(id, params = {}) { | ||
const { query, filters, paginate } = this.filterQuery(params); | ||
const solrQuery = (0, query_1.jsonQuery)(id, filters, query, paginate, this.options.escapeFn); | ||
const response = await this.client.post(this.queryHandler, { data: solrQuery }); | ||
if (response.response.numFound === 0) | ||
throw new errors_1.NotFound(`No record found for id '${id}'`); | ||
const result = (0, response_1.responseGet)(response); | ||
return result; | ||
async create(data, params) { | ||
return this._create(data, params); | ||
} | ||
async _find(params = {}) { | ||
const { query, filters, paginate } = this.filterQuery(params); | ||
const solrQuery = (0, query_1.jsonQuery)(null, filters, query, paginate, this.options.escapeFn); | ||
const response = await this.client.post(this.queryHandler, { data: solrQuery }); | ||
const result = (0, response_1.responseFind)(filters, paginate, response); | ||
return result; | ||
async update(id, data, params) { | ||
return this._update(id, data, params); | ||
} | ||
async _create(data, params = {}) { | ||
const sel = (0, adapter_commons_1.select)(params, this.id); | ||
if (commons_1._.isEmpty(data)) | ||
throw new errors_1.MethodNotAllowed('Data is empty'); | ||
let dataToCreate = Array.isArray(data) ? [...data] : [{ ...data }]; | ||
if (this.options.createUUID) { | ||
dataToCreate = (0, query_1.addIds)(dataToCreate, this.options.id); | ||
} | ||
await this.client.post(this.updateHandler, { data: dataToCreate, params: this.options.commit }); | ||
return sel(Array.isArray(data) ? dataToCreate : dataToCreate[0]); | ||
async patch(id, data, params) { | ||
return this._patch(id, data, params); | ||
} | ||
async _update(id, data, params = {}) { | ||
const sel = (0, adapter_commons_1.select)(params, this.id); | ||
await this._getOrFind(id, params); | ||
const dataToUpdate = id && !Array.isArray(data) ? [{ id, ...data }] : data; | ||
await this.client.post(this.updateHandler, { data: dataToUpdate, params: this.options.commit }); | ||
return this._getOrFind(id, params).then(res => sel(commons_1._.omit(res, 'score', '_version_'))); | ||
async remove(id, params) { | ||
return this._remove(id, params); | ||
} | ||
async _patch(id, data, params = {}) { | ||
const sel = (0, adapter_commons_1.select)(params, this.id); | ||
const dataToPatch = await this._getOrFind(id, params); | ||
const { ids, patchData } = (0, query_1.patchQuery)(dataToPatch, data, this.id); | ||
await this.client.post(this.updateHandler, { data: patchData, params: this.options.commit }); | ||
const result = await this._find({ query: { id: { $in: ids } } }); | ||
if (result.data) | ||
return sel(ids.length === 1 ? result.data[0] : result.data); | ||
return sel(ids.length === 1 ? result[0] : result); | ||
} | ||
async _remove(id, params = {}) { | ||
const sel = (0, adapter_commons_1.select)(params, this.id); | ||
const dataToDelete = await this._getOrFind(id, params); | ||
const { query } = this.filterQuery(params); | ||
const queryToDelete = (0, query_1.deleteQuery)(id, query, this.options.escapeFn); | ||
await this.client.post(this.updateHandler, { data: queryToDelete, params: this.options.commit }); | ||
return sel(dataToDelete); | ||
} | ||
} | ||
exports.Service = Service; | ||
function service(options) { | ||
return new Service(options); | ||
} | ||
exports.default = service; | ||
exports.SolrService = SolrService; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "feathers-solr", | ||
"description": "A service plugin for Solr", | ||
"version": "3.0.5", | ||
"version": "3.0.6", | ||
"keywords": [ | ||
@@ -9,3 +9,6 @@ "feathers", | ||
"solr", | ||
"solr-client" | ||
"solr-client", | ||
"search", | ||
"database", | ||
"api" | ||
], | ||
@@ -31,3 +34,4 @@ "license": "MIT", | ||
"prepublish": "npm run build", | ||
"lint": "eslint src/**/*.ts test/**/*.ts --fix", | ||
"lint": "eslint src/**/*.ts --fix", | ||
"lint:test": "eslint test/**/*.ts --fix", | ||
"build": "shx rm -rf lib/ && tsc", | ||
@@ -45,23 +49,23 @@ "test": "npm run build && npm run mocha", | ||
"dependencies": { | ||
"@feathersjs/adapter-commons": "^5.0.0-pre.15", | ||
"@feathersjs/commons": "^5.0.0-pre.15", | ||
"@feathersjs/errors": "^5.0.0-pre.15" | ||
"@feathersjs/adapter-commons": "^5.0.0-pre.33", | ||
"@feathersjs/commons": "^5.0.0-pre.33", | ||
"@feathersjs/errors": "^5.0.0-pre.33" | ||
}, | ||
"devDependencies": { | ||
"@feathersjs/adapter-tests": "^5.0.0-pre.15", | ||
"@feathersjs/express": "^5.0.0-pre.15", | ||
"@feathersjs/feathers": "^5.0.0-pre.15", | ||
"@types/mocha": "^9.0.0", | ||
"@types/node": "^17.0.5", | ||
"@typescript-eslint/eslint-plugin": "^5.8.0", | ||
"@typescript-eslint/parser": "^5.8.0", | ||
"eslint": "^8.5.0", | ||
"eslint-plugin-import": "^2.25.3", | ||
"@feathersjs/adapter-tests": "^5.0.0-pre.33", | ||
"@feathersjs/express": "^5.0.0-pre.33", | ||
"@feathersjs/feathers": "^5.0.0-pre.33", | ||
"@types/mocha": "^10.0.1", | ||
"@types/node": "^18.11.13", | ||
"@typescript-eslint/eslint-plugin": "^5.46.0", | ||
"@typescript-eslint/parser": "^5.46.0", | ||
"eslint": "^8.29.0", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-prefer-arrow": "^1.2.3", | ||
"mocha": "^9.1.3", | ||
"mocha": "^10.1.0", | ||
"nyc": "^15.1.0", | ||
"shx": "^0.3.3", | ||
"ts-node": "^10.4.0", | ||
"typescript": "^4.5.4" | ||
"shx": "^0.3.4", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^4.9.4" | ||
} | ||
} |
207
README.md
@@ -8,5 +8,4 @@ # feathers-solr | ||
A [Feathers](https://feathersjs.com/) Solr Adapter. Require >= Solr 5.x. | ||
A [Feathers](https://feathersjs.com/) Solr Adapter. Tested with Solr 8.x, require at least >= Solr 5.x. | ||
> See this [adapter in action](https://feathers.better-search-box.com) | ||
@@ -19,5 +18,5 @@ ## Installation | ||
> **Important:** `feathers-solr` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html). | ||
> __Important:__ `@feathersjs/memory` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html). | ||
> It use sthe native node `http` and `https` module. | ||
## API | ||
@@ -30,14 +29,4 @@ | ||
```js | ||
import { solrClient } from '../src/client'; | ||
const Client = solrClient(options.host); | ||
const options = { | ||
host: 'http://localhost:8983/solr', | ||
core: 'gettingstarted' | ||
} | ||
const Client = solrClient(options.host); | ||
const app = feathers(); | ||
app.use('/gettingstarted', Solr({ ...options, multi: false })); | ||
const service = require('feathers-solr'); | ||
app.use('/search', service({host, core})); | ||
``` | ||
@@ -48,12 +37,18 @@ | ||
- `core` - The name of the Solr Core / Colelction. | ||
- `defaultParams` - This params added to all Solr request. | ||
- `id` (_optional_, default: `'id'`) - The name of the id field property. | ||
- `commitStrategy` - (_optional_, default: `{ softCommit: true, commitWithin: 10000, overwrite: true }`) - Define how Index changes are stored [Solr Commits](https://lucene.apache.org/solr/guide/7_7/updatehandlers-in-solrconfig.html#UpdateHandlersinSolrConfig-commitandsoftCommit). | ||
- `defaultSearch` - (_optional_, default: `{ defType: 'edismax', qf: 'name^10 age^1 gender' }`) - Search strategy if query contains the param `$search` [The Extended DisMax Query Parser](https://lucene.apache.org/solr/guide/6_6/the-extended-dismax-query-parser.html). | ||
- `suggestHandler` - (_optional_, default: `suggest`) - Request a Solr Suggest Handler instead reggular a search if query contains the param `$suggest` [Suggester](https://lucene.apache.org/solr/guide/7_7/suggester.html). | ||
- `events` (_optional_) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service | ||
- `paginate` (_optional_) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size | ||
- `whitelist` (default: `['$search', '$params', '$facet', '$filter']`) [optional] - The list of additional non-standard query parameters to allow, by default populated with all Solr specific ones. You can override, for example in order to restrict access to some queries (see the [options documentation](https://docs.feathersjs.com/api/databases/common.html#serviceoptions)). | ||
- `multi` (_optional_) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`) | ||
- `host` - The name of the Solr core / collection. | ||
- `core` - The name of the Solr core / collection. | ||
- `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service | ||
- `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size | ||
- `whitelist` (*DEPRECATED*) - renamed to `allow` | ||
- `allow` (*optional*) - A list of additional query parameters to allow | ||
- `multi` (*optional*) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`) | ||
- `id` (*optional*, default: `'id'`) - The name of the id field property. | ||
- `commitStrategy` - (*optional*, default: `{ softCommit: true, commitWithin: 10000, overwrite: true }`) - Define how Index changes are stored [Solr Commits](https://lucene.apache.org/solr/guide/7_7/updatehandlers-in-solrconfig.html#UpdateHandlersinSolrConfig-commitandsoftCommit). | ||
- `defaultParams` (*optional* default: `{ echoParams: 'none' }`)- This params added to all Solr request. | ||
- `defaultSearch` - (*optional*, default: `{ defType: 'edismax', qf: 'name^10 age^1 gender' }`) - Search strategy if query contains the param `$search` [The Extended DisMax Query Parser](https://lucene.apache.org/solr/guide/6_6/the-extended-dismax-query-parser.html). | ||
- `queryHandler` (*optional* default: `'/query'`) - This params defines the Solr request handler to use. | ||
- `updateHandler` (*optional* default: `'/update/json'`) - This params defines the Solr update handler to use. | ||
- `createUUID` (*optional* default: `true`) - This params add aa UUID if not exist on data. Id's generated by `crypto` | ||
- `escapeFn` (*optional* default: `(key: string, value: any) => { key, value }`) - To apply escaping. | ||
- `requestOptions` (*optional* default: `{ timeout: 10 })` - The [options](https://nodejs.org/api/http.html#httprequestoptions-callback) passed to `http.request`. | ||
@@ -67,8 +62,6 @@ ## Getting Started | ||
const express = require('@feathersjs/express'); | ||
const fetch = require('node-fetch'); | ||
const undici = require('undici'); | ||
const Service = require('feathers-solr'); | ||
const { SolrClient } = require('feathers-solr'); | ||
const solrServer = 'http://localhost:8983/solr/gettingstarted'; | ||
const socketio = require('@feathersjs/socketio'); | ||
const Service = require('feathers-solr').Service; | ||
// Create an Express compatible Feathers application instance. | ||
@@ -82,7 +75,9 @@ const app = express(feathers()); | ||
app.configure(express.rest()); | ||
// Enable REST services | ||
// Set up default error handler | ||
app.use(express.errorHandler()); | ||
// init Adapter witch Fetch or Undici | ||
// Create a service | ||
const options = { | ||
Model: SolrClient(fetch, solrServer), | ||
host: 'http://localhost:8983/solr', | ||
core: 'gettingstarted', | ||
paginate: {}, | ||
@@ -93,15 +88,16 @@ events: ['testing'] | ||
app.listen(3030, () => { | ||
console.log(`Feathers server listening on port http://127.0.0.1:3030`); | ||
// Start the server. | ||
const port = 3030; | ||
app.listen(port, () => { | ||
console.log(`Feathers server listening on port ${port}`) | ||
}); | ||
``` | ||
Install Solr | ||
Start Solr | ||
``` | ||
```bash | ||
bin/solr start -e gettingstarted | ||
``` | ||
Use `feathers-solr/bin/install-solr.sh` for a kickstart installation. | ||
Run the example with `node app` and go to [localhost:3030/gettingstarted](http://localhost:3030/gettingstarted). | ||
@@ -113,5 +109,5 @@ | ||
## Supportet Solr specific queries | ||
## Supported Solr specific queries | ||
This Adapter use the Solr [JSON Request API](https://lucene.apache.org/solr/guide/7_7/json-request-api.html). | ||
This Adapter uses the Solr [JSON Request API](https://lucene.apache.org/solr/guide/7_7/json-request-api.html). | ||
@@ -125,3 +121,3 @@ The following params passed in raw to Solr. This gives the **full** access to the Solr [JSON Request API](https://lucene.apache.org/solr/guide/7_7/json-request-api.html). | ||
To avoid full query (read) access, just whitelist only `$search` and add your query startegy into a Hook. | ||
To avoid full query (read) access, just whitelist only `$search` and add your query strategy into a Hook. | ||
@@ -169,3 +165,3 @@ ### \$search | ||
A alias to Solr param `facet` | ||
An alias to Solr param `facet` | ||
@@ -243,3 +239,3 @@ - [Solr Facet Functions and Analytics](http://yonik.com/solr-facet-functions/) | ||
An alias to Solr param `params`. Allows you to access all solr query (read) features like: | ||
An alias to Solr param `params`. Allows you to access all Solr query (read) features like: | ||
@@ -347,3 +343,3 @@ - [The Extended DisMax (eDismax) Query Parser](https://lucene.apache.org/solr/guide/7_7/the-extended-dismax-query-parser.html) | ||
sort: 'geodist() asc' | ||
} | ||
} | ||
}, | ||
@@ -367,3 +363,3 @@ paginate: { max: 10, default: 3 } | ||
The `options.commitStrategy.override` is true in default. This allow to override an existing `id` by `service.create`. | ||
Add the field `_version_` to the `$select` params will return the document content with it's version. Create with an existing `id` and `_version_` for [optimistic concurrency](https://lucene.apache.org/solr/guide/6_6/updating-parts-of-documents.html#UpdatingPartsofDocuments-OptimisticConcurrency) | ||
Add the field `_version_` to the `$select` params will return the document content with its version. Create with an existing `id` and `_version_` for [optimistic concurrency](https://lucene.apache.org/solr/guide/6_6/updating-parts-of-documents.html#UpdatingPartsofDocuments-OptimisticConcurrency) | ||
@@ -405,3 +401,3 @@ ### Service.update | ||
```Javascript | ||
service.remove(null, {query: {id:'*'}}); | ||
service.remove(null, {}); | ||
``` | ||
@@ -411,90 +407,59 @@ | ||
Most of the data mutating operations in Solr (create, update, remove) do not return the full resulting document, therefore I had to resolve to using get as well in order to return complete data. This solution is of course adding a bit of an overhead, although it is also compliant with the standard behaviour expected of a feathers database adapter. | ||
Data mutating operations in Solr do not return document data. This is implemented as additional queries to return deletd or modified data. | ||
> Use Raw Query `service.Model.post('update/json', data)` to avoid this overhead. The response is native Solr. | ||
To avoid this overhead use the `client` directly for bulk operations. | ||
```js | ||
const options = { | ||
host: 'http://localhost:8983/solr', | ||
core: 'gettingstarted', | ||
} | ||
## Raw Solr Queries | ||
const client = solrClient('http://localhost:8983/solr'); | ||
You can access all Solr API endpoints by using a direct model usage. | ||
Ping the Solr core/collection: | ||
```Javascript | ||
service.Model.get('admin/ping'); | ||
await client.post('/update/json', { data: [] }) | ||
``` | ||
Get Solr schema information: | ||
## Maniging Solr | ||
```Javascript | ||
service.Model.get('schema'); | ||
``` | ||
Using the `solrClient` for raw communication with solr. | ||
See adapter [test]('//test/../../test/additional.test.ts') how to: | ||
- `create` and `delete` a Solr core | ||
- `add`, 'update' and `delete` the Solr core schema | ||
- `add` and `delete` the Solr core config request handler and components | ||
Modify Solr schema: | ||
```js | ||
const options = { | ||
host: 'http://localhost:8983/solr', | ||
core: 'gettingstarted', | ||
} | ||
```Javascript | ||
service.Model.post('schema',{"add-field":{name:"age",type:"pint"}}); | ||
``` | ||
const client = solrClient('http://localhost:8983/solr'); | ||
await client.post('/admin/cores', { params: {...createCore, name: name} }) | ||
await client.post(`/${core}/schema`, { data: addSchema }); | ||
await client.post(`/${core}/config`, { data: addConfig }); | ||
Get Solr config information: | ||
```Javascript | ||
service.Model.get('config'); | ||
``` | ||
Modify Solr config: | ||
## License | ||
```Javascript | ||
service.Model.post('config',{"add-requesthandler":{...}}); | ||
``` | ||
Copyright (c) 2022 | ||
## Use a different HTTP Client | ||
The MIT License (MIT) | ||
This Adapter offers a `node-fetch` interface for a maximum on HTTP Client comfort and `undici` for maximum (100% compared to node-fetch) in performance. | ||
If you like to go with your favorite one: | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
```Javascript | ||
class CustomClient { | ||
constructor(HTTPModule, conn) {} | ||
get(api, params = {}) {} | ||
post(api, data, params = {}) {} | ||
}; | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
const options = { | ||
Model: CustomClient(HTTPModule, solrServer), | ||
paginate: {}, | ||
events: ['testing'] | ||
}; | ||
app.service('solr', new Service(options)) | ||
``` | ||
## Contributing | ||
If you find a bug or something to improve i will be happy to see your PR! | ||
When adding a new feature, please make sure you write tests for it with decent coverage as well. | ||
## TODO | ||
- Hook Examples | ||
- Schema Migration Hook (drop,alter,safe) | ||
- Json Hook Store Data as JSON | ||
- Validation Hook | ||
- Spellcheck | ||
- Suggester | ||
- MoreLikeThis | ||
## Changelog | ||
**2.3.0** | ||
**2.2.0** | ||
- complete refactoring | ||
- implement @feathers/adapter-tests | ||
## License | ||
Copyright (c) 2015 | ||
Licensed under the [MIT license](LICENSE). | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
177
src/index.ts
@@ -1,156 +0,49 @@ | ||
import { NotFound, MethodNotAllowed } from '@feathersjs/errors'; | ||
import { NullableId, Id } from '@feathersjs/feathers'; | ||
import { _ } from '@feathersjs/commons'; | ||
import { AdapterService, ServiceOptions, InternalServiceMethods, AdapterParams, select } from '@feathersjs/adapter-commons'; | ||
import { solrClient, SolrClient } from './client'; | ||
import { responseFind, responseGet } from './response'; | ||
import { addIds, jsonQuery, patchQuery, deleteQuery } from './query'; | ||
export const escapeFn = (key: string, value: any) => { | ||
return { key, value } | ||
} | ||
import type { AdapterParams, PaginationOptions } from '@feathersjs/adapter-commons'; | ||
import type { Paginated, ServiceMethods, Id, NullableId } from '@feathersjs/feathers'; | ||
import { SolrAdapter } from './adapter' | ||
export interface SolrServiceOptions extends ServiceOptions { | ||
host: string; | ||
core: string; | ||
commit?: { | ||
softCommit?: boolean; | ||
commitWithin?: number; | ||
overwrite?: boolean | ||
}; | ||
queryHandler?: string; | ||
updateHandler?: string; | ||
defaultSearch?: any; | ||
defaultParams?: any; | ||
createUUID?: boolean; | ||
escapeFn?: (key: string, value: any) => { key: string, value: any }; | ||
requestOptions: { timeout: 10 }; | ||
} | ||
export * from './adapter' | ||
export class Service<T = any, D = Partial<T>> extends AdapterService<T, D> implements InternalServiceMethods<T> { | ||
options: SolrServiceOptions; | ||
client: SolrClient; | ||
queryHandler: string; | ||
updateHandler: string; | ||
constructor (options: Partial<SolrServiceOptions>) { | ||
const { host, core, requestOptions, ...opts } = options; | ||
super(_.extend({ | ||
id: 'id', | ||
commit: { | ||
softCommit: true, | ||
commitWithin: 10000, | ||
overwrite: true | ||
}, | ||
queryHandler: '/query', | ||
updateHandler: '/update/json', | ||
defaultSearch: {}, | ||
defaultParams: { echoParams: 'none' }, | ||
createUUID: true, | ||
escapeFn | ||
}, opts)); | ||
this.queryHandler = `/${core}${this.options.queryHandler}`; | ||
this.updateHandler = `/${core}${this.options.updateHandler}`; | ||
this.client = solrClient(host, requestOptions) | ||
export class SolrService<T = any, D = Partial<T>, P extends AdapterParams = AdapterParams> | ||
extends SolrAdapter<T, D, P> | ||
implements ServiceMethods<T | Paginated<T>, D, P> | ||
{ | ||
async find(params?: P & { paginate?: PaginationOptions }): Promise<Paginated<T>> | ||
async find(params?: P & { paginate: false }): Promise<T[]> | ||
async find(params?: P): Promise<Paginated<T> | T[]> | ||
async find(params?: P): Promise<Paginated<T> | T[]> { | ||
return this._find(params) as any | ||
} | ||
_getOrFind (id: Id, params: AdapterParams) { | ||
if (id !== null) return this._get(id, params); | ||
return this._find( | ||
Object.assign(params, { | ||
paginate: false | ||
}) | ||
); | ||
async get(id: NullableId, params?: P): Promise<T> | ||
async get(id: Id, params?: P): Promise<T> | ||
async get(id: Id | NullableId, params?: P): Promise<T> { | ||
return this._get(id as Id, params) | ||
} | ||
async _get (id: Id, params: AdapterParams = {}) { | ||
const { query, filters, paginate } = this.filterQuery(params); | ||
const solrQuery = jsonQuery(id, filters, query, paginate, this.options.escapeFn); | ||
const response = await this.client.post(this.queryHandler, { data: solrQuery }) | ||
if (response.response.numFound === 0) throw new NotFound(`No record found for id '${id}'`); | ||
const result = responseGet(response); | ||
return result; | ||
async create(data: D, params?: P): Promise<T> | ||
async create(data: D[], params?: P): Promise<T[]> | ||
async create(data: D | D[], params?: P): Promise<T | T[]> { | ||
return this._create(data, params) | ||
} | ||
async _find (params: AdapterParams = {}) { | ||
const { query, filters, paginate } = this.filterQuery(params); | ||
const solrQuery = jsonQuery(null, filters, query, paginate, this.options.escapeFn); | ||
const response = await this.client.post(this.queryHandler, { data: solrQuery }) | ||
const result = responseFind(filters, paginate, response); | ||
return result; | ||
async update(id: Id, data: D, params?: P): Promise<T> | ||
async update(id: NullableId, data: D, params?: P): Promise<T> | ||
async update(id: Id | NullableId, data: D, params?: P): Promise<T> { | ||
return this._update(id as Id, data, params) | ||
} | ||
async _create (data: Partial<T> | Partial<T>[], params: AdapterParams = {}): Promise<T | T[]> { | ||
const sel = select(params, this.id); | ||
if (_.isEmpty(data)) throw new MethodNotAllowed('Data is empty'); | ||
let dataToCreate: any | any[] = Array.isArray(data) ? [...data] : [{ ...data }]; | ||
if (this.options.createUUID) { | ||
dataToCreate = addIds(dataToCreate, this.options.id); | ||
} | ||
await this.client.post(this.updateHandler, { data: dataToCreate, params: this.options.commit }); | ||
return sel(Array.isArray(data) ? dataToCreate : dataToCreate[0]); | ||
async patch(id: NullableId, data: Partial<D>, params?: P): Promise<T> | ||
async patch(id: Id, data: Partial<D>, params?: P): Promise<T> | ||
async patch(id: null, data: Partial<D>, params?: P): Promise<T[]> | ||
async patch(id: NullableId | NullableId, data: Partial<D>, params?: P): Promise<T | T[]> { | ||
return this._patch(id as NullableId, data, params) | ||
} | ||
async _update (id: NullableId, data: T, params: AdapterParams = {}) { | ||
const sel = select(params, this.id); | ||
await this._getOrFind(id, params); | ||
const dataToUpdate: any = id && !Array.isArray(data) ? [{ id, ...data }] : data; | ||
await this.client.post(this.updateHandler, { data: dataToUpdate, params: this.options.commit }); | ||
return this._getOrFind(id, params).then(res => sel(_.omit(res, 'score', '_version_'))); | ||
async remove(id: Id, params?: P): Promise<T> | ||
async remove(id: NullableId, params?: P): Promise<T> | ||
async remove(id: null, params?: P): Promise<T[]> | ||
async remove(id: NullableId | NullableId, params?: P): Promise<T | T[]> { | ||
return this._remove(id as NullableId, params) | ||
} | ||
async _patch (id: NullableId, data: Partial<T>, params: AdapterParams = {}) { | ||
const sel = select(params, this.id); | ||
const dataToPatch = await this._getOrFind(id, params); | ||
const { ids, patchData } = patchQuery(dataToPatch, data, this.id); | ||
await this.client.post(this.updateHandler, { data: patchData, params: this.options.commit }); | ||
const result: any = await this._find({ query: { id: { $in: ids } } }); | ||
if (result.data) return sel(ids.length === 1 ? result.data[0] : result.data) | ||
return sel(ids.length === 1 ? result[0] : result) | ||
} | ||
async _remove (id: NullableId, params: AdapterParams = {}): Promise<T | T[]> { | ||
const sel = select(params, this.id); | ||
const dataToDelete = await this._getOrFind(id, params); | ||
const { query } = this.filterQuery(params); | ||
const queryToDelete = deleteQuery(id, query, this.options.escapeFn); | ||
await this.client.post(this.updateHandler, { data: queryToDelete, params: this.options.commit }); | ||
return sel(dataToDelete); | ||
} | ||
} | ||
export default function service (options: Partial<SolrServiceOptions>) { | ||
return new Service(options); | ||
} |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
286718
88
1204
1
451
3