-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathutils.js
182 lines (170 loc) · 5.47 KB
/
utils.js
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* #### Import members from **@openedx/frontend-base**
*
* @module Utilities
*/
import camelCase from 'lodash.camelcase';
import snakeCase from 'lodash.snakecase';
/**
* This is the underlying function used by camelCaseObject, snakeCaseObject, and convertKeyNames
* above.
*
* Given an object (or array) and a modification function, will perform the function on each key it
* encounters on the object and its tree of children.
*
* The modification function must take a string as an argument and returns a string.
*
* Example:
*
* ```
* (key) => {
* if (key === 'edX') {
* return 'Open edX';
* }
* return key;
* }
* ```
*
* This function will turn any key that matches 'edX' into 'Open edX'. All other keys will be
* passed through unmodified.
*
* Can accept arrays as well as objects, and will perform its conversion on any objects it finds in
* the array.
*
* @param {Object} object
* @param {function} modify
* @returns {Object}
*/
export function modifyObjectKeys(object, modify) {
// If the passed in object is not an Object, return it.
if (
object === undefined
|| object === null
|| (typeof object !== 'object' && !Array.isArray(object))
) {
return object;
}
if (Array.isArray(object)) {
return object.map(value => modifyObjectKeys(value, modify));
}
// Otherwise, process all its keys.
const result = {};
Object.entries(object).forEach(([key, value]) => {
result[modify(key)] = modifyObjectKeys(value, modify);
});
return result;
}
/**
* Performs a deep conversion to camelCase on all keys in the provided object and its tree of
* children. Uses [lodash.camelcase](https://lodash.com/docs/4.17.15#camelCase) on each key. This
* is commonly used to convert snake_case keys in models from a backend server into camelCase keys
* for use in the JavaScript client.
*
* Can accept arrays as well as objects, and will perform its conversion on any objects it finds in
* the array.
*
* @param {Array|Object} object
* @returns {Array|Object}
*/
export function camelCaseObject(object) {
return modifyObjectKeys(object, camelCase);
}
/**
* Performs a deep conversion to snake_case on all keys in the provided object and its tree of
* children. Uses [lodash.snakecase](https://lodash.com/docs/4.17.15#snakeCase) on each key. This
* is commonly used to convert camelCase keys from the JavaScript app into snake_case keys expected
* by backend servers.
*
* Can accept arrays as well as objects, and will perform its conversion on any objects it finds in
* the array.
*
* @param {Array|Object} object
* @returns {Array|Object}
*/
export function snakeCaseObject(object) {
return modifyObjectKeys(object, snakeCase);
}
/**
* Given a map of key-value pairs, performs a deep conversion key names in the specified object
* _from_ the key _to_ the value. This is useful for updating names in an API request to the names
* used throughout a client application if they happen to differ. It can also be used in the
* reverse - formatting names from the client application to names expected by an API.
*
* ```
* import { convertKeyNames } from '@openedx/frontend-base';
*
* // This object can be of any shape or depth with subobjects/arrays.
* const myObject = {
* myKey: 'my value',
* }
*
* const result = convertKeyNames(myObject, { myKey: 'their_key' });
*
* console.log(result) // { their_key: 'my value' }
* ```
*
* Can accept arrays as well as objects, and will perform its conversion on any objects it finds in
* the array.
*
* @param {Array|Object} object
* @param {Object} nameMap
* @returns {Array|Object}
*/
export function convertKeyNames(object, nameMap) {
const transformer = key => (nameMap[key] === undefined ? key : nameMap[key]);
return modifyObjectKeys(object, transformer);
}
/**
* Given a string URL return an element that has been parsed via href.
* This element has the possibility to return different part of the URL.
parser.protocol; // => "http:"
parser.hostname; // => "example.com"
parser.port; // => "3000"
parser.pathname; // => "/pathname/"
parser.search; // => "?search=test"
parser.hash; // => "#hash"
parser.host; // => "example.com:3000"
* https://gist.github.com/jlong/2428561
*
* @param {string}
* @returns {Object}
*/
export function parseURL(url) {
if (typeof document !== 'undefined') {
const parser = document.createElement('a');
parser.href = url;
return parser;
}
return {};
}
/**
* Given a string URL return the path of the URL
*
*
* @param {string}
* @returns {string}
*/
export function getPath(url) {
return typeof document !== 'undefined' ? parseURL(url)?.pathname : '';
}
/**
* *Deprecated*: A method which converts the supplied query string into an object of
* key-value pairs and returns it. Defaults to the current query string - should perform like
* [window.searchParams](https://developer.mozilla.org/en-US/docs/Web/API/URL/searchParams)
*
* @deprecated
* @param {string} [search=global.location.search]
* @returns {Object}
*/
export function getQueryParameters(search = global.location.search) {
const keyValueFragments = search
.slice(search.indexOf('?') + 1)
.split('&')
.filter(hash => hash !== '');
return keyValueFragments.reduce((params, keyValueFragment) => {
const split = keyValueFragment.indexOf('=');
const key = keyValueFragment.slice(0, split);
const value = keyValueFragment.slice(split + 1);
return Object.assign(params, { [key]: decodeURIComponent(value) });
}, {});
}