json-rest-api 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export { RestApiPlugin } from './plugins/core/rest-api-plugin.js'
|
|
|
13
13
|
export { FileHandlingPlugin } from './plugins/core/file-handling-plugin.js'
|
|
14
14
|
export { CorsPlugin } from './plugins/core/rest-api-cors-plugin.js'
|
|
15
15
|
export { AccessPlugin } from './plugins/core/rest-api-access.js'
|
|
16
|
+
export { LabelPlugin } from './plugins/core/rest-api-label-plugin.js'
|
|
16
17
|
|
|
17
18
|
// Database plugins
|
|
18
19
|
export { RestApiKnexPlugin } from './plugins/core/rest-api-knex-plugin.js'
|
package/package.json
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export const LabelPlugin = {
|
|
2
|
+
name: 'rest-api-label',
|
|
3
|
+
dependencies: ['rest-api'],
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Install the label plugin (adds a computed 'label' attribute to all resources)
|
|
7
|
+
* @param {object} deps Injected dependencies from json-rest-api
|
|
8
|
+
* @param {function} deps.addHook - Register hooks
|
|
9
|
+
* @param {object} deps.pluginOptions - Plugin options
|
|
10
|
+
*/
|
|
11
|
+
async install ({ addHook, pluginOptions = {} }) {
|
|
12
|
+
const opts = {
|
|
13
|
+
preferNameFields: ['name', 'title'],
|
|
14
|
+
disable: false,
|
|
15
|
+
...pluginOptions
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function pickLabelFieldFromFields (fields, searchSchema) {
|
|
19
|
+
const byGlobal = Object.keys(searchSchema || {}).find(k => searchSchema[k]?.globalSearch)
|
|
20
|
+
if (byGlobal) return byGlobal
|
|
21
|
+
for (const key of opts.preferNameFields) {
|
|
22
|
+
if (fields?.[key]?.type === 'string') return key
|
|
23
|
+
}
|
|
24
|
+
const firstString = Object.entries(fields || {}).find(([_, def]) => def?.type === 'string')?.[0]
|
|
25
|
+
if (firstString) return firstString
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Inject as a computed field AFTER schemas are compiled,
|
|
30
|
+
// so it lives in schemaInfo.computed and not in schemaStructure
|
|
31
|
+
addHook(
|
|
32
|
+
'scope:added',
|
|
33
|
+
'rest-api-label:inject-computed',
|
|
34
|
+
{ afterFunction: 'compileResourceSchemas' },
|
|
35
|
+
({ context, scopes }) => {
|
|
36
|
+
if (opts.disable) return
|
|
37
|
+
const { scopeName } = context
|
|
38
|
+
const scope = scopes?.[scopeName]
|
|
39
|
+
const schemaInfo = scope?.vars?.schemaInfo
|
|
40
|
+
if (!schemaInfo) return
|
|
41
|
+
|
|
42
|
+
// Respect explicit label already defined by resource
|
|
43
|
+
if (schemaInfo.computed?.label || schemaInfo.schemaStructure?.label) {
|
|
44
|
+
// If label accidentally made it into schemaStructure, remove it
|
|
45
|
+
if (schemaInfo.schemaStructure?.label) delete schemaInfo.schemaStructure.label
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const structure = schemaInfo.schemaStructure || {}
|
|
50
|
+
const searchStruct = schemaInfo.searchSchemaStructure || {}
|
|
51
|
+
const idProp = schemaInfo.idProperty || 'id'
|
|
52
|
+
|
|
53
|
+
const pick = pickLabelFieldFromFields(structure, searchStruct)
|
|
54
|
+
|
|
55
|
+
schemaInfo.computed = schemaInfo.computed || {}
|
|
56
|
+
schemaInfo.computed.label = {
|
|
57
|
+
type: 'string',
|
|
58
|
+
computed: true,
|
|
59
|
+
...(pick ? { dependencies: [pick] } : {}),
|
|
60
|
+
compute: ({ attributes }) => {
|
|
61
|
+
if (pick) {
|
|
62
|
+
const v = attributes?.[pick]
|
|
63
|
+
if (v != null) return String(v)
|
|
64
|
+
}
|
|
65
|
+
for (const k of opts.preferNameFields) {
|
|
66
|
+
if (attributes?.[k] != null) return String(attributes[k])
|
|
67
|
+
}
|
|
68
|
+
return String(attributes?.[idProp] ?? '')
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|