-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
114 lines (104 loc) · 4.47 KB
/
Copy pathindex.js
File metadata and controls
114 lines (104 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* @file
*
* Support for things like File uploads will need to be added on top of regular
* APIs as these require custom headers and binary bodies rather than serialized
* JSON.
*
* Devour's API provides a lot of JSON:API specific serialization and request
* generation out of the box which the Drupal community can build on top of to
* extend and streamline usage of the JSON:API module.
*/
const JsonApi = require('devour-client')
const httpProtocol = () => typeof window !== 'undefined' ? window.location.protocol : 'https:'
function DevourDrupal({ logger = true } = {}) {
this.devour = new JsonApi({ logger, pluralize: false })
this.bearer = function (token) {
this.devour.headers['Authorization'] = token ? `Bearer ${token}` : null
}
this.init = function (openApi) {
return this.devour.axios
.get(openApi)
.then(response => {
this.devour.apiUrl = `${httpProtocol()}//${response.data.host}${response.data.basePath}`
Object.keys(response.data.definitions)
.map(key => {
try {
const modelParts = key.split('--')
const definition = response.data.definitions[key]
const attributes = definition.properties.data.properties.attributes
const relationships = definition.properties.data.properties.relationships
const requiredAttributes = definition.properties.data.properties.attributes.required || []
const requiredRelationships = definition.properties.data.properties.relationships.required || []
this.devour.define(key, {
...Object.keys(attributes.properties)
.map(key => ({
key,
value: attributes.properties[key]
}))
.reduce((prev, curr) => {
let type
switch (curr.value.type) {
case 'boolean':
type = false
break
case 'string':
type = ''
break
case 'float':
case 'integer':
case 'number':
type = 0
break
case 'object':
type = {}
break
case 'array':
type = []
break
}
prev[curr.key] = type
return prev
}, {}),
...Object.keys(relationships.properties)
.map(key => {
const relationship = relationships.properties[key]
const relationshipType = relationship.properties.data.type
let relationshipModel
if (relationshipType === 'array') {
relationshipModel = relationship.properties.data.items.properties.type.enum
} else {
relationshipModel = relationship.properties.data.properties.type.enum
}
if (relationshipModel) {
return {
key,
value: {
jsonApi: relationshipType === 'array' ? 'hasMany' : 'hasOne',
type: relationshipModel.length === 1 ? relationshipModel[0] : undefined,
types: relationshipModel.length === 1 ? undefined : relationshipModel
}
}
}
})
.filter(item => !!item)
.reduce((prev, curr) => {
prev[curr.key] = curr.value
return prev
}, {}),
}, {
collectionPath: `${modelParts[0]}/${modelParts[1]}`,
required: {
attributes: requiredAttributes,
relationships: requiredRelationships
}
})
} catch (err) {
console.error(`Failed to define model for ${key}`, err)
}
})
})
.then(() => this)
}
}
module.exports.DevourDrupal = DevourDrupal