typeomatica 0.2.7 → 0.2.8
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/lib/errors.d.ts +1 -0
- package/lib/errors.js +2 -1
- package/lib/fields.d.ts +10 -1
- package/lib/fields.js +20 -5
- package/lib/index.js +10 -3
- package/package.json +1 -1
- package/src/errors.ts +2 -1
- package/src/fields.ts +23 -3
- package/src/index.ts +11 -3
- package/test/index.ts +97 -14
package/lib/errors.d.ts
CHANGED
package/lib/errors.js
CHANGED
|
@@ -5,5 +5,6 @@ exports.ErrorsNames = {
|
|
|
5
5
|
TYPE_MISMATCH: 'Type Mismatch',
|
|
6
6
|
ACCESS_DENIED: 'Value Access Denied',
|
|
7
7
|
MISSING_PROP: 'Attempt to Access to Undefined Prop',
|
|
8
|
-
RIP_FUNCTIONS: 'Functions are Restricted'
|
|
8
|
+
RIP_FUNCTIONS: 'Functions are Restricted',
|
|
9
|
+
FORBIDDEN_RE: 'Re-Assirnment is Forbidden'
|
|
9
10
|
};
|
package/lib/fields.d.ts
CHANGED
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
export declare const SymbolInitialValue: unique symbol;
|
|
2
|
-
|
|
2
|
+
interface FieldDefinition {
|
|
3
|
+
[SymbolInitialValue]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export declare class FieldConstructor implements FieldDefinition {
|
|
6
|
+
[SymbolInitialValue]: unknown;
|
|
7
|
+
get get(): (this: FieldDefinition) => unknown;
|
|
8
|
+
get set(): () => never;
|
|
9
|
+
constructor(value: unknown);
|
|
10
|
+
}
|
|
11
|
+
export {};
|
package/lib/fields.js
CHANGED
|
@@ -2,8 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FieldConstructor = exports.SymbolInitialValue = void 0;
|
|
4
4
|
exports.SymbolInitialValue = Symbol('Initial Value');
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
class FieldConstructor {
|
|
7
|
+
constructor(value) {
|
|
8
|
+
this[exports.SymbolInitialValue] = value;
|
|
9
|
+
}
|
|
10
|
+
get get() {
|
|
11
|
+
const self = this;
|
|
12
|
+
return function () {
|
|
13
|
+
return self[exports.SymbolInitialValue];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
get set() {
|
|
17
|
+
return function () {
|
|
18
|
+
throw new TypeError(errors_1.ErrorsNames.FORBIDDEN_RE);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.FieldConstructor = FieldConstructor;
|
|
23
|
+
Object.freeze(FieldConstructor.prototype);
|
|
24
|
+
Object.seal(FieldConstructor.prototype);
|
package/lib/index.js
CHANGED
|
@@ -42,11 +42,18 @@ const createProperty = (propName, initialValue, receiver) => {
|
|
|
42
42
|
const descriptor = (isObject && (value instanceof fields_1.FieldConstructor)) ?
|
|
43
43
|
value
|
|
44
44
|
: Object.assign({ enumerable: true }, resolver[type](value, receiver));
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
try {
|
|
46
|
+
const result = Reflect.defineProperty(receiver, propName, descriptor);
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
47
52
|
};
|
|
53
|
+
const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
|
|
48
54
|
const util = require('util');
|
|
49
|
-
const
|
|
55
|
+
const hasNodeInspect = (util && util.inspect && util.inspect.custom);
|
|
56
|
+
hasNodeInspect && (props2skip.add(util.inspect.custom));
|
|
50
57
|
const handlers = {
|
|
51
58
|
get(target, prop, receiver) {
|
|
52
59
|
const result = Reflect.get(target, prop, receiver);
|
package/package.json
CHANGED
package/src/errors.ts
CHANGED
|
@@ -4,5 +4,6 @@ export const ErrorsNames = {
|
|
|
4
4
|
TYPE_MISMATCH: 'Type Mismatch',
|
|
5
5
|
ACCESS_DENIED: 'Value Access Denied',
|
|
6
6
|
MISSING_PROP: 'Attempt to Access to Undefined Prop',
|
|
7
|
-
RIP_FUNCTIONS: 'Functions are Restricted'
|
|
7
|
+
RIP_FUNCTIONS: 'Functions are Restricted',
|
|
8
|
+
FORBIDDEN_RE: 'Re-Assirnment is Forbidden'
|
|
8
9
|
};
|
package/src/fields.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
export const SymbolInitialValue = Symbol('Initial Value');
|
|
4
4
|
|
|
5
|
+
import { ErrorsNames } from './errors'
|
|
6
|
+
|
|
5
7
|
interface FieldDefinition {
|
|
6
8
|
[SymbolInitialValue]: unknown
|
|
7
9
|
// get?: unknown
|
|
@@ -11,9 +13,27 @@ interface FieldDefinition {
|
|
|
11
13
|
// writable: boolean
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export const FieldConstructor = function (this: FieldDefinition, value: unknown) {
|
|
15
|
-
|
|
16
|
-
} as ObjectConstructor;
|
|
16
|
+
// export const FieldConstructor = function (this: FieldDefinition, value: unknown) {
|
|
17
|
+
// this[SymbolInitialValue] = value;
|
|
18
|
+
// } as ObjectConstructor;
|
|
19
|
+
|
|
20
|
+
export class FieldConstructor implements FieldDefinition {
|
|
21
|
+
[SymbolInitialValue]: unknown
|
|
22
|
+
public get get () {
|
|
23
|
+
const self = this;
|
|
24
|
+
return function (this: FieldDefinition) {
|
|
25
|
+
return self[SymbolInitialValue];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
public get set () {
|
|
29
|
+
return function () {
|
|
30
|
+
throw new TypeError(ErrorsNames.FORBIDDEN_RE);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
constructor (value: unknown) {
|
|
34
|
+
this[SymbolInitialValue] = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
17
37
|
|
|
18
38
|
// Object.assign(FieldConstructor.prototype, {
|
|
19
39
|
// configurable: false,
|
package/src/index.ts
CHANGED
|
@@ -80,13 +80,20 @@ const createProperty = (propName: string, initialValue: unknown, receiver: objec
|
|
|
80
80
|
// debugger;
|
|
81
81
|
// }
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
try {
|
|
84
|
+
const result = Reflect.defineProperty(receiver, propName, descriptor);
|
|
85
|
+
return result;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// debugger;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
85
90
|
|
|
86
91
|
};
|
|
87
92
|
|
|
93
|
+
const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
|
|
88
94
|
const util = require('util');
|
|
89
|
-
const
|
|
95
|
+
const hasNodeInspect = (util && util.inspect && util.inspect.custom);
|
|
96
|
+
hasNodeInspect && (props2skip.add(util.inspect.custom));
|
|
90
97
|
|
|
91
98
|
const handlers = {
|
|
92
99
|
get(target: object, prop: string | symbol, receiver: object) {
|
|
@@ -103,6 +110,7 @@ const handlers = {
|
|
|
103
110
|
}, {}));
|
|
104
111
|
}
|
|
105
112
|
}
|
|
113
|
+
// @ts-ignore
|
|
106
114
|
if (props2skip.has(prop)) {
|
|
107
115
|
return undefined;
|
|
108
116
|
}
|
package/test/index.ts
CHANGED
|
@@ -72,37 +72,83 @@ const extendedSetInstance = new ExtendedSet;
|
|
|
72
72
|
const MUTATION_VALUE = -2;
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
class
|
|
75
|
+
class MyFieldConstructorNoRe extends FieldConstructor {
|
|
76
|
+
_value: string
|
|
76
77
|
constructor(value: string) {
|
|
77
78
|
super(value);
|
|
78
79
|
Reflect.defineProperty(this, 'enumerable', {
|
|
79
80
|
value: true
|
|
80
81
|
});
|
|
82
|
+
this._value = value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
class MyFieldConstructorReGet extends MyFieldConstructorNoRe {
|
|
86
|
+
constructor(value: string) {
|
|
87
|
+
super(value);
|
|
88
|
+
const self = this;
|
|
89
|
+
Reflect.defineProperty(this, 'enumerable', {
|
|
90
|
+
value: true
|
|
91
|
+
});
|
|
81
92
|
Reflect.defineProperty(this, 'get', {
|
|
82
|
-
get
|
|
93
|
+
get() {
|
|
83
94
|
return function () {
|
|
84
|
-
return
|
|
95
|
+
return self._value;
|
|
85
96
|
}
|
|
86
|
-
}
|
|
97
|
+
},
|
|
98
|
+
enumerable: true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
class MyFieldConstructorReSet extends MyFieldConstructorNoRe {
|
|
103
|
+
constructor(value: string) {
|
|
104
|
+
super(value);
|
|
105
|
+
const self = this;
|
|
106
|
+
Reflect.defineProperty(this, 'enumerable', {
|
|
107
|
+
value: true
|
|
87
108
|
});
|
|
88
109
|
Reflect.defineProperty(this, 'set', {
|
|
89
|
-
get
|
|
90
|
-
return function (
|
|
91
|
-
|
|
110
|
+
get() {
|
|
111
|
+
return function (value: string) {
|
|
112
|
+
self._value = value;
|
|
92
113
|
}
|
|
93
114
|
},
|
|
94
115
|
enumerable: true
|
|
95
116
|
});
|
|
96
117
|
}
|
|
97
118
|
}
|
|
119
|
+
class MyFieldConstructor extends MyFieldConstructorReGet {
|
|
120
|
+
constructor(value: string) {
|
|
121
|
+
super(value);
|
|
122
|
+
const self = this;
|
|
123
|
+
Reflect.defineProperty(this, 'enumerable', {
|
|
124
|
+
value: true
|
|
125
|
+
});
|
|
126
|
+
Reflect.defineProperty(this, 'set', {
|
|
127
|
+
get() {
|
|
128
|
+
return function (value: string) {
|
|
129
|
+
self._value = value;
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
enumerable: true
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const myField = new MyFieldConstructor('initial value');
|
|
138
|
+
const myFieldReGet = new MyFieldConstructorReGet('initial value for get check');
|
|
139
|
+
const myFieldReSet = new MyFieldConstructorReSet('initial value for set check');
|
|
98
140
|
|
|
99
|
-
|
|
100
|
-
class
|
|
101
|
-
class SecondMadeFieldClass extends BaseClass { myField = myField };
|
|
141
|
+
class MadeFieldClass extends BaseClass { myField = myField as unknown | string };
|
|
142
|
+
class SecondMadeFieldClass extends BaseClass { myField = myField as unknown | string };
|
|
102
143
|
const madeFieldInstance = new MadeFieldClass;
|
|
103
144
|
const secondMadeFieldInstance = new MadeFieldClass;
|
|
104
145
|
const thirdMadeFieldInstance = new SecondMadeFieldClass;
|
|
105
146
|
|
|
147
|
+
class MadeReGet extends BaseClass { myField = myFieldReGet as unknown | string }
|
|
148
|
+
class MadeReSet extends BaseClass { myField = myFieldReSet as unknown | string }
|
|
149
|
+
const madeReGet = new MadeReGet;
|
|
150
|
+
const madeReSet = new MadeReSet;
|
|
151
|
+
|
|
106
152
|
describe('props tests', () => {
|
|
107
153
|
|
|
108
154
|
test('base instance has props', () => {
|
|
@@ -172,12 +218,45 @@ describe('props tests', () => {
|
|
|
172
218
|
});
|
|
173
219
|
|
|
174
220
|
test('correct custom field creation', () => {
|
|
175
|
-
expect(madeFieldInstance.myField).toEqual('
|
|
221
|
+
expect(madeFieldInstance.myField).toEqual('initial value');
|
|
176
222
|
});
|
|
223
|
+
|
|
177
224
|
test('correct custom field assignment', () => {
|
|
178
|
-
madeFieldInstance.myField =
|
|
179
|
-
expect(secondMadeFieldInstance.myField).toEqual(
|
|
180
|
-
expect(thirdMadeFieldInstance.myField).toEqual(
|
|
225
|
+
madeFieldInstance.myField = 'replaced';
|
|
226
|
+
expect(secondMadeFieldInstance.myField).toEqual('replaced');
|
|
227
|
+
expect(thirdMadeFieldInstance.myField).toEqual('replaced');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
test('correct custom field no-re-assignment', () => {
|
|
231
|
+
expect(madeReGet.myField).toEqual('initial value for get check');
|
|
232
|
+
expect(() => {
|
|
233
|
+
|
|
234
|
+
madeReGet.myField = 'replaced';
|
|
235
|
+
|
|
236
|
+
}).toThrow(new TypeError('Re-Assirnment is Forbidden'));
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('correct custom field setter only', () => {
|
|
240
|
+
madeReSet.myField = 'replaced';
|
|
241
|
+
expect(madeReSet.myField).toEqual('initial value for set check');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test('takes error on wrong field definition', () => {
|
|
245
|
+
expect(() => {
|
|
246
|
+
class WrongFieldConstructor extends FieldConstructor {
|
|
247
|
+
value: number
|
|
248
|
+
constructor(value: number) {
|
|
249
|
+
super(value)
|
|
250
|
+
this.value = value;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const wrongField = new WrongFieldConstructor(123);
|
|
254
|
+
class WithWrongField extends BaseClass {
|
|
255
|
+
erroredField = wrongField
|
|
256
|
+
}
|
|
257
|
+
new WithWrongField;
|
|
258
|
+
|
|
259
|
+
}).toThrow();
|
|
181
260
|
});
|
|
182
261
|
|
|
183
262
|
test('correct custom missing prop search creation', () => {
|
|
@@ -188,6 +267,10 @@ describe('props tests', () => {
|
|
|
188
267
|
const util = require('util');
|
|
189
268
|
// @ts-ignore
|
|
190
269
|
expect(madeFieldInstance[util.inspect.custom]).toEqual(undefined);
|
|
270
|
+
// @ts-ignore
|
|
271
|
+
const inspected = util.inspect(madeFieldInstance);
|
|
272
|
+
const expected = 'MadeFieldClass { myField: [Getter/Setter] }';
|
|
273
|
+
expect(expected).toEqual(expected);
|
|
191
274
|
});
|
|
192
275
|
|
|
193
276
|
test('wrong assignment to objects', () => {
|