typeomatica 0.3.2 → 0.3.4
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.js +1 -0
- package/lib/fields.d.ts +1 -1
- package/lib/fields.js +1 -0
- package/lib/index.d.ts +12 -6
- package/lib/index.js +137 -18
- package/lib/types/functions.js +1 -0
- package/lib/types/index.js +1 -0
- package/lib/types/nullish.js +1 -0
- package/lib/types/objects.js +1 -0
- package/lib/types/primitives.js +1 -0
- package/lib/types/special.js +1 -0
- package/package.json +40 -18
- package/.editorconfig +0 -11
- package/.eslintignore +0 -0
- package/.eslintrc.js +0 -76
- package/.gitattributes +0 -22
- package/.github/workflows/node.js.yml +0 -62
- package/.husky/pre-commit +0 -4
- package/jest.config.js +0 -8
- package/src/errors.ts +0 -9
- package/src/fields.ts +0 -76
- package/src/index.ts +0 -184
- package/src/types/functions.ts +0 -7
- package/src/types/index.ts +0 -17
- package/src/types/nullish.ts +0 -15
- package/src/types/objects.ts +0 -19
- package/src/types/primitives.ts +0 -69
- package/src/types/special.ts +0 -19
- package/test/__snapshots__/index.ts.snap +0 -3
- package/test/addition.js +0 -43
- package/test/index.ts +0 -622
- package/tsconfig.jest.json +0 -38
- package/tsconfig.json +0 -34
package/src/fields.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { ErrorsNames } from './errors'
|
|
4
|
-
|
|
5
|
-
const SymbolInitialValue = Symbol('Initial Value');
|
|
6
|
-
|
|
7
|
-
interface FieldDefinition {
|
|
8
|
-
[SymbolInitialValue]: unknown
|
|
9
|
-
// get?: unknown
|
|
10
|
-
// set?: unknown
|
|
11
|
-
// configurable: boolean,
|
|
12
|
-
// enumerable: boolean,
|
|
13
|
-
// writable: boolean
|
|
14
|
-
}
|
|
15
|
-
|
|
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
|
-
static get SymbolInitialValue () {
|
|
37
|
-
return SymbolInitialValue;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Object.assign(FieldConstructor.prototype, {
|
|
42
|
-
// configurable: false,
|
|
43
|
-
// enumerable: false,
|
|
44
|
-
// // writable: false
|
|
45
|
-
// })
|
|
46
|
-
|
|
47
|
-
// Object.defineProperty(FieldConstructor.prototype, 'get', {
|
|
48
|
-
// get() {
|
|
49
|
-
// return this[symbolValue];
|
|
50
|
-
// },
|
|
51
|
-
// // @ts-ignore
|
|
52
|
-
// set(value: unknown) {
|
|
53
|
-
// throw new Error('broken behaviour: assignment to getter');
|
|
54
|
-
// },
|
|
55
|
-
// configurable: false,
|
|
56
|
-
// enumerable: true,
|
|
57
|
-
// // writable: false
|
|
58
|
-
// });
|
|
59
|
-
|
|
60
|
-
// Object.defineProperty(FieldConstructor.prototype, 'set', {
|
|
61
|
-
// get() {
|
|
62
|
-
// return function (this: FieldDefinition, value: unknown) {
|
|
63
|
-
// this[symbolValue] = value;
|
|
64
|
-
// }
|
|
65
|
-
// },
|
|
66
|
-
// // @ts-ignore
|
|
67
|
-
// set(value: unknown) {
|
|
68
|
-
// throw new Error('broken behaviour: assignment to setter');
|
|
69
|
-
// },
|
|
70
|
-
// configurable: false,
|
|
71
|
-
// enumerable: true,
|
|
72
|
-
// // writable: false
|
|
73
|
-
// });
|
|
74
|
-
|
|
75
|
-
Object.freeze(FieldConstructor.prototype);
|
|
76
|
-
Object.seal(FieldConstructor.prototype);
|
package/src/index.ts
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { ErrorsNames } from './errors';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
functions,
|
|
7
|
-
nullish,
|
|
8
|
-
objects,
|
|
9
|
-
primitives,
|
|
10
|
-
special,
|
|
11
|
-
isPrimitive
|
|
12
|
-
} from './types';
|
|
13
|
-
|
|
14
|
-
import { FieldConstructor } from './fields';
|
|
15
|
-
|
|
16
|
-
const resolver = Object.entries({
|
|
17
|
-
primitives,
|
|
18
|
-
special,
|
|
19
|
-
nullish,
|
|
20
|
-
objects,
|
|
21
|
-
functions
|
|
22
|
-
}).reduce((obj: object, [key, _handler]) => {
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
obj[key] = function (initialValue: object, receiver: object) {
|
|
25
|
-
const handler = _handler(initialValue);
|
|
26
|
-
return {
|
|
27
|
-
get() {
|
|
28
|
-
const invocationThis = this;
|
|
29
|
-
if (invocationThis !== receiver) {
|
|
30
|
-
throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
31
|
-
}
|
|
32
|
-
const result = handler.get();
|
|
33
|
-
return result;
|
|
34
|
-
},
|
|
35
|
-
set(replacementValue: unknown) {
|
|
36
|
-
const invocationThis = this;
|
|
37
|
-
if (invocationThis !== receiver) {
|
|
38
|
-
throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
39
|
-
}
|
|
40
|
-
const result = handler.set(replacementValue);
|
|
41
|
-
return result;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
return obj;
|
|
47
|
-
}, {});
|
|
48
|
-
|
|
49
|
-
const createProperty = (propName: string, initialValue: unknown, receiver: object) => {
|
|
50
|
-
|
|
51
|
-
const value = initialValue;
|
|
52
|
-
const valueIsPrimitive = isPrimitive(initialValue);
|
|
53
|
-
const isObject = typeof initialValue === 'object';
|
|
54
|
-
const isFunction = initialValue instanceof Function;
|
|
55
|
-
const isNull = initialValue === null;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* special: undefined or BigInt or Symbol
|
|
59
|
-
* or other non constructible type
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
const type = valueIsPrimitive ? 'primitives' : (
|
|
63
|
-
isObject ? (
|
|
64
|
-
isNull ? 'nullish' : 'objects'
|
|
65
|
-
) : (
|
|
66
|
-
isFunction ? 'functions' : 'special'
|
|
67
|
-
)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const descriptor = (isObject && (value instanceof FieldConstructor)) ?
|
|
71
|
-
value
|
|
72
|
-
:
|
|
73
|
-
{
|
|
74
|
-
enumerable: true,
|
|
75
|
-
// @ts-ignore
|
|
76
|
-
...resolver[type](value, receiver),
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// if (value instanceof FieldConstructor) {
|
|
80
|
-
// descriptor;
|
|
81
|
-
// debugger;
|
|
82
|
-
// }
|
|
83
|
-
|
|
84
|
-
const result = Reflect.defineProperty(receiver, propName, descriptor);
|
|
85
|
-
return result;
|
|
86
|
-
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
|
|
90
|
-
const util = require('util');
|
|
91
|
-
const hasNodeInspect = (util && util.inspect && util.inspect.custom);
|
|
92
|
-
hasNodeInspect && (props2skip.add(util.inspect.custom));
|
|
93
|
-
|
|
94
|
-
const handlers = {
|
|
95
|
-
get(target: object, prop: string | symbol, receiver: object) {
|
|
96
|
-
const result = Reflect.get(target, prop, receiver);
|
|
97
|
-
if (result !== undefined) {
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
if (prop === 'toJSON') {
|
|
101
|
-
return function (this: typeof target) {
|
|
102
|
-
return JSON.stringify(Object.entries(this).reduce((obj, [key, value]) => {
|
|
103
|
-
// @ts-ignore
|
|
104
|
-
obj[key] = value.valueOf();
|
|
105
|
-
return obj;
|
|
106
|
-
}, {}));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// @ts-ignore
|
|
110
|
-
if (props2skip.has(prop)) {
|
|
111
|
-
return undefined;
|
|
112
|
-
}
|
|
113
|
-
throw new Error(`${ErrorsNames.MISSING_PROP}: [ ${String(prop).valueOf()} ] of ${receiver.constructor.name}`);
|
|
114
|
-
},
|
|
115
|
-
set(_: object, prop: string, value: unknown, receiver: object) {
|
|
116
|
-
const result = createProperty(prop, value, receiver);
|
|
117
|
-
return result;
|
|
118
|
-
},
|
|
119
|
-
// defineProperty(target: object, key: string, descriptor: object) {
|
|
120
|
-
// Reflect.defineProperty(target, key, descriptor);
|
|
121
|
-
// return true;
|
|
122
|
-
// }
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// user have to precisely define all props
|
|
126
|
-
const BaseTarget = Object.create(null);
|
|
127
|
-
|
|
128
|
-
// const BasePrototype = new Proxy(BaseTarget, handlers);
|
|
129
|
-
|
|
130
|
-
// @ts-ignore
|
|
131
|
-
const BaseConstructor = function (this: object, InstanceTarget = BaseTarget) {
|
|
132
|
-
if (!new.target) {
|
|
133
|
-
const self = BaseConstructor.bind(this, InstanceTarget);
|
|
134
|
-
self.prototype = {
|
|
135
|
-
constructor: BaseConstructor
|
|
136
|
-
};
|
|
137
|
-
return self;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const InstancePrototype = new Proxy(InstanceTarget, handlers);
|
|
141
|
-
|
|
142
|
-
let protoPointer = this;
|
|
143
|
-
let protoConstrcutor;
|
|
144
|
-
do {
|
|
145
|
-
protoPointer = Reflect.getPrototypeOf(protoPointer) as object;
|
|
146
|
-
protoConstrcutor = Reflect.getOwnPropertyDescriptor(protoPointer, 'constructor')!.value;
|
|
147
|
-
} while (protoConstrcutor !== BaseConstructor);
|
|
148
|
-
Reflect.setPrototypeOf(protoPointer, InstancePrototype);
|
|
149
|
-
|
|
150
|
-
} as ObjectConstructor;
|
|
151
|
-
// } as IDEF;
|
|
152
|
-
|
|
153
|
-
// Reflect.setPrototypeOf(BaseConstructor.prototype, BasePrototype);
|
|
154
|
-
|
|
155
|
-
Object.defineProperty(module, 'exports', {
|
|
156
|
-
get() {
|
|
157
|
-
return BaseConstructor;
|
|
158
|
-
},
|
|
159
|
-
enumerable: true
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// @ts-ignore
|
|
163
|
-
export class BaseClass extends BaseConstructor { };
|
|
164
|
-
// export { FieldConstructor } from './fields';
|
|
165
|
-
|
|
166
|
-
Object.defineProperty(module.exports, 'BaseClass', {
|
|
167
|
-
get() {
|
|
168
|
-
return BaseClass;
|
|
169
|
-
},
|
|
170
|
-
enumerable: true
|
|
171
|
-
});
|
|
172
|
-
Object.defineProperty(module.exports, 'FieldConstructor', {
|
|
173
|
-
get() {
|
|
174
|
-
return FieldConstructor;
|
|
175
|
-
},
|
|
176
|
-
enumerable: true
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
export type IDEF<T, P = {}, R = {}> = {
|
|
181
|
-
new(...args: unknown[]): T;
|
|
182
|
-
(this: T, ...args: unknown[]): R;
|
|
183
|
-
prototype: P;
|
|
184
|
-
};
|
package/src/types/functions.ts
DELETED
package/src/types/index.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
export { functions } from './functions';
|
|
4
|
-
export { nullish } from './nullish';
|
|
5
|
-
export { objects } from './objects';
|
|
6
|
-
export { primitives } from './primitives';
|
|
7
|
-
export { special } from './special';
|
|
8
|
-
|
|
9
|
-
const PRIMITIVE_TYPES = [
|
|
10
|
-
'string',
|
|
11
|
-
'number',
|
|
12
|
-
'boolean',
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
export const isPrimitive = (value: unknown) => {
|
|
16
|
-
return PRIMITIVE_TYPES.includes(typeof value);
|
|
17
|
-
};
|
package/src/types/nullish.ts
DELETED
package/src/types/objects.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { ErrorsNames } from '../errors';
|
|
4
|
-
|
|
5
|
-
export const objects = (value: object) => {
|
|
6
|
-
return {
|
|
7
|
-
get() {
|
|
8
|
-
return value;
|
|
9
|
-
},
|
|
10
|
-
set(replacementValue: unknown) {
|
|
11
|
-
if (replacementValue instanceof Object && replacementValue.constructor === value.constructor) {
|
|
12
|
-
value = replacementValue;
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
const error = new TypeError(ErrorsNames.TYPE_MISMATCH);
|
|
16
|
-
throw error;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
};
|
package/src/types/primitives.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { ErrorsNames } from '../errors';
|
|
4
|
-
|
|
5
|
-
export const primitives = (initialValue: object) => {
|
|
6
|
-
let value = Object(initialValue);
|
|
7
|
-
const initialType = typeof initialValue;
|
|
8
|
-
|
|
9
|
-
return {
|
|
10
|
-
get() {
|
|
11
|
-
const proxyAsValue = new Proxy(value, {
|
|
12
|
-
// get(target, prop, receiver) {
|
|
13
|
-
get(_, prop) {
|
|
14
|
-
if (prop === Symbol.toPrimitive) {
|
|
15
|
-
return function (hint: string) {
|
|
16
|
-
if (hint !== initialType) {
|
|
17
|
-
throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
18
|
-
}
|
|
19
|
-
return value.valueOf();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (prop === 'valueOf') {
|
|
24
|
-
return function () {
|
|
25
|
-
return value.valueOf();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// @ts-ignore
|
|
30
|
-
if (value[prop] instanceof Function) {
|
|
31
|
-
return value[prop].bind(value);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const answer = value[prop];
|
|
35
|
-
return answer;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
return proxyAsValue;
|
|
39
|
-
},
|
|
40
|
-
// get() {
|
|
41
|
-
// const preparedValue = {
|
|
42
|
-
// [Symbol.toPrimitive]() {
|
|
43
|
-
// return function () {
|
|
44
|
-
// throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
45
|
-
// };
|
|
46
|
-
// }
|
|
47
|
-
// };
|
|
48
|
-
// Reflect.setPrototypeOf(preparedValue, value);
|
|
49
|
-
// debugger;
|
|
50
|
-
// return preparedValue;
|
|
51
|
-
// },
|
|
52
|
-
set(replacementValue: unknown) {
|
|
53
|
-
if (replacementValue instanceof value.constructor) {
|
|
54
|
-
value = replacementValue;
|
|
55
|
-
return value;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const prevalue = Object(replacementValue);
|
|
59
|
-
|
|
60
|
-
if (prevalue instanceof value.constructor) {
|
|
61
|
-
value = prevalue;
|
|
62
|
-
return value;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const error = new TypeError(ErrorsNames.TYPE_MISMATCH);
|
|
66
|
-
throw error;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
};
|
package/src/types/special.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
import { ErrorsNames } from '../errors';
|
|
4
|
-
|
|
5
|
-
export const special = (value: object) => {
|
|
6
|
-
return {
|
|
7
|
-
get() {
|
|
8
|
-
return value;
|
|
9
|
-
},
|
|
10
|
-
set(replacementValue: object) {
|
|
11
|
-
if (typeof replacementValue === typeof value) {
|
|
12
|
-
value = replacementValue;
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
const error = new TypeError(ErrorsNames.TYPE_MISMATCH);
|
|
16
|
-
throw error;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
};
|
package/test/addition.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const BasePrototype = require('..');
|
|
4
|
-
|
|
5
|
-
class Base extends BasePrototype({
|
|
6
|
-
additionalProp: 321,
|
|
7
|
-
}) {
|
|
8
|
-
numberValue = 123;
|
|
9
|
-
constructor() {
|
|
10
|
-
super();
|
|
11
|
-
this.stringValue = '123';
|
|
12
|
-
this.booleanValue = true;
|
|
13
|
-
this.objectValue = {};
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const baseInstance = new Base;
|
|
18
|
-
|
|
19
|
-
describe('props tests', () => {
|
|
20
|
-
|
|
21
|
-
test('base instance has props', () => {
|
|
22
|
-
expect(Object.keys(baseInstance)).toEqual(["numberValue", "stringValue", "booleanValue", "objectValue"]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('JavaScript class fields allow re-definition', () => {
|
|
26
|
-
baseInstance.numberValue = '123';
|
|
27
|
-
expect(baseInstance.numberValue).toEqual('123');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('everything the rest is the same', () => {
|
|
31
|
-
expect(baseInstance.additionalProp).toEqual(321);
|
|
32
|
-
expect(() => {
|
|
33
|
-
baseInstance.stringValue = 123;
|
|
34
|
-
}).toThrow(new TypeError('Type Mismatch'));
|
|
35
|
-
expect(() => {
|
|
36
|
-
baseInstance.booleanValue = 123;
|
|
37
|
-
}).toThrow(new TypeError('Type Mismatch'));
|
|
38
|
-
expect(() => {
|
|
39
|
-
baseInstance.objectValue = null;
|
|
40
|
-
}).toThrow(new TypeError('Type Mismatch'));
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
});
|