Skip to content

Commit 253f335

Browse files
committed
feat: add type annotations, new solr functions
BREAKING CHANGE: From now on, the `core` parameter needs to be passed through the `config` parameter. This simplifies the API by removing special cases. The provided typings provide better user experience when developing in an IDE such as vscode.
1 parent 9d3604e commit 253f335

2 files changed

Lines changed: 101 additions & 50 deletions

File tree

.eslintrc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
{
2-
"extends": [
3-
"standard"
4-
],
2+
"extends": ["standard"],
53
"env": {
64
"mocha": true
75
},
86
"rules": {
97
"indent": "off",
108
"quotes": ["error", "double"]
119
}
12-
}
10+
}

src/index.js

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,64 @@
1+
// @ts-check
2+
/**
3+
* @typedef {typeof defaultConfig} SolrConfig
4+
* @typedef {import(".").SolrDocument} SolrDocument
5+
* @typedef {import(".").SolrData} SolrData
6+
* @typedef {import(".").SolrResponse} SolrResponse
7+
* @typedef {import("axios").AxiosError} AxiosError
8+
* @typedef {import(".").SolrException} SolrException
9+
*/
10+
111
const url = require("url")
2-
const axios = require("axios")
12+
const { default: axios } = require("axios")
313

414
const defaultConfig = {
515
hostname: "localhost",
616
port: 8983,
7-
protocol: "http"
17+
protocol: "http",
18+
debug: false,
19+
core: "",
20+
apiPrefix: "api/cores"
821
}
922

10-
const ensureArray = x => (x instanceof Array ? x : [x])
11-
12-
const solrPost = config => path => (data, coreOpt = "") => {
13-
const core = coreOpt || config.core
14-
if (!core) {
15-
throw new Error("core not specified")
16-
}
23+
/** @type {(x:object) => object|object[]} */
24+
const ensureArray = x => (Object(x) instanceof Array ? x : [x])
1725

26+
/**
27+
* @type {(config:SolrConfig) => (path:string) => (data:SolrData) => Promise<SolrResponse>}
28+
*/
29+
const solrPost = config => path => async data => {
30+
const { core, apiPrefix } = config
1831
const solrUrl = url.format({
1932
...defaultConfig,
2033
...config, // overrides defalt config
21-
pathname: `solr/${core}/${path}`,
34+
pathname: `${apiPrefix}/${core}/${path}`,
2235
query: {
2336
wt: "json",
2437
overwrite: true,
2538
commitWithin: 1000
2639
}
2740
})
2841

29-
return axios
30-
.post(solrUrl, ensureArray(data), {
31-
headers: {
32-
"content-type": "application/json; charset=utf-8",
33-
accept: "application/json; charset=utf-8"
34-
}
35-
})
36-
.then(r => r.data)
42+
if (config.debug) {
43+
console.debug(`\n$ curl '${solrUrl}' -d '${JSON.stringify(data)}'\n`)
44+
}
45+
46+
const response = await axios.post(solrUrl, data, {
47+
headers: {
48+
"content-type": "application/json; charset=utf-8",
49+
accept: "application/json; charset=utf-8"
50+
}
51+
})
52+
53+
return response.data
3754
}
3855

39-
const solrGet = config => path => (query = {}, coreOpt = "") => {
40-
const core = coreOpt || query.core || config.core
41-
if (!core) {
42-
throw new Error("core not specified")
43-
}
56+
/**
57+
* @type {(config:SolrConfig) => (path:string) => (query:any) => Promise<SolrResponse>}
58+
*/
59+
const solrGet = config => path => async query => {
60+
const core = query.core || config.core
61+
const { apiPrefix } = config
4462

4563
// we don't want to alter the query structure
4664
const queryWithoutCore = { ...query }
@@ -49,38 +67,73 @@ const solrGet = config => path => (query = {}, coreOpt = "") => {
4967
const solrUrl = url.format({
5068
...defaultConfig,
5169
...config, // overrides defalt config
52-
pathname: `solr/${core}/${path}`,
53-
query: queryWithoutCore // DO NOT rename the query parameter!
70+
pathname: `${apiPrefix}/${core}/${path}`,
71+
query: queryWithoutCore // DO NOT rename the "query" parameter!
5472
})
5573

5674
if (config.debug) {
57-
console.debug("SOLR QUERY:")
58-
console.debug(query)
59-
console.debug("SOLR HTTP GET: " + solrUrl)
75+
console.debug(`\n$ curl '${solrUrl}'\n`)
6076
}
6177

62-
return axios(solrUrl).then(r => r.data)
78+
const response = await axios(solrUrl)
79+
return response.data
6380
}
6481

82+
/**
83+
* Perform an operation on solr schema.
84+
* @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#modify-the-schema
85+
* @param {SolrConfig} config
86+
*/
87+
const solrSchema = config => op => data =>
88+
solrPost(config)("schema")({ [op]: data })
89+
90+
/** @param {SolrConfig} config */
6591
const prepareSolrClient = config => ({
92+
ping: () =>
93+
solrGet({ ...config, apiPrefix: "solr" })("admin/ping")({})
94+
.then(value => {
95+
return value.status === "OK"
96+
})
97+
.catch(() => false),
98+
99+
/**
100+
* @param {SolrDocument} data */
101+
add: data => solrPost(config)("update")(ensureArray(data)),
102+
103+
/**
104+
* @type {(data: import(".").FieldProperties) => Promise<SolrResponse>}
105+
* @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#add-a-new-field
106+
*/
107+
addField: solrSchema(config)("add-field"),
108+
109+
/**
110+
* @type {(data:import(".").FieldTypeProperties) => Promise<SolrResponse>}
111+
* @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#add-a-new-field-type
112+
*/
113+
addFieldType: solrSchema(config)("add-field-type"),
114+
115+
/**
116+
* @type {({name:string}) => Promise<SolrResponse>}
117+
*/
118+
deleteField: solrSchema(config)("delete-field"),
119+
120+
/**
121+
* @type {({name:string}) => Promise<SolrResponse>}
122+
*/
123+
deleteFieldType: solrSchema(config)("delete-field-type"),
124+
125+
/**
126+
* @type {(query:import(".").SolrSelect) => Promise<SolrResponse>}
127+
*/
66128
select: solrGet(config)("select"),
67-
ping: core => solrGet(config)("admin/ping")({ core }),
68-
add: solrPost(config)("update"),
69-
delete: () => Error("not implemented yet"),
70-
commit: () => Error("not implemented yet"),
71-
rollback: () => Error("not implemented yet"),
72-
spell: () => Error("not implemented yet"),
73-
optimize: () => Error("not implemented yet"),
74-
realTimeGet: () => Error("not implemented yet"),
75-
facet: (jsonFacet, coreOpt = "") =>
76-
solrGet(config)("query")(
77-
{
78-
q: "*:*", // filtering will be implemented later
79-
rows: 0,
80-
"json.facet": JSON.stringify(jsonFacet)
81-
},
82-
coreOpt
83-
)
129+
130+
facet: (facetMap, filterArr = []) =>
131+
solrPost(config)("query")({
132+
query: "*:*",
133+
limit: "0",
134+
filter: filterArr,
135+
facet: facetMap
136+
})
84137
})
85138

86139
module.exports = {

0 commit comments

Comments
 (0)