typeomatica 0.2.9 → 0.3.0
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/fields.d.ts +2 -1
- package/lib/fields.js +9 -6
- package/lib/index.d.ts +1 -1
- package/lib/index.js +9 -12
- package/lib/types/primitives.js +2 -1
- package/package.json +8 -8
- package/src/fields.ts +5 -2
- package/src/index.ts +9 -12
- package/src/types/primitives.ts +2 -1
- package/test/index.ts +72 -6
- package/tsconfig.jest.json +6 -2
package/lib/fields.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
declare const SymbolInitialValue: unique symbol;
|
|
2
2
|
interface FieldDefinition {
|
|
3
3
|
[SymbolInitialValue]: unknown;
|
|
4
4
|
}
|
|
@@ -7,5 +7,6 @@ export declare class FieldConstructor implements FieldDefinition {
|
|
|
7
7
|
get get(): (this: FieldDefinition) => unknown;
|
|
8
8
|
get set(): () => never;
|
|
9
9
|
constructor(value: unknown);
|
|
10
|
+
static get SymbolInitialValue(): symbol;
|
|
10
11
|
}
|
|
11
12
|
export {};
|
package/lib/fields.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FieldConstructor =
|
|
4
|
-
exports.SymbolInitialValue = Symbol('Initial Value');
|
|
3
|
+
exports.FieldConstructor = void 0;
|
|
5
4
|
const errors_1 = require("./errors");
|
|
5
|
+
const SymbolInitialValue = Symbol('Initial Value');
|
|
6
6
|
class FieldConstructor {
|
|
7
|
-
constructor(value) {
|
|
8
|
-
this[exports.SymbolInitialValue] = value;
|
|
9
|
-
}
|
|
10
7
|
get get() {
|
|
11
8
|
const self = this;
|
|
12
9
|
return function () {
|
|
13
|
-
return self[
|
|
10
|
+
return self[SymbolInitialValue];
|
|
14
11
|
};
|
|
15
12
|
}
|
|
16
13
|
get set() {
|
|
@@ -18,6 +15,12 @@ class FieldConstructor {
|
|
|
18
15
|
throw new TypeError(errors_1.ErrorsNames.FORBIDDEN_RE);
|
|
19
16
|
};
|
|
20
17
|
}
|
|
18
|
+
constructor(value) {
|
|
19
|
+
this[SymbolInitialValue] = value;
|
|
20
|
+
}
|
|
21
|
+
static get SymbolInitialValue() {
|
|
22
|
+
return SymbolInitialValue;
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
exports.FieldConstructor = FieldConstructor;
|
|
23
26
|
Object.freeze(FieldConstructor.prototype);
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare const BaseConstructor: ObjectConstructor;
|
|
2
2
|
export declare class BaseClass extends BaseConstructor {
|
|
3
3
|
}
|
|
4
|
-
export
|
|
4
|
+
export type IDEF<T, P = {}, R = {}> = {
|
|
5
5
|
new (...args: unknown[]): T;
|
|
6
6
|
(this: T, ...args: unknown[]): R;
|
|
7
7
|
prototype: P;
|
package/lib/index.js
CHANGED
|
@@ -19,14 +19,16 @@ const resolver = Object.entries({
|
|
|
19
19
|
if (invocationThis !== receiver) {
|
|
20
20
|
throw new ReferenceError(errors_1.ErrorsNames.ACCESS_DENIED);
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
const result = handler.get();
|
|
23
|
+
return result;
|
|
23
24
|
},
|
|
24
25
|
set(replacementValue) {
|
|
25
26
|
const invocationThis = this;
|
|
26
27
|
if (invocationThis !== receiver) {
|
|
27
28
|
throw new ReferenceError(errors_1.ErrorsNames.ACCESS_DENIED);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
const result = handler.set(replacementValue);
|
|
31
|
+
return result;
|
|
30
32
|
}
|
|
31
33
|
};
|
|
32
34
|
};
|
|
@@ -42,13 +44,8 @@ const createProperty = (propName, initialValue, receiver) => {
|
|
|
42
44
|
const descriptor = (isObject && (value instanceof fields_1.FieldConstructor)) ?
|
|
43
45
|
value
|
|
44
46
|
: Object.assign({ enumerable: true }, resolver[type](value, receiver));
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
catch (error) {
|
|
50
|
-
throw error;
|
|
51
|
-
}
|
|
47
|
+
const result = Reflect.defineProperty(receiver, propName, descriptor);
|
|
48
|
+
return result;
|
|
52
49
|
};
|
|
53
50
|
const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
|
|
54
51
|
const util = require('util');
|
|
@@ -81,11 +78,11 @@ const handlers = {
|
|
|
81
78
|
const BaseTarget = Object.create(null);
|
|
82
79
|
const BaseConstructor = function (InstanceTarget = BaseTarget) {
|
|
83
80
|
if (!new.target) {
|
|
84
|
-
const
|
|
85
|
-
|
|
81
|
+
const self = BaseConstructor.bind(this, InstanceTarget);
|
|
82
|
+
self.prototype = {
|
|
86
83
|
constructor: BaseConstructor
|
|
87
84
|
};
|
|
88
|
-
return
|
|
85
|
+
return self;
|
|
89
86
|
}
|
|
90
87
|
const InstancePrototype = new Proxy(InstanceTarget, handlers);
|
|
91
88
|
let protoPointer = this;
|
package/lib/types/primitives.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typeomatica",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "type logic against javascript metaprogramming",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=14"
|
|
@@ -30,16 +30,16 @@
|
|
|
30
30
|
"url": "git+https://github.com/wentout/typeomatica.git"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/jest": "^29.
|
|
34
|
-
"@types/node": "^18.
|
|
35
|
-
"eslint": "^8.
|
|
33
|
+
"@types/jest": "^29.5.0",
|
|
34
|
+
"@types/node": "^18.15.5",
|
|
35
|
+
"eslint": "^8.36.0",
|
|
36
36
|
"husky": "^8.0.3",
|
|
37
|
-
"jest": "^29.
|
|
37
|
+
"jest": "^29.5.0",
|
|
38
38
|
"json5": "^2.2.3",
|
|
39
|
-
"lint-staged": "^13.
|
|
39
|
+
"lint-staged": "^13.2.0",
|
|
40
40
|
"set-value": "^4.1.0",
|
|
41
|
-
"ts-jest": "^29.0.
|
|
41
|
+
"ts-jest": "^29.0.5",
|
|
42
42
|
"ts-node": "^10.9.1",
|
|
43
|
-
"typescript": "^
|
|
43
|
+
"typescript": "^5.0.2"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/fields.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
export const SymbolInitialValue = Symbol('Initial Value');
|
|
4
|
-
|
|
5
3
|
import { ErrorsNames } from './errors'
|
|
6
4
|
|
|
5
|
+
const SymbolInitialValue = Symbol('Initial Value');
|
|
6
|
+
|
|
7
7
|
interface FieldDefinition {
|
|
8
8
|
[SymbolInitialValue]: unknown
|
|
9
9
|
// get?: unknown
|
|
@@ -33,6 +33,9 @@ export class FieldConstructor implements FieldDefinition {
|
|
|
33
33
|
constructor (value: unknown) {
|
|
34
34
|
this[SymbolInitialValue] = value;
|
|
35
35
|
}
|
|
36
|
+
static get SymbolInitialValue () {
|
|
37
|
+
return SymbolInitialValue;
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
// Object.assign(FieldConstructor.prototype, {
|
package/src/index.ts
CHANGED
|
@@ -29,14 +29,16 @@ const resolver = Object.entries({
|
|
|
29
29
|
if (invocationThis !== receiver) {
|
|
30
30
|
throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
const result = handler.get();
|
|
33
|
+
return result;
|
|
33
34
|
},
|
|
34
35
|
set(replacementValue: unknown) {
|
|
35
36
|
const invocationThis = this;
|
|
36
37
|
if (invocationThis !== receiver) {
|
|
37
38
|
throw new ReferenceError(ErrorsNames.ACCESS_DENIED);
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
+
const result = handler.set(replacementValue);
|
|
41
|
+
return result;
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
};
|
|
@@ -79,13 +81,8 @@ const createProperty = (propName: string, initialValue: unknown, receiver: objec
|
|
|
79
81
|
// debugger;
|
|
80
82
|
// }
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return result;
|
|
85
|
-
} catch (error) {
|
|
86
|
-
// debugger;
|
|
87
|
-
throw error;
|
|
88
|
-
}
|
|
84
|
+
const result = Reflect.defineProperty(receiver, propName, descriptor);
|
|
85
|
+
return result;
|
|
89
86
|
|
|
90
87
|
};
|
|
91
88
|
|
|
@@ -133,11 +130,11 @@ const BaseTarget = Object.create(null);
|
|
|
133
130
|
// @ts-ignore
|
|
134
131
|
const BaseConstructor = function (this: object, InstanceTarget = BaseTarget) {
|
|
135
132
|
if (!new.target) {
|
|
136
|
-
const
|
|
137
|
-
|
|
133
|
+
const self = BaseConstructor.bind(this, InstanceTarget);
|
|
134
|
+
self.prototype = {
|
|
138
135
|
constructor: BaseConstructor
|
|
139
136
|
};
|
|
140
|
-
return
|
|
137
|
+
return self;
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
const InstancePrototype = new Proxy(InstanceTarget, handlers);
|
package/src/types/primitives.ts
CHANGED
package/test/index.ts
CHANGED
|
@@ -10,16 +10,31 @@ const BasePrototype = require('..');
|
|
|
10
10
|
// @ts-ignore
|
|
11
11
|
import { BaseClass, IDEF, FieldConstructor } from '..';
|
|
12
12
|
|
|
13
|
+
const { SymbolInitialValue } = FieldConstructor;
|
|
14
|
+
|
|
15
|
+
interface IBase {
|
|
16
|
+
get getterField(): string
|
|
17
|
+
set setterField(value: string)
|
|
18
|
+
numberValue: number
|
|
19
|
+
stringValue: string
|
|
20
|
+
booleanValue: boolean
|
|
21
|
+
objectValue: object
|
|
22
|
+
}
|
|
23
|
+
|
|
13
24
|
class Base extends BasePrototype({
|
|
14
25
|
additionalProp: 321,
|
|
15
26
|
someMethod() {
|
|
16
27
|
return this.numberValue.valueOf();
|
|
17
28
|
},
|
|
18
|
-
}) {
|
|
29
|
+
}) implements IBase {
|
|
19
30
|
numberValue = 123;
|
|
31
|
+
stringValue: string
|
|
32
|
+
booleanValue: boolean
|
|
33
|
+
objectValue: object
|
|
20
34
|
|
|
21
35
|
get getterField() {
|
|
22
|
-
|
|
36
|
+
const answer = `${this.stringValue}`;
|
|
37
|
+
return answer;
|
|
23
38
|
}
|
|
24
39
|
|
|
25
40
|
set setterField(value: string) {
|
|
@@ -138,7 +153,20 @@ const myField = new MyFieldConstructor('initial value');
|
|
|
138
153
|
const myFieldReGet = new MyFieldConstructorReGet('initial value for get check');
|
|
139
154
|
const myFieldReSet = new MyFieldConstructorReSet('initial value for set check');
|
|
140
155
|
|
|
141
|
-
class MadeFieldClass extends BaseClass {
|
|
156
|
+
class MadeFieldClass extends BaseClass {
|
|
157
|
+
myField = myField as unknown | string
|
|
158
|
+
get [SymbolInitialValue] () {
|
|
159
|
+
const self = this;
|
|
160
|
+
return (fieldName: 'myField') => {
|
|
161
|
+
if (fieldName !== 'myField') {
|
|
162
|
+
return self[fieldName];
|
|
163
|
+
}
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
const answer = myField[SymbolInitialValue];
|
|
166
|
+
return answer;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
};
|
|
142
170
|
class SecondMadeFieldClass extends BaseClass { myField = myField as unknown | string };
|
|
143
171
|
const madeFieldInstance = new MadeFieldClass;
|
|
144
172
|
const secondMadeFieldInstance = new MadeFieldClass;
|
|
@@ -152,12 +180,36 @@ const madeReSet = new MadeReSet;
|
|
|
152
180
|
describe('props tests', () => {
|
|
153
181
|
|
|
154
182
|
test('base instance has props', () => {
|
|
183
|
+
var gf: string;
|
|
184
|
+
var sv: string;
|
|
155
185
|
expect(Object.keys(baseInstance)).toEqual(["numberValue", "stringValue", "booleanValue", "objectValue"]);
|
|
186
|
+
|
|
187
|
+
gf = baseInstance.getterField;
|
|
188
|
+
expect(gf).toEqual('123');
|
|
189
|
+
sv = baseInstance.stringValue;
|
|
190
|
+
expect(sv.valueOf()).toEqual('123');
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
baseInstance.setterField = '12345';
|
|
194
|
+
|
|
195
|
+
gf = baseInstance.getterField;
|
|
196
|
+
expect(gf).toEqual('12345');
|
|
197
|
+
sv = baseInstance.stringValue;
|
|
198
|
+
expect(sv.valueOf()).toEqual('12345');
|
|
199
|
+
|
|
200
|
+
baseInstance.setterField = '123';
|
|
201
|
+
|
|
202
|
+
gf = baseInstance.getterField;
|
|
203
|
+
expect(gf).toEqual('123');
|
|
204
|
+
sv = baseInstance.stringValue;
|
|
205
|
+
expect(`${sv}`).toEqual('123');
|
|
156
206
|
});
|
|
157
207
|
|
|
158
208
|
test('simple instance works & strings too', () => {
|
|
159
209
|
expect(simpleInstance.stringProp.toString()).toBe('123');
|
|
160
210
|
expect(simpleInstance.stringProp.length).toBe(3);
|
|
211
|
+
|
|
212
|
+
|
|
161
213
|
expect(/String$/.test(simpleInstance.stringProp.constructor.name)).toBe(true);
|
|
162
214
|
expect(() => {
|
|
163
215
|
|
|
@@ -179,6 +231,7 @@ describe('props tests', () => {
|
|
|
179
231
|
test('fails boolean arithmetics', () => {
|
|
180
232
|
expect(() => {
|
|
181
233
|
|
|
234
|
+
// @ts-ignore
|
|
182
235
|
baseInstance.booleanValue + 5;
|
|
183
236
|
|
|
184
237
|
}).toThrow(new ReferenceError('Value Access Denied'));
|
|
@@ -191,12 +244,13 @@ describe('props tests', () => {
|
|
|
191
244
|
|
|
192
245
|
// warning!
|
|
193
246
|
// booleanValue does not rely on baseInstance anymore!
|
|
247
|
+
// @ts-ignore
|
|
194
248
|
booleanValue = new Boolean(false);
|
|
195
249
|
|
|
196
250
|
let value = baseInstance.booleanValue.valueOf();
|
|
197
251
|
expect(value).toEqual(true);
|
|
198
252
|
|
|
199
|
-
|
|
253
|
+
// @ts-ignore
|
|
200
254
|
baseInstance.booleanValue = new Boolean(false);
|
|
201
255
|
value = baseInstance.booleanValue.valueOf();
|
|
202
256
|
expect(value).toEqual(false);
|
|
@@ -214,6 +268,7 @@ describe('props tests', () => {
|
|
|
214
268
|
|
|
215
269
|
test('correct object assignment', () => {
|
|
216
270
|
baseInstance.objectValue = { a: 123 };
|
|
271
|
+
// @ts-ignore
|
|
217
272
|
expect(baseInstance.objectValue.a).toEqual(123);
|
|
218
273
|
});
|
|
219
274
|
|
|
@@ -222,6 +277,17 @@ describe('props tests', () => {
|
|
|
222
277
|
});
|
|
223
278
|
|
|
224
279
|
test('correct custom field assignment', () => {
|
|
280
|
+
madeFieldInstance.myField = 'replaced';
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
const initialValue = madeFieldInstance[SymbolInitialValue]('myField');
|
|
283
|
+
expect(initialValue).toEqual('initial value');
|
|
284
|
+
expect(secondMadeFieldInstance.myField).toEqual('replaced');
|
|
285
|
+
expect(thirdMadeFieldInstance.myField).toEqual('replaced');
|
|
286
|
+
|
|
287
|
+
madeFieldInstance.myField = 'replaced secondary';
|
|
288
|
+
expect(secondMadeFieldInstance.myField).toEqual('replaced secondary');
|
|
289
|
+
expect(thirdMadeFieldInstance.myField).toEqual('replaced secondary');
|
|
290
|
+
|
|
225
291
|
madeFieldInstance.myField = 'replaced';
|
|
226
292
|
expect(secondMadeFieldInstance.myField).toEqual('replaced');
|
|
227
293
|
expect(thirdMadeFieldInstance.myField).toEqual('replaced');
|
|
@@ -276,7 +342,7 @@ describe('props tests', () => {
|
|
|
276
342
|
test('wrong assignment to objects', () => {
|
|
277
343
|
|
|
278
344
|
expect(() => {
|
|
279
|
-
|
|
345
|
+
// @ts-ignore
|
|
280
346
|
baseInstance.objectValue = 123;
|
|
281
347
|
|
|
282
348
|
}).toThrow(new TypeError('Type Mismatch'));
|
|
@@ -321,7 +387,7 @@ describe('props tests', () => {
|
|
|
321
387
|
|
|
322
388
|
test('wrong assignment', () => {
|
|
323
389
|
expect(() => {
|
|
324
|
-
|
|
390
|
+
// @ts-ignore
|
|
325
391
|
baseInstance.booleanValue = 123;
|
|
326
392
|
|
|
327
393
|
}).toThrow(new TypeError('Type Mismatch'));
|