MCPcopy Index your code
hub / github.com/node-config/node-config / makeImmutable

Method makeImmutable

lib/util.js:159–230  ·  view source on GitHub ↗

* Make a javascript object immutable (assuring it cannot be changed from the current value) * * All attributes of that object are made immutable, including properties of contained * objects, recursively. * * This operation cannot be undone. * * Example: * *

(object)

Source from the content-addressed store, hash-verified

157 * @return object {Object} - The original object is returned - for chaining.
158 */
159 static makeImmutable(object) {
160 if (Buffer.isBuffer(object)) {
161 return object;
162 }
163
164 for (let propertyName of Object.keys(object)) {
165 let value = object[propertyName];
166
167 if (value instanceof RawConfig) {
168 Object.defineProperty(object, propertyName, {
169 value: value.resolve(),
170 writable: false,
171 configurable: false
172 });
173 } else if (Array.isArray(value)) {
174 // Ensure object items of this array are also immutable.
175 for (let item of value) {
176 if (this.isObject(item) || Array.isArray(item)) {
177 this.makeImmutable(item);
178 }
179 }
180
181 Object.defineProperty(object, propertyName, {
182 value: Object.freeze(value)
183 });
184 } else {
185 // Call recursively if an object.
186 if (this.isObject(value)) {
187 // Create a proxy, to capture user updates of configuration options, and throw an exception for awareness, as per:
188 // https://github.com/lorenwest/node-config/issues/514
189 value = new Proxy(this.makeImmutable(value), {
190 get(target, property, receiver) {
191 // Bypass proxy receiver for properties directly on the target (e.g., RegExp.prototype.source)
192 // or properties that are not functions to prevent errors related to internal object methods.
193 if (Object.hasOwn(target, property) || (property in target && typeof target[property] !== 'function')) {
194 return Reflect.get(target, property);
195 }
196
197 // Otherwise, use the proxy receiver to handle the property access
198 const ref = Reflect.get(target, property, receiver);
199
200 // Binds the method's `this` context to the target object (e.g., Date.prototype.toISOString)
201 // to ensure it behaves correctly when called on the proxy.
202 if (typeof ref === 'function') {
203 return ref.bind(target);
204 }
205 return ref;
206 },
207 set(target, name) {
208 const message = (Reflect.has(target, name) ? 'update' : 'add');
209 // Notify the user.
210 throw Error(`Can not ${message} runtime configuration property: "${name}". Configuration objects are immutable unless ALLOW_CONFIG_MUTATIONS is set.`)
211 }
212 });
213 }
214
215 // Check if property already has writable: false and configurable: false
216 const currentDescriptor = Object.getOwnPropertyDescriptor(object, propertyName);

Callers 5

2-config-test.jsFile · 0.45
0-util.jsFile · 0.45
config.tsFile · 0.45
index.jsFile · 0.45

Calls 2

isObjectMethod · 0.95
resolveMethod · 0.80

Tested by

no test coverage detected