Skip to content

Commit ade5e8a

Browse files
committed
feat: add solr.config function and and configAutoEnableFields
function for convenience. Also refactor some utility functions to a separete `src/utils.js` file.
1 parent b9dda8b commit ade5e8a

3 files changed

Lines changed: 135 additions & 53 deletions

File tree

src/index.js

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22
/**
33
* Support for type checking and intellisense in vscode:
44
* @typedef {import("./solr").SolrConfig} SolrConfig
5+
* @typedef {import("./solr").ConfigRequest} ConfigRequest
56
* @typedef {import("./solr").SolrData} SolrData
67
* @typedef {import("./solr").SolrDocument} SolrDocument
78
* @typedef {import("./solr").SolrResponse} SolrResponse
8-
* @typedef {import("./solr").DeleteQuery} DeleteQuery
9+
* @typedef {import("./solr").DeleteRequest} DeleteRequest
910
* @typedef {import("./solr").FieldProperties} FieldProperties
1011
* @typedef {import("./solr").FieldTypeProperties} FieldTypeProperties
11-
* @typedef {import("./solr").SolrQuery} SolrQuery
12+
* @typedef {import("./solr").QueryRequest} QueryRequest
1213
*/
1314

1415
const url = require("url")
1516
const { default: axios } = require("axios")
17+
const { mergeConfig, ensureArray, isEmptyObject } = require("./utils")
1618

1719
/** @type {SolrConfig} */
1820
const defaultConfig = {
@@ -30,12 +32,6 @@ const defaultConfig = {
3032
apiPrefix: "api/cores"
3133
}
3234

33-
/** @type {(x:object) => object|object[]} */
34-
const ensureArray = x => (Object(x) instanceof Array ? x : [x])
35-
36-
const isEmptyObject = obj =>
37-
Object.keys(obj).length === 0 && obj.constructor === Object
38-
3935
/** @type {(config:SolrConfig) => (path:string) => (data:SolrData) => Promise<SolrResponse>} */
4036
const solrPost = config => path => async data => {
4137
const { core, apiPrefix } = config
@@ -45,9 +41,9 @@ const solrPost = config => path => async data => {
4541
})
4642

4743
if (config.debug) {
48-
const dataPart = isEmptyObject(data) ? "" : ` -d '${JSON.stringify(data)}'`
44+
const dataPart = isEmptyObject(data) ? "" : `-d '${JSON.stringify(data)}'`
4945
console.debug(
50-
`\n$ curl -X POST '${solrUrl}' -H 'Content-Type: application/json'${dataPart}\n`
46+
`\ncurl -X POST '${solrUrl}' -H 'Content-Type: application/json' ${dataPart}\n`
5147
)
5248
}
5349

@@ -58,28 +54,6 @@ const solrPost = config => path => async data => {
5854
return response.data
5955
}
6056

61-
/**
62-
* Perform an operation on solr schema.
63-
* @see https://lucene.apache.org/solr/guide/7_5/schema-api.html#modify-the-schema
64-
* @param {SolrConfig} config
65-
*/
66-
const solrSchema = config => op => data =>
67-
solrPost(config)("schema")({ [op]: data })
68-
69-
const mergeConfig = (a, b) => mergeConfigImpure({ ...a }, b)
70-
71-
function mergeConfigImpure (target, source) {
72-
for (let k in source) {
73-
const objOrScalar = target[k]
74-
if (objOrScalar != null && objOrScalar.constructor === Object) {
75-
mergeConfigImpure(objOrScalar, source[k]) // recurse on objects
76-
} else {
77-
target[k] = source[k] // assign scalar value
78-
}
79-
}
80-
return target
81-
}
82-
8357
/** @param {SolrConfig} userConfig */
8458
const prepareSolrClient = (userConfig = {}) => {
8559
const config = mergeConfig(defaultConfig, userConfig)
@@ -88,10 +62,19 @@ const prepareSolrClient = (userConfig = {}) => {
8862
if (!config.core) {
8963
throw Error("missing 'core' parameter in your config")
9064
}
65+
66+
// some functions require /solr prefix instead of /api/cores/
67+
const configWithSolrPrefix = { ...config, apiPrefix: "solr" }
68+
69+
const solrConfigRequest = solrPost(configWithSolrPrefix)("config")
70+
71+
const solrSchemaRequest = op => data =>
72+
solrPost(config)("schema")({ [op]: data })
73+
9174
// now creating the API
9275
return {
9376
ping: () =>
94-
solrPost({ ...config, apiPrefix: "solr" })("admin/ping")({})
77+
solrPost(configWithSolrPrefix)("admin/ping")({})
9578
.then(value => {
9679
return value.status === "OK"
9780
})
@@ -100,26 +83,39 @@ const prepareSolrClient = (userConfig = {}) => {
10083
/** @param {SolrDocument | SolrDocument[]} data */
10184
add: data => solrPost(config)("update")(ensureArray(data)),
10285

103-
/** @param {DeleteQuery} deleteQuery */
86+
/** @param {DeleteRequest} deleteQuery */
10487
delete: deleteQuery =>
105-
solrPost({ ...config, apiPrefix: "solr" })("update")({
88+
solrPost(configWithSolrPrefix)("update")({
10689
delete: deleteQuery
10790
}),
10891

10992
/** @type {(data:FieldProperties) => Promise<SolrResponse>} */
110-
addField: solrSchema(config)("add-field"),
93+
addField: solrSchemaRequest("add-field"),
11194

11295
/** @type {(data:FieldTypeProperties) => Promise<SolrResponse>} */
113-
addFieldType: solrSchema(config)("add-field-type"),
96+
addFieldType: solrSchemaRequest("add-field-type"),
11497

11598
/** @type {({name:string}) => Promise<SolrResponse>} */
116-
deleteField: solrSchema(config)("delete-field"),
99+
deleteField: solrSchemaRequest("delete-field"),
117100

118101
/** @type {({name:string}) => Promise<SolrResponse>} */
119-
deleteFieldType: solrSchema(config)("delete-field-type"),
120-
121-
/** @type {(data:SolrQuery) => Promise<SolrResponse>} */
122-
query: solrPost(config)("query")
102+
deleteFieldType: solrSchemaRequest("delete-field-type"),
103+
104+
/** @type {(data:QueryRequest) => Promise<SolrResponse>} */
105+
query: solrPost(config)("query"),
106+
107+
config: solrConfigRequest,
108+
109+
/**
110+
* Convenience function to set the `update.autoCreateFields` user property.
111+
* @param {boolean} enable
112+
*/
113+
configAutoEnableFields: enable =>
114+
solrConfigRequest({
115+
"set-user-property": {
116+
"update.autoCreateFields": enable ? "true" : "false"
117+
}
118+
})
123119
}
124120
}
125121

src/solr.d.ts

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -244,15 +244,6 @@ type SolrDataValue = any
244244
// | SolrFragmentWithId
245245
// | SolrFragmentWithId[]
246246

247-
/**
248-
* This type definition contains just the most important parts.
249-
*/
250-
interface SolrResponseHeader {
251-
params?: object
252-
status: number
253-
QTime: number
254-
}
255-
256247
interface TermsFacet {
257248
buckets: { val: string; count: number }[]
258249
}
@@ -303,6 +294,15 @@ export interface SolrDocument {
303294
[key: string]: SolrDataValue | SolrData
304295
}
305296

297+
/**
298+
* This type definition contains just the most important parts.
299+
*/
300+
interface SolrResponseHeader {
301+
params?: object
302+
status: number
303+
QTime: number
304+
}
305+
306306
/**
307307
* This type definition contains just the most important parts.
308308
*/
@@ -349,7 +349,7 @@ export interface SolrException {
349349
stack: string
350350
}
351351

352-
export interface SolrQuery {
352+
export interface QueryRequest {
353353
query?
354354
filter?
355355
start?
@@ -379,7 +379,67 @@ export interface SolrConfig {
379379
apiPrefix?: string
380380
}
381381

382-
export interface DeleteQuery {
382+
export interface DeleteRequest {
383383
id?: string
384384
query?: any
385385
}
386+
387+
export type ConfigRequest = {
388+
// Commands for Common Properties:
389+
// https://lucene.apache.org/solr/guide/7_5/config-api.html#commands-for-common-properties
390+
391+
"set-property"?: { [property: string]: any }
392+
"unset-property"?: string
393+
394+
// Basic Commands for Components
395+
// https://lucene.apache.org/solr/guide/7_5/config-api.html#basic-commands-for-components
396+
397+
"add-requesthandler"?: any
398+
"update-requesthandler"?: any
399+
"delete-requesthandler"?: any
400+
"add-searchcomponent"?: any
401+
"update-searchcomponent"?: any
402+
"delete-searchcomponent"?: any
403+
"add-initparams"?: any
404+
"update-initparams"?: any
405+
"delete-initparams"?: any
406+
"add-queryresponsewriter"?: any
407+
"update-queryresponsewriter"?: any
408+
"delete-queryresponsewriter"?: any
409+
410+
// Advanced Commands for Components:
411+
// https://lucene.apache.org/solr/guide/7_5/config-api.html#advanced-commands-for-components
412+
413+
"add-queryparser"?: any
414+
"update-queryparser"?: any
415+
"delete-queryparser"?: any
416+
"add-valuesourceparser"?: any
417+
"update-valuesourceparser"?: any
418+
"delete-valuesourceparser"?: any
419+
"add-transformer"?: any
420+
"update-transformer"?: any
421+
"delete-transformer"?: any
422+
"add-updateprocessor"?: any
423+
"update-updateprocessor"?: any
424+
"delete-updateprocessor"?: any
425+
"add-queryconverter"?: any
426+
"update-queryconverter"?: any
427+
"delete-queryconverter"?: any
428+
"add-listener"?: any
429+
"update-listener"?: any
430+
"delete-listener"?: any
431+
"add-runtimelib"?: any
432+
"update-runtimelib"?: any
433+
"delete-runtimelib"?: any
434+
435+
// Commands for User-Defined Properties:
436+
// https://lucene.apache.org/solr/guide/7_5/config-api.html#commands-for-user-defined-properties
437+
"set-user-property"?: {
438+
"update.autoCreateFields"?: TrueOrFalseString // boolean does not work, perhaps a bug in solr
439+
[variableName: string]: any
440+
}
441+
"unset-user-property"?: string
442+
}
443+
444+
type TrueOrFalseString = "true" | "false"
445+
type OnOrOffString = "on" | "off"

src/utils.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const mergeConfig = (a, b) => mergeConfigImpure({ ...a }, b)
2+
3+
function mergeConfigImpure (target, source) {
4+
for (let k in source) {
5+
const objOrScalar = target[k]
6+
if (objOrScalar != null && objOrScalar.constructor === Object) {
7+
mergeConfigImpure(objOrScalar, source[k]) // recurse on objects
8+
} else {
9+
target[k] = source[k] // assign scalar value
10+
}
11+
}
12+
return target
13+
}
14+
15+
/** @type {(x:object) => object|object[]} */
16+
const ensureArray = x => (Object(x) instanceof Array ? x : [x])
17+
18+
const isEmptyObject = obj =>
19+
Object.keys(obj).length === 0 && obj.constructor === Object
20+
21+
module.exports = {
22+
mergeConfig,
23+
mergeConfigImpure,
24+
ensureArray,
25+
isEmptyObject
26+
}

0 commit comments

Comments
 (0)