@hyperfrontend/immutable-api-utils 0.0.1
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/CHANGELOG.md +5 -0
- package/LICENSE.md +21 -0
- package/README.md +192 -0
- package/SECURITY.md +82 -0
- package/bundle/index.iife.js +65 -0
- package/bundle/index.iife.js.map +1 -0
- package/bundle/index.iife.min.js +2 -0
- package/bundle/index.iife.min.js.map +1 -0
- package/bundle/index.umd.js +66 -0
- package/bundle/index.umd.js.map +1 -0
- package/bundle/index.umd.min.js +2 -0
- package/bundle/index.umd.min.js.map +1 -0
- package/index.cjs.js +60 -0
- package/index.cjs.js.map +1 -0
- package/index.d.ts +4 -0
- package/index.d.ts.map +1 -0
- package/index.esm.js +56 -0
- package/index.esm.js.map +1 -0
- package/locked-prop-descriptors.d.ts +3 -0
- package/locked-prop-descriptors.d.ts.map +1 -0
- package/locked-props.d.ts +3 -0
- package/locked-props.d.ts.map +1 -0
- package/locked.d.ts +16 -0
- package/locked.d.ts.map +1 -0
- package/package.json +55 -0
package/CHANGELOG.md
ADDED
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Andrew Redican
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# @hyperfrontend/immutable-api-utils
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://github.com/AndrewRedican/hyperfrontend/actions/workflows/ci-lib-immutable-api-utils.yml">
|
|
5
|
+
<img src="https://img.shields.io/github/actions/workflow/status/AndrewRedican/hyperfrontend/ci-lib-immutable-api-utils.yml?style=flat-square&logo=github&label=build" alt="Build">
|
|
6
|
+
</a>
|
|
7
|
+
<a href="https://codecov.io/gh/AndrewRedican/hyperfrontend/flags?flags%5B0%5D=immutable-api-utils">
|
|
8
|
+
<img src="https://codecov.io/gh/AndrewRedican/hyperfrontend/graph/badge.svg?flag=immutable-api-utils" alt="Coverage">
|
|
9
|
+
</a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/@hyperfrontend/immutable-api-utils">
|
|
11
|
+
<img src="https://img.shields.io/npm/v/@hyperfrontend/immutable-api-utils?style=flat-square" alt="npm version">
|
|
12
|
+
</a>
|
|
13
|
+
</p>
|
|
14
|
+
<p align="center">
|
|
15
|
+
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
16
|
+
<a href="#contributors">
|
|
17
|
+
<img src="https://img.shields.io/github/all-contributors/AndrewRedican/hyperfrontend?color=ee8449&style=flat-square" alt="All Contributors">
|
|
18
|
+
</a>
|
|
19
|
+
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
20
|
+
<a href="https://github.com/AndrewRedican/hyperfrontend/blob/main/LICENSE.md">
|
|
21
|
+
<img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License">
|
|
22
|
+
</a>
|
|
23
|
+
<a href="https://www.npmjs.com/package/@hyperfrontend/immutable-api-utils">
|
|
24
|
+
<img src="https://img.shields.io/npm/dm/@hyperfrontend/immutable-api-utils?style=flat-square" alt="npm downloads">
|
|
25
|
+
</a>
|
|
26
|
+
<a href="https://github.com/AndrewRedican/hyperfrontend">
|
|
27
|
+
<img src="https://img.shields.io/github/stars/AndrewRedican/hyperfrontend?style=flat-square" alt="GitHub stars">
|
|
28
|
+
</a>
|
|
29
|
+
<a href="https://bundlephobia.com/package/@hyperfrontend/immutable-api-utils">
|
|
30
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@hyperfrontend/immutable-api-utils?style=flat-square" alt="Bundle Size">
|
|
31
|
+
</a>
|
|
32
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen?style=flat-square&logo=node.js" alt="Node Version">
|
|
33
|
+
<img src="https://img.shields.io/badge/tree%20shakeable-%E2%9C%93-success?style=flat-square" alt="Tree Shakeable">
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
Decorators and utilities for creating immutable, tamper-proof object APIs.
|
|
37
|
+
|
|
38
|
+
## What is @hyperfrontend/immutable-api-utils?
|
|
39
|
+
|
|
40
|
+
@hyperfrontend/immutable-api-utils provides low-level utilities for locking object properties and methods to prevent modification. Using JavaScript's property descriptors (`Object.defineProperty`), it creates truly immutable APIs where neither values nor method bindings can be altered after definition.
|
|
41
|
+
|
|
42
|
+
The library offers three approaches: a TypeScript decorator (`@locked()`) for class methods, a functional API (`lockedProps()`) for bulk property locking, and descriptor builders (`lockedPropertyDescriptors()`) for granular control. All utilities enforce non-writable, non-configurable descriptors while maintaining correct `this` binding through per-instance caching.
|
|
43
|
+
|
|
44
|
+
### Key Features
|
|
45
|
+
|
|
46
|
+
- **`@locked()` decorator** for TypeScript classes—prevents method overwriting and ensures correct `this` binding
|
|
47
|
+
- **Bulk property locking** via `lockedProps()` for multiple properties in one call
|
|
48
|
+
- **Property descriptor creation** with `lockedPropertyDescriptors()` for custom locking patterns
|
|
49
|
+
- **Per-instance binding cache** to avoid repeated `.bind()` calls
|
|
50
|
+
- **Zero runtime dependencies** - pure JavaScript property descriptor manipulation
|
|
51
|
+
|
|
52
|
+
### Architecture Highlights
|
|
53
|
+
|
|
54
|
+
The `@locked()` decorator uses Symbol-based caching to store bound methods per instance, avoiding the performance cost of repeated `.bind()` calls. Properties are marked `configurable: false` to prevent deletion or descriptor modification, and `writable: false` to block reassignment.
|
|
55
|
+
|
|
56
|
+
## Why Use @hyperfrontend/immutable-api-utils?
|
|
57
|
+
|
|
58
|
+
### Prevents Accidental API Tampering in Shared Contexts
|
|
59
|
+
|
|
60
|
+
When exposing objects to third-party code, plugin systems, or sandboxed environments, you need guarantees that critical methods won't be overwritten. `@locked()` makes methods truly immutable—attempting reassignment throws a TypeError. This protects public APIs from accidental or malicious modification.
|
|
61
|
+
|
|
62
|
+
### Eliminates `this` Binding Bugs Without Arrow Functions
|
|
63
|
+
|
|
64
|
+
Arrow functions in class fields break inheritance and bloat bundle sizes due to per-instance function creation. The `@locked()` decorator provides correct `this` binding (like arrow functions) while using efficient prototype methods. Methods are bound once per instance and cached with Symbol keys.
|
|
65
|
+
|
|
66
|
+
### Simplifies Immutable Object Construction
|
|
67
|
+
|
|
68
|
+
Building frozen objects with `Object.freeze()` is shallow and doesn't prevent descriptor modification. `lockedProps()` provides deep immutability for specific properties while allowing controlled mutability elsewhere—ideal for partially frozen configs or API surfaces.
|
|
69
|
+
|
|
70
|
+
### TypeScript-First with Runtime Enforcement
|
|
71
|
+
|
|
72
|
+
Unlike TypeScript `readonly` (compile-time only), these utilities enforce immutability at runtime. This catches bugs in JavaScript-land, during deserialization, or when interfacing with dynamically typed code. Type safety and runtime safety in one decorator.
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm install @hyperfrontend/immutable-api-utils
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { locked, lockedProps, lockedPropertyDescriptors } from '@hyperfrontend/immutable-api-utils'
|
|
84
|
+
|
|
85
|
+
// Decorator usage: lock methods in classes
|
|
86
|
+
class Counter {
|
|
87
|
+
private count = 0
|
|
88
|
+
|
|
89
|
+
@locked()
|
|
90
|
+
increment() {
|
|
91
|
+
this.count++
|
|
92
|
+
return this.count
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@locked()
|
|
96
|
+
getValue() {
|
|
97
|
+
return this.count
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const counter = new Counter()
|
|
102
|
+
counter.increment() // Works: 1
|
|
103
|
+
counter.increment = () => 0 // Throws: Cannot overwrite locked method
|
|
104
|
+
|
|
105
|
+
// Ensure correct `this` binding even when method is extracted
|
|
106
|
+
const { increment } = counter
|
|
107
|
+
increment() // Still works correctly, `this` remains bound
|
|
108
|
+
|
|
109
|
+
// Functional API: lock multiple properties
|
|
110
|
+
const config = {}
|
|
111
|
+
lockedProps(config, [
|
|
112
|
+
['apiKey', 'secret-key-12345'],
|
|
113
|
+
['timeout', 5000],
|
|
114
|
+
['retries', 3],
|
|
115
|
+
])
|
|
116
|
+
|
|
117
|
+
config.apiKey = 'hacked' // Silent fail in non-strict mode, throws in strict mode
|
|
118
|
+
Object.defineProperty(config, 'apiKey', { writable: true }) // Throws: cannot redefine
|
|
119
|
+
|
|
120
|
+
// Low-level descriptor creation
|
|
121
|
+
const obj = {}
|
|
122
|
+
Object.defineProperty(obj, 'version', lockedPropertyDescriptors('1.0.0', true))
|
|
123
|
+
// Property is non-writable, non-configurable, but enumerable
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## API Overview
|
|
127
|
+
|
|
128
|
+
### Decorator
|
|
129
|
+
|
|
130
|
+
- **`@locked()`** - TypeScript decorator that makes class methods immutable with correct `this` binding
|
|
131
|
+
|
|
132
|
+
### Functions
|
|
133
|
+
|
|
134
|
+
- **`lockedProps(object, pairs)`** - Lock multiple properties on an object with key-value pairs
|
|
135
|
+
- **`lockedPropertyDescriptors(value, enumerable?)`** - Create a locked property descriptor for manual use with `Object.defineProperty`
|
|
136
|
+
|
|
137
|
+
## Use Cases
|
|
138
|
+
|
|
139
|
+
- **Plugin APIs**: Prevent plugins from modifying core library methods
|
|
140
|
+
- **Sandboxed execution**: Expose safe APIs to untrusted code
|
|
141
|
+
- **Configuration objects**: Lock critical config values after initialization
|
|
142
|
+
- **Public library interfaces**: Protect exported classes from mutation
|
|
143
|
+
- **Event emitters**: Prevent handler list manipulation
|
|
144
|
+
- **Prototype pollution defense**: Make critical prototypes tamper-proof
|
|
145
|
+
|
|
146
|
+
## Compatibility
|
|
147
|
+
|
|
148
|
+
| Platform | Support |
|
|
149
|
+
| ----------------------------- | :-----: |
|
|
150
|
+
| Browser | ✅ |
|
|
151
|
+
| Node.js | ✅ |
|
|
152
|
+
| Web Workers | ✅ |
|
|
153
|
+
| Deno, Bun, Cloudflare Workers | ✅ |
|
|
154
|
+
|
|
155
|
+
### Output Formats
|
|
156
|
+
|
|
157
|
+
| Format | File | Tree-Shakeable |
|
|
158
|
+
| ------ | -------------------------- | :------------: |
|
|
159
|
+
| ESM | `index.esm.js` | ✅ |
|
|
160
|
+
| CJS | `index.cjs.js` | ❌ |
|
|
161
|
+
| IIFE | `bundle/index.iife.min.js` | ❌ |
|
|
162
|
+
| UMD | `bundle/index.umd.min.js` | ❌ |
|
|
163
|
+
|
|
164
|
+
**Bundle size:** < 1 KB (minified, self-contained)
|
|
165
|
+
|
|
166
|
+
### CDN Usage
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<!-- unpkg -->
|
|
170
|
+
<script src="https://unpkg.com/@hyperfrontend/immutable-api-utils"></script>
|
|
171
|
+
|
|
172
|
+
<!-- jsDelivr -->
|
|
173
|
+
<script src="https://cdn.jsdelivr.net/npm/@hyperfrontend/immutable-api-utils"></script>
|
|
174
|
+
|
|
175
|
+
<script>
|
|
176
|
+
const { immutableApi, freezeClass, sealClass } = HyperfrontendImmutableApiUtils
|
|
177
|
+
</script>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Global variable:** `HyperfrontendImmutableApiUtils`
|
|
181
|
+
|
|
182
|
+
### Dependencies
|
|
183
|
+
|
|
184
|
+
None — zero external dependencies.
|
|
185
|
+
|
|
186
|
+
## Part of hyperfrontend
|
|
187
|
+
|
|
188
|
+
This library is part of the [hyperfrontend](https://github.com/AndrewRedican/hyperfrontend) monorepo. [Full documentation](https://hyperfrontend.dev).
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
We take the security of hyperfrontend seriously. If you discover a security vulnerability, please help us protect our users by following responsible disclosure practices.
|
|
6
|
+
|
|
7
|
+
### How to Report
|
|
8
|
+
|
|
9
|
+
**Please DO NOT report security vulnerabilities through public GitHub issues.**
|
|
10
|
+
|
|
11
|
+
Instead, please report security vulnerabilities directly via email to:
|
|
12
|
+
|
|
13
|
+
**<andrew.redican.mejia@gmail.com>**
|
|
14
|
+
|
|
15
|
+
### What to Include
|
|
16
|
+
|
|
17
|
+
To help us understand and resolve the issue quickly, please include the following information in your report:
|
|
18
|
+
|
|
19
|
+
- **Description**: A clear description of the vulnerability
|
|
20
|
+
- **Impact**: The potential impact and severity of the issue
|
|
21
|
+
- **Reproduction Steps**: Detailed steps to reproduce the vulnerability
|
|
22
|
+
- **Environment**: The version of hyperfrontend affected, browser/Node.js version, operating system, etc.
|
|
23
|
+
- **Proof of Concept**: If possible, include a minimal code example or proof of concept
|
|
24
|
+
- **Suggested Fix**: If you have ideas on how to fix the issue (optional)
|
|
25
|
+
|
|
26
|
+
### Response Timeline
|
|
27
|
+
|
|
28
|
+
- **Acknowledgment**: We will acknowledge receipt of your vulnerability report within 2 business days
|
|
29
|
+
- **Initial Assessment**: We will provide an initial assessment within 5 business days
|
|
30
|
+
- **Patch Development**: We aim to develop and test a patch within 10 days of acknowledgment
|
|
31
|
+
- **Public Disclosure**: Please allow at least **10 days** from the initial report before making the vulnerability publicly known
|
|
32
|
+
|
|
33
|
+
This grace period gives us time to:
|
|
34
|
+
|
|
35
|
+
- Verify and reproduce the issue
|
|
36
|
+
- Develop and test a fix
|
|
37
|
+
- Release a patched version
|
|
38
|
+
- Notify users to update their dependencies
|
|
39
|
+
|
|
40
|
+
### Coordinated Disclosure
|
|
41
|
+
|
|
42
|
+
We believe in coordinated disclosure and appreciate your cooperation in:
|
|
43
|
+
|
|
44
|
+
- Not exploiting the vulnerability beyond what is necessary to demonstrate it
|
|
45
|
+
- Not accessing, modifying, or deleting data that doesn't belong to you
|
|
46
|
+
- Allowing us reasonable time to address the issue before public disclosure
|
|
47
|
+
- Making a good faith effort to avoid privacy violations, data destruction, and service interruption
|
|
48
|
+
|
|
49
|
+
### Recognition
|
|
50
|
+
|
|
51
|
+
Once the vulnerability is patched and publicly disclosed, we will acknowledge your responsible disclosure in:
|
|
52
|
+
|
|
53
|
+
- Our release notes
|
|
54
|
+
- Our security advisories (if applicable)
|
|
55
|
+
- This SECURITY.md file (with your permission)
|
|
56
|
+
|
|
57
|
+
Thank you for helping keep hyperfrontend and its users safe!
|
|
58
|
+
|
|
59
|
+
## Security Best Practices
|
|
60
|
+
|
|
61
|
+
When using hyperfrontend in your applications:
|
|
62
|
+
|
|
63
|
+
1. **Keep Dependencies Updated**: Regularly update to the latest version to receive security patches
|
|
64
|
+
2. **Content Security Policy**: Implement appropriate CSP headers when embedding features
|
|
65
|
+
3. **Input Validation**: Validate and sanitize all data passed between features
|
|
66
|
+
4. **Origin Verification**: Always verify the origin of messages in cross-frame communication
|
|
67
|
+
5. **Authentication**: Implement proper authentication and authorization for sensitive features
|
|
68
|
+
6. **HTTPS**: Always serve hyperfrontend features over HTTPS in production
|
|
69
|
+
|
|
70
|
+
## Security Updates
|
|
71
|
+
|
|
72
|
+
Security updates will be released as patch versions and documented in the [CHANGELOG](https://github.com/AndrewRedican/hyperfrontend/releases) and GitHub Security Advisories.
|
|
73
|
+
|
|
74
|
+
## Supported Versions
|
|
75
|
+
|
|
76
|
+
We currently provide security updates for:
|
|
77
|
+
|
|
78
|
+
| Version | Supported |
|
|
79
|
+
| ------- | ------------------ |
|
|
80
|
+
| 0.0.x | :white_check_mark: |
|
|
81
|
+
|
|
82
|
+
As the project matures, we will update this table to reflect our long-term support policy.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
var HyperfrontendImmutableApiUtils = (function (exports) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a decorator that locks a method to prevent overwriting and ensure correct `this` binding.
|
|
6
|
+
*
|
|
7
|
+
* @locked
|
|
8
|
+
* Ensures a classic prototype method cannot be overwritten and is
|
|
9
|
+
* always called with the correct `this` instance without needing arrow functions.
|
|
10
|
+
*
|
|
11
|
+
* - The method of the prototype is non-configurable and non-enumerable.
|
|
12
|
+
* - Any attempt to assign to the method throws an error.
|
|
13
|
+
* - It does not support class fields / arrow functions.
|
|
14
|
+
*
|
|
15
|
+
* @returns A method decorator that locks the method
|
|
16
|
+
*/
|
|
17
|
+
const locked = () => {
|
|
18
|
+
return function lockMethod(target, key, descriptor) {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
20
|
+
const original = descriptor.value;
|
|
21
|
+
const BOUND = Symbol(`[[locked.bound:${String(key)}]]`);
|
|
22
|
+
return {
|
|
23
|
+
configurable: false,
|
|
24
|
+
enumerable: false,
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
get() {
|
|
27
|
+
// cache a bound function per instance
|
|
28
|
+
if (!Object.prototype.hasOwnProperty.call(this, BOUND)) {
|
|
29
|
+
Object.defineProperty(this, BOUND, {
|
|
30
|
+
value: original.bind(this),
|
|
31
|
+
writable: false,
|
|
32
|
+
configurable: false,
|
|
33
|
+
enumerable: false,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return this[BOUND];
|
|
37
|
+
},
|
|
38
|
+
set() {
|
|
39
|
+
throw new TypeError(`Cannot overwrite locked method ${String(key)}`);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const lockedPropertyDescriptors = (value, enumerable = false) => ({
|
|
46
|
+
value,
|
|
47
|
+
writable: false,
|
|
48
|
+
configurable: false,
|
|
49
|
+
enumerable,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const lockedProps = (object, propertyValuePairs) => {
|
|
53
|
+
const propertyMap = {};
|
|
54
|
+
propertyValuePairs.forEach(([key, value]) => (propertyMap[key] = lockedPropertyDescriptors(value)));
|
|
55
|
+
Object.defineProperties(object, propertyMap);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
exports.locked = locked;
|
|
59
|
+
exports.lockedPropertyDescriptors = lockedPropertyDescriptors;
|
|
60
|
+
exports.lockedProps = lockedProps;
|
|
61
|
+
|
|
62
|
+
return exports;
|
|
63
|
+
|
|
64
|
+
})({});
|
|
65
|
+
//# sourceMappingURL=index.iife.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.iife.js","sources":["../../../../../../../../../../libs/utils/immutable-api/src/locked.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":";;;IAQA;;;;;;;;;;;;IAYG;AACI,UAAM,MAAM,GAAG,MAAmB;IACvC,IAAA,OAAO,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAA;;IAEhD,QAAA,MAAM,QAAQ,GAAa,UAAU,CAAC,KAAK;YAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,CAAI,CAAC;YACvD,OAA2B;IACzB,YAAA,YAAY,EAAE,KAAK;IACnB,YAAA,UAAU,EAAE,KAAK;;gBAEjB,GAAG,GAAA;;IAED,gBAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;IACtD,oBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;IACjC,wBAAA,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B,wBAAA,QAAQ,EAAE,KAAK;IACf,wBAAA,YAAY,EAAE,KAAK;IACnB,wBAAA,UAAU,EAAE,KAAK;IAClB,qBAAA,CAAC;oBACJ;IACA,gBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB,CAAC;gBACD,GAAG,GAAA;oBACD,MAAM,IAAI,SAAS,CAAC,CAAA,+BAAA,EAAkC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC;gBACtE,CAAC;aACF;IACH,IAAA,CAAC;IACH;;AC7CO,UAAM,yBAAyB,GAAiC,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,MAAM;QACrG,KAAK;IACL,IAAA,QAAQ,EAAE,KAAK;IACf,IAAA,YAAY,EAAE,KAAK;QACnB,UAAU;IACX,CAAA;;UCCY,WAAW,GAAiB,CAAC,MAAM,EAAE,kBAAkB,KAAI;QACtE,MAAM,WAAW,GAA0B,EAAE;QAC7C,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnG,IAAA,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC;IAC9C;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var HyperfrontendImmutableApiUtils=function(e){"use strict";const r=(e,r=!1)=>({value:e,writable:!1,configurable:!1,enumerable:r});return e.locked=()=>function(e,r,t){const o=t.value,n=Symbol(`[[locked.bound:${String(r)}]]`);return{configurable:!1,enumerable:!1,get(){return Object.prototype.hasOwnProperty.call(this,n)||Object.defineProperty(this,n,{value:o.bind(this),writable:!1,configurable:!1,enumerable:!1}),this[n]},set(){throw new TypeError(`Cannot overwrite locked method ${String(r)}`)}}},e.lockedPropertyDescriptors=r,e.lockedProps=(e,t)=>{const o={};t.forEach(([e,t])=>o[e]=r(t)),Object.defineProperties(e,o)},e}({});
|
|
2
|
+
//# sourceMappingURL=index.iife.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.iife.min.js","sources":["../../../../../../../../../../libs/utils/immutable-api/src/locked.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":["lockedPropertyDescriptors","value","enumerable","writable","configurable","target","key","descriptor","original","BOUND","Symbol","String","get","Object","prototype","hasOwnProperty","call","this","defineProperty","bind","set","TypeError","object","propertyValuePairs","propertyMap","forEach","defineProperties"],"mappings":"4DAqBO,MCnBMA,EAA0D,CAACC,EAAOC,GAAa,KAAK,CAC/FD,QACAE,UAAU,EACVC,cAAc,EACdF,+BDeoB,IACb,SAAoBG,EAAQC,EAAKC,GAEtC,MAAMC,EAAqBD,EAAWN,MAChCQ,EAAQC,OAAO,kBAAkBC,OAAOL,QAC9C,MAA2B,CACzBF,cAAc,EACdF,YAAY,EAEZ,GAAAU,GAUE,OARKC,OAAOC,UAAUC,eAAeC,KAAKC,KAAMR,IAC9CI,OAAOK,eAAeD,KAAMR,EAAO,CACjCR,MAAOO,EAASW,KAAKF,MACrBd,UAAU,EACVC,cAAc,EACdF,YAAY,IAGTe,KAAKR,EACd,EACA,GAAAW,GACE,MAAM,IAAIC,UAAU,kCAAkCV,OAAOL,KAC/D,EAEJ,8CEtCuC,CAACgB,EAAQC,KAChD,MAAMC,EAAqC,CAAA,EAC3CD,EAAmBE,QAAQ,EAAEnB,EAAKL,KAAYuB,EAAYlB,GAAON,EAA0BC,IAC3FY,OAAOa,iBAAiBJ,EAAQE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.HyperfrontendImmutableApiUtils = {}));
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a decorator that locks a method to prevent overwriting and ensure correct `this` binding.
|
|
9
|
+
*
|
|
10
|
+
* @locked
|
|
11
|
+
* Ensures a classic prototype method cannot be overwritten and is
|
|
12
|
+
* always called with the correct `this` instance without needing arrow functions.
|
|
13
|
+
*
|
|
14
|
+
* - The method of the prototype is non-configurable and non-enumerable.
|
|
15
|
+
* - Any attempt to assign to the method throws an error.
|
|
16
|
+
* - It does not support class fields / arrow functions.
|
|
17
|
+
*
|
|
18
|
+
* @returns A method decorator that locks the method
|
|
19
|
+
*/
|
|
20
|
+
const locked = () => {
|
|
21
|
+
return function lockMethod(target, key, descriptor) {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
23
|
+
const original = descriptor.value;
|
|
24
|
+
const BOUND = Symbol(`[[locked.bound:${String(key)}]]`);
|
|
25
|
+
return {
|
|
26
|
+
configurable: false,
|
|
27
|
+
enumerable: false,
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
get() {
|
|
30
|
+
// cache a bound function per instance
|
|
31
|
+
if (!Object.prototype.hasOwnProperty.call(this, BOUND)) {
|
|
32
|
+
Object.defineProperty(this, BOUND, {
|
|
33
|
+
value: original.bind(this),
|
|
34
|
+
writable: false,
|
|
35
|
+
configurable: false,
|
|
36
|
+
enumerable: false,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return this[BOUND];
|
|
40
|
+
},
|
|
41
|
+
set() {
|
|
42
|
+
throw new TypeError(`Cannot overwrite locked method ${String(key)}`);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const lockedPropertyDescriptors = (value, enumerable = false) => ({
|
|
49
|
+
value,
|
|
50
|
+
writable: false,
|
|
51
|
+
configurable: false,
|
|
52
|
+
enumerable,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const lockedProps = (object, propertyValuePairs) => {
|
|
56
|
+
const propertyMap = {};
|
|
57
|
+
propertyValuePairs.forEach(([key, value]) => (propertyMap[key] = lockedPropertyDescriptors(value)));
|
|
58
|
+
Object.defineProperties(object, propertyMap);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
exports.locked = locked;
|
|
62
|
+
exports.lockedPropertyDescriptors = lockedPropertyDescriptors;
|
|
63
|
+
exports.lockedProps = lockedProps;
|
|
64
|
+
|
|
65
|
+
}));
|
|
66
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../../../../../../../../../../libs/utils/immutable-api/src/locked.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":";;;;;;IAQA;;;;;;;;;;;;IAYG;AACI,UAAM,MAAM,GAAG,MAAmB;IACvC,IAAA,OAAO,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAA;;IAEhD,QAAA,MAAM,QAAQ,GAAa,UAAU,CAAC,KAAK;YAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,CAAI,CAAC;YACvD,OAA2B;IACzB,YAAA,YAAY,EAAE,KAAK;IACnB,YAAA,UAAU,EAAE,KAAK;;gBAEjB,GAAG,GAAA;;IAED,gBAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;IACtD,oBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;IACjC,wBAAA,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;IAC1B,wBAAA,QAAQ,EAAE,KAAK;IACf,wBAAA,YAAY,EAAE,KAAK;IACnB,wBAAA,UAAU,EAAE,KAAK;IAClB,qBAAA,CAAC;oBACJ;IACA,gBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB,CAAC;gBACD,GAAG,GAAA;oBACD,MAAM,IAAI,SAAS,CAAC,CAAA,+BAAA,EAAkC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC;gBACtE,CAAC;aACF;IACH,IAAA,CAAC;IACH;;AC7CO,UAAM,yBAAyB,GAAiC,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,MAAM;QACrG,KAAK;IACL,IAAA,QAAQ,EAAE,KAAK;IACf,IAAA,YAAY,EAAE,KAAK;QACnB,UAAU;IACX,CAAA;;UCCY,WAAW,GAAiB,CAAC,MAAM,EAAE,kBAAkB,KAAI;QACtE,MAAM,WAAW,GAA0B,EAAE;QAC7C,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnG,IAAA,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC;IAC9C;;;;;;;;;;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).HyperfrontendImmutableApiUtils={})}(this,function(e){"use strict";const t=(e,t=!1)=>({value:e,writable:!1,configurable:!1,enumerable:t});e.locked=()=>function(e,t,o){const r=o.value,n=Symbol(`[[locked.bound:${String(t)}]]`);return{configurable:!1,enumerable:!1,get(){return Object.prototype.hasOwnProperty.call(this,n)||Object.defineProperty(this,n,{value:r.bind(this),writable:!1,configurable:!1,enumerable:!1}),this[n]},set(){throw new TypeError(`Cannot overwrite locked method ${String(t)}`)}}},e.lockedPropertyDescriptors=t,e.lockedProps=(e,o)=>{const r={};o.forEach(([e,o])=>r[e]=t(o)),Object.defineProperties(e,r)}});
|
|
2
|
+
//# sourceMappingURL=index.umd.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.min.js","sources":["../../../../../../../../../../libs/utils/immutable-api/src/locked.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../../../../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":["lockedPropertyDescriptors","value","enumerable","writable","configurable","target","key","descriptor","original","BOUND","Symbol","String","get","Object","prototype","hasOwnProperty","call","this","defineProperty","bind","set","TypeError","object","propertyValuePairs","propertyMap","forEach","defineProperties"],"mappings":"qQAqBO,MCnBMA,EAA0D,CAACC,EAAOC,GAAa,KAAK,CAC/FD,QACAE,UAAU,EACVC,cAAc,EACdF,wBDeoB,IACb,SAAoBG,EAAQC,EAAKC,GAEtC,MAAMC,EAAqBD,EAAWN,MAChCQ,EAAQC,OAAO,kBAAkBC,OAAOL,QAC9C,MAA2B,CACzBF,cAAc,EACdF,YAAY,EAEZ,GAAAU,GAUE,OARKC,OAAOC,UAAUC,eAAeC,KAAKC,KAAMR,IAC9CI,OAAOK,eAAeD,KAAMR,EAAO,CACjCR,MAAOO,EAASW,KAAKF,MACrBd,UAAU,EACVC,cAAc,EACdF,YAAY,IAGTe,KAAKR,EACd,EACA,GAAAW,GACE,MAAM,IAAIC,UAAU,kCAAkCV,OAAOL,KAC/D,EAEJ,8CEtCuC,CAACgB,EAAQC,KAChD,MAAMC,EAAqC,CAAA,EAC3CD,EAAmBE,QAAQ,EAAEnB,EAAKL,KAAYuB,EAAYlB,GAAON,EAA0BC,IAC3FY,OAAOa,iBAAiBJ,EAAQE"}
|
package/index.cjs.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a decorator that locks a method to prevent overwriting and ensure correct `this` binding.
|
|
5
|
+
*
|
|
6
|
+
* @locked
|
|
7
|
+
* Ensures a classic prototype method cannot be overwritten and is
|
|
8
|
+
* always called with the correct `this` instance without needing arrow functions.
|
|
9
|
+
*
|
|
10
|
+
* - The method of the prototype is non-configurable and non-enumerable.
|
|
11
|
+
* - Any attempt to assign to the method throws an error.
|
|
12
|
+
* - It does not support class fields / arrow functions.
|
|
13
|
+
*
|
|
14
|
+
* @returns A method decorator that locks the method
|
|
15
|
+
*/
|
|
16
|
+
const locked = () => {
|
|
17
|
+
return function lockMethod(target, key, descriptor) {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
19
|
+
const original = descriptor.value;
|
|
20
|
+
const BOUND = Symbol(`[[locked.bound:${String(key)}]]`);
|
|
21
|
+
return {
|
|
22
|
+
configurable: false,
|
|
23
|
+
enumerable: false,
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
get() {
|
|
26
|
+
// cache a bound function per instance
|
|
27
|
+
if (!Object.prototype.hasOwnProperty.call(this, BOUND)) {
|
|
28
|
+
Object.defineProperty(this, BOUND, {
|
|
29
|
+
value: original.bind(this),
|
|
30
|
+
writable: false,
|
|
31
|
+
configurable: false,
|
|
32
|
+
enumerable: false,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return this[BOUND];
|
|
36
|
+
},
|
|
37
|
+
set() {
|
|
38
|
+
throw new TypeError(`Cannot overwrite locked method ${String(key)}`);
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const lockedPropertyDescriptors = (value, enumerable = false) => ({
|
|
45
|
+
value,
|
|
46
|
+
writable: false,
|
|
47
|
+
configurable: false,
|
|
48
|
+
enumerable,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const lockedProps = (object, propertyValuePairs) => {
|
|
52
|
+
const propertyMap = {};
|
|
53
|
+
propertyValuePairs.forEach(([key, value]) => (propertyMap[key] = lockedPropertyDescriptors(value)));
|
|
54
|
+
Object.defineProperties(object, propertyMap);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
exports.locked = locked;
|
|
58
|
+
exports.lockedPropertyDescriptors = lockedPropertyDescriptors;
|
|
59
|
+
exports.lockedProps = lockedProps;
|
|
60
|
+
//# sourceMappingURL=index.cjs.js.map
|
package/index.cjs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../../../../libs/utils/immutable-api/src/locked.ts","../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":";;AAQA;;;;;;;;;;;;AAYG;AACI,MAAM,MAAM,GAAG,MAAmB;AACvC,IAAA,OAAO,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAA;;AAEhD,QAAA,MAAM,QAAQ,GAAa,UAAU,CAAC,KAAK;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,CAAI,CAAC;QACvD,OAA2B;AACzB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,UAAU,EAAE,KAAK;;YAEjB,GAAG,GAAA;;AAED,gBAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACtD,oBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;AACjC,wBAAA,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1B,wBAAA,QAAQ,EAAE,KAAK;AACf,wBAAA,YAAY,EAAE,KAAK;AACnB,wBAAA,UAAU,EAAE,KAAK;AAClB,qBAAA,CAAC;gBACJ;AACA,gBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YACD,GAAG,GAAA;gBACD,MAAM,IAAI,SAAS,CAAC,CAAA,+BAAA,EAAkC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC;YACtE,CAAC;SACF;AACH,IAAA,CAAC;AACH;;AC7CO,MAAM,yBAAyB,GAAiC,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,MAAM;IACrG,KAAK;AACL,IAAA,QAAQ,EAAE,KAAK;AACf,IAAA,YAAY,EAAE,KAAK;IACnB,UAAU;AACX,CAAA;;MCCY,WAAW,GAAiB,CAAC,MAAM,EAAE,kBAAkB,KAAI;IACtE,MAAM,WAAW,GAA0B,EAAE;IAC7C,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC;AACnG,IAAA,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9C;;;;;;"}
|
package/index.d.ts
ADDED
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../libs/utils/immutable-api/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,2BAA2B,CAAA;AACzC,cAAc,gBAAgB,CAAA"}
|
package/index.esm.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a decorator that locks a method to prevent overwriting and ensure correct `this` binding.
|
|
3
|
+
*
|
|
4
|
+
* @locked
|
|
5
|
+
* Ensures a classic prototype method cannot be overwritten and is
|
|
6
|
+
* always called with the correct `this` instance without needing arrow functions.
|
|
7
|
+
*
|
|
8
|
+
* - The method of the prototype is non-configurable and non-enumerable.
|
|
9
|
+
* - Any attempt to assign to the method throws an error.
|
|
10
|
+
* - It does not support class fields / arrow functions.
|
|
11
|
+
*
|
|
12
|
+
* @returns A method decorator that locks the method
|
|
13
|
+
*/
|
|
14
|
+
const locked = () => {
|
|
15
|
+
return function lockMethod(target, key, descriptor) {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
17
|
+
const original = descriptor.value;
|
|
18
|
+
const BOUND = Symbol(`[[locked.bound:${String(key)}]]`);
|
|
19
|
+
return {
|
|
20
|
+
configurable: false,
|
|
21
|
+
enumerable: false,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
get() {
|
|
24
|
+
// cache a bound function per instance
|
|
25
|
+
if (!Object.prototype.hasOwnProperty.call(this, BOUND)) {
|
|
26
|
+
Object.defineProperty(this, BOUND, {
|
|
27
|
+
value: original.bind(this),
|
|
28
|
+
writable: false,
|
|
29
|
+
configurable: false,
|
|
30
|
+
enumerable: false,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return this[BOUND];
|
|
34
|
+
},
|
|
35
|
+
set() {
|
|
36
|
+
throw new TypeError(`Cannot overwrite locked method ${String(key)}`);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const lockedPropertyDescriptors = (value, enumerable = false) => ({
|
|
43
|
+
value,
|
|
44
|
+
writable: false,
|
|
45
|
+
configurable: false,
|
|
46
|
+
enumerable,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const lockedProps = (object, propertyValuePairs) => {
|
|
50
|
+
const propertyMap = {};
|
|
51
|
+
propertyValuePairs.forEach(([key, value]) => (propertyMap[key] = lockedPropertyDescriptors(value)));
|
|
52
|
+
Object.defineProperties(object, propertyMap);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { locked, lockedPropertyDescriptors, lockedProps };
|
|
56
|
+
//# sourceMappingURL=index.esm.js.map
|
package/index.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../../../libs/utils/immutable-api/src/locked.ts","../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts","../../../../libs/utils/immutable-api/src/locked-props.ts"],"sourcesContent":[null,null,null],"names":[],"mappings":"AAQA;;;;;;;;;;;;AAYG;AACI,MAAM,MAAM,GAAG,MAAmB;AACvC,IAAA,OAAO,SAAS,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAA;;AAEhD,QAAA,MAAM,QAAQ,GAAa,UAAU,CAAC,KAAK;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAA,eAAA,EAAkB,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,CAAI,CAAC;QACvD,OAA2B;AACzB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,UAAU,EAAE,KAAK;;YAEjB,GAAG,GAAA;;AAED,gBAAA,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACtD,oBAAA,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE;AACjC,wBAAA,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1B,wBAAA,QAAQ,EAAE,KAAK;AACf,wBAAA,YAAY,EAAE,KAAK;AACnB,wBAAA,UAAU,EAAE,KAAK;AAClB,qBAAA,CAAC;gBACJ;AACA,gBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YACD,GAAG,GAAA;gBACD,MAAM,IAAI,SAAS,CAAC,CAAA,+BAAA,EAAkC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC;YACtE,CAAC;SACF;AACH,IAAA,CAAC;AACH;;AC7CO,MAAM,yBAAyB,GAAiC,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,MAAM;IACrG,KAAK;AACL,IAAA,QAAQ,EAAE,KAAK;AACf,IAAA,YAAY,EAAE,KAAK;IACnB,UAAU;AACX,CAAA;;MCCY,WAAW,GAAiB,CAAC,MAAM,EAAE,kBAAkB,KAAI;IACtE,MAAM,WAAW,GAA0B,EAAE;IAC7C,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAAC;AACnG,IAAA,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC;AAC9C;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked-prop-descriptors.d.ts","sourceRoot":"","sources":["../../../../libs/utils/immutable-api/src/locked-prop-descriptors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,4BAA4B,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,KAAK,kBAAkB,CAAA;AAEvG,eAAO,MAAM,yBAAyB,EAAE,4BAKtC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked-props.d.ts","sourceRoot":"","sources":["../../../../libs/utils/immutable-api/src/locked-props.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,MAAM,EAEd,kBAAkB,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAChC,IAAI,CAAA;AAET,eAAO,MAAM,WAAW,EAAE,YAIzB,CAAA"}
|
package/locked.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type LockedMethod = (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) => any;
|
|
2
|
+
/**
|
|
3
|
+
* Creates a decorator that locks a method to prevent overwriting and ensure correct `this` binding.
|
|
4
|
+
*
|
|
5
|
+
* @locked
|
|
6
|
+
* Ensures a classic prototype method cannot be overwritten and is
|
|
7
|
+
* always called with the correct `this` instance without needing arrow functions.
|
|
8
|
+
*
|
|
9
|
+
* - The method of the prototype is non-configurable and non-enumerable.
|
|
10
|
+
* - Any attempt to assign to the method throws an error.
|
|
11
|
+
* - It does not support class fields / arrow functions.
|
|
12
|
+
*
|
|
13
|
+
* @returns A method decorator that locks the method
|
|
14
|
+
*/
|
|
15
|
+
export declare const locked: () => LockedMethod;
|
|
16
|
+
//# sourceMappingURL=locked.d.ts.map
|
package/locked.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked.d.ts","sourceRoot":"","sources":["../../../../libs/utils/immutable-api/src/locked.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,CACzB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,EAE5B,UAAU,EAAE,uBAAuB,CAAC,GAAG,CAAC,KAErC,GAAG,CAAA;AAER;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,QAAO,YA0BzB,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hyperfrontend/immutable-api-utils",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Decorators and utilities for creating immutable, tamper-proof object APIs.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18.0.0",
|
|
9
|
+
"npm": ">=8.0.0"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"immutable",
|
|
13
|
+
"decorator",
|
|
14
|
+
"property-descriptor",
|
|
15
|
+
"locked",
|
|
16
|
+
"frozen",
|
|
17
|
+
"non-writable",
|
|
18
|
+
"non-configurable",
|
|
19
|
+
"this-binding",
|
|
20
|
+
"typescript",
|
|
21
|
+
"api-protection",
|
|
22
|
+
"zero-dependencies",
|
|
23
|
+
"functional",
|
|
24
|
+
"tamper-proof"
|
|
25
|
+
],
|
|
26
|
+
"main": "./index.cjs.js",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/AndrewRedican/hyperfrontend.git"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/AndrewRedican/hyperfrontend/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/AndrewRedican/hyperfrontend#readme",
|
|
35
|
+
"author": {
|
|
36
|
+
"name": "andrew.redican.mejia@gmail.com",
|
|
37
|
+
"url": "https://hyperfrontend.dev"
|
|
38
|
+
},
|
|
39
|
+
"exports": {
|
|
40
|
+
"./package.json": "./package.json",
|
|
41
|
+
".": {
|
|
42
|
+
"types": "./index.d.ts",
|
|
43
|
+
"import": "./index.esm.js",
|
|
44
|
+
"require": "./index.cjs.js"
|
|
45
|
+
},
|
|
46
|
+
"./bundle": {
|
|
47
|
+
"import": "./bundle/index.iife.min.js",
|
|
48
|
+
"require": "./bundle/index.iife.min.js"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"module": "./index.esm.js",
|
|
52
|
+
"types": "./index.d.ts",
|
|
53
|
+
"unpkg": "./bundle/index.umd.min.js",
|
|
54
|
+
"jsdelivr": "./bundle/index.umd.min.js"
|
|
55
|
+
}
|