@pocket-architect/core 0.1.5
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/.editorconfig +15 -0
- package/.eslintignore +2 -0
- package/.eslintrc.json +27 -0
- package/.prettierrc +12 -0
- package/build/AggregateRoot.d.ts +3 -0
- package/build/AggregateRoot.js +14 -0
- package/build/AggregateRoot.js.map +1 -0
- package/build/Entity.d.ts +8 -0
- package/build/Entity.js +37 -0
- package/build/Entity.js.map +1 -0
- package/build/Entity.spec.d.ts +1 -0
- package/build/Entity.spec.js +35 -0
- package/build/Entity.spec.js.map +1 -0
- package/build/ValueObject.d.ts +9 -0
- package/build/ValueObject.js +22 -0
- package/build/ValueObject.js.map +1 -0
- package/build/ValueObject.spec.d.ts +1 -0
- package/build/ValueObject.spec.js +33 -0
- package/build/ValueObject.spec.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +10 -0
- package/build/index.js.map +1 -0
- package/jest.config.js +18 -0
- package/package.json +39 -0
- package/src/AggregateRoot.ts +5 -0
- package/src/Entity.spec.ts +30 -0
- package/src/Entity.ts +38 -0
- package/src/ValueObject.spec.ts +27 -0
- package/src/ValueObject.ts +25 -0
- package/src/index.ts +10 -0
- package/tsconfig.json +30 -0
- package/tsconfig.release.json +9 -0
package/.editorconfig
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
trim_trailing_whitespace = true
|
|
7
|
+
insert_final_newline = true
|
|
8
|
+
|
|
9
|
+
[*.md]
|
|
10
|
+
insert_final_newline = false
|
|
11
|
+
trim_trailing_whitespace = false
|
|
12
|
+
|
|
13
|
+
[*.{js,json,ts,mts,yml,yaml}]
|
|
14
|
+
indent_size = 2
|
|
15
|
+
indent_style = space
|
package/.eslintignore
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": false,
|
|
4
|
+
"es6": true,
|
|
5
|
+
"node": true
|
|
6
|
+
},
|
|
7
|
+
"parser": "@typescript-eslint/parser",
|
|
8
|
+
"parserOptions": {
|
|
9
|
+
"project": "tsconfig.json",
|
|
10
|
+
"sourceType": "module",
|
|
11
|
+
"ecmaVersion": 2020
|
|
12
|
+
},
|
|
13
|
+
"plugins": ["@typescript-eslint", "jest"],
|
|
14
|
+
"extends": [
|
|
15
|
+
"eslint:recommended",
|
|
16
|
+
"plugin:@typescript-eslint/recommended",
|
|
17
|
+
"plugin:jest/recommended",
|
|
18
|
+
"prettier"
|
|
19
|
+
],
|
|
20
|
+
"rules": {
|
|
21
|
+
// The following rule is enabled only to supplement the inline suppression
|
|
22
|
+
// examples, and because it is not a recommended rule, you should either
|
|
23
|
+
// disable it, or understand what it enforces.
|
|
24
|
+
// https://typescript-eslint.io/rules/explicit-function-return-type/
|
|
25
|
+
"@typescript-eslint/explicit-function-return-type": "warn"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/.prettierrc
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateRoot = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var Entity_1 = require("./Entity");
|
|
6
|
+
var AggregateRoot = /** @class */ (function (_super) {
|
|
7
|
+
tslib_1.__extends(AggregateRoot, _super);
|
|
8
|
+
function AggregateRoot() {
|
|
9
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
10
|
+
}
|
|
11
|
+
return AggregateRoot;
|
|
12
|
+
}(Entity_1.Entity));
|
|
13
|
+
exports.AggregateRoot = AggregateRoot;
|
|
14
|
+
//# sourceMappingURL=AggregateRoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateRoot.js","sourceRoot":"","sources":["../src/AggregateRoot.ts"],"names":[],"mappings":";;;;AAAA,mCAAkC;AAElC;IAA+C,yCAAS;IAAxD;;IAEA,CAAC;IAAD,oBAAC;AAAD,CAAC,AAFD,CAA+C,eAAM,GAEpD;AAFqB,sCAAa"}
|
package/build/Entity.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Entity = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var uuid_by_string_1 = tslib_1.__importDefault(require("uuid-by-string"));
|
|
6
|
+
var cuid2_1 = require("@paralleldrive/cuid2");
|
|
7
|
+
var isEntity = function (v) {
|
|
8
|
+
return v instanceof Entity;
|
|
9
|
+
};
|
|
10
|
+
var Entity = /** @class */ (function () {
|
|
11
|
+
function Entity(props, id) {
|
|
12
|
+
this._id = id ? id : (0, uuid_by_string_1.default)((0, cuid2_1.createId)(), (0, uuid_by_string_1.default)(this.constructor.name));
|
|
13
|
+
this.props = props;
|
|
14
|
+
}
|
|
15
|
+
Entity.prototype.equals = function (object) {
|
|
16
|
+
if (object === null || object === undefined) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (this === object) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (!isEntity(object)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return this._id == object._id;
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(Entity.prototype, "id", {
|
|
28
|
+
get: function () {
|
|
29
|
+
return this._id;
|
|
30
|
+
},
|
|
31
|
+
enumerable: false,
|
|
32
|
+
configurable: true
|
|
33
|
+
});
|
|
34
|
+
return Entity;
|
|
35
|
+
}());
|
|
36
|
+
exports.Entity = Entity;
|
|
37
|
+
//# sourceMappingURL=Entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.js","sourceRoot":"","sources":["../src/Entity.ts"],"names":[],"mappings":";;;;AAAA,0EAAuC;AACvC,8CAA+C;AAE/C,IAAM,QAAQ,GAAG,UAAI,CAAY;IAC/B,OAAO,CAAC,YAAY,MAAM,CAAA;AAC5B,CAAC,CAAA;AAID;IAIE,gBAAsB,KAAQ,EAAE,EAAa;QAC3C,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,wBAAU,EAAC,IAAA,gBAAQ,GAAE,EAAE,IAAA,wBAAU,EAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAEM,uBAAM,GAAb,UAAc,MAAkB;QAC9B,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAA;IAC/B,CAAC;IAED,sBAAI,sBAAE;aAAN;YACE,OAAO,IAAI,CAAC,GAAG,CAAA;QACjB,CAAC;;;OAAA;IACH,aAAC;AAAD,CAAC,AA5BD,IA4BC;AA5BqB,wBAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var Entity_1 = require("./Entity");
|
|
5
|
+
var TestEntity = /** @class */ (function (_super) {
|
|
6
|
+
tslib_1.__extends(TestEntity, _super);
|
|
7
|
+
function TestEntity() {
|
|
8
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
9
|
+
}
|
|
10
|
+
TestEntity.create = function (props, id) {
|
|
11
|
+
return new TestEntity(props, id);
|
|
12
|
+
};
|
|
13
|
+
return TestEntity;
|
|
14
|
+
}(Entity_1.Entity));
|
|
15
|
+
describe('Entity', function () {
|
|
16
|
+
var entity;
|
|
17
|
+
beforeAll(function () {
|
|
18
|
+
entity = TestEntity.create({ name: 'test' }, '1');
|
|
19
|
+
});
|
|
20
|
+
test('base', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
21
|
+
var entityNew, entity2;
|
|
22
|
+
return tslib_1.__generator(this, function (_a) {
|
|
23
|
+
entityNew = TestEntity.create({ name: 'test2' });
|
|
24
|
+
expect(entityNew.id.length).toEqual(36); // random id
|
|
25
|
+
entity2 = TestEntity.create({ name: 'test2' }, '1');
|
|
26
|
+
expect(entity.equals(entity2)).toBeTruthy(); // same id
|
|
27
|
+
expect(entity.equals(entity)).toBeTruthy(); // same instance
|
|
28
|
+
expect(entity.equals(null)).toBeFalsy(); // null
|
|
29
|
+
expect(entity.equals({ id: '1' })).toBeFalsy(); // not Entity
|
|
30
|
+
expect(entity.id).toEqual('1');
|
|
31
|
+
return [2 /*return*/];
|
|
32
|
+
});
|
|
33
|
+
}); });
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=Entity.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Entity.spec.js","sourceRoot":"","sources":["../src/Entity.spec.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAKlC;IAAyB,sCAAiB;IAA1C;;IAIA,CAAC;IAHQ,iBAAM,GAAb,UAAc,KAAgB,EAAE,EAAU;QACxC,OAAO,IAAI,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC;IACH,iBAAC;AAAD,CAAC,AAJD,CAAyB,eAAM,GAI9B;AAED,QAAQ,CAAC,QAAQ,EAAE;IACjB,IAAI,MAAkB,CAAC;IAEvB,SAAS,CAAC;QACR,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,EAAE;;;YACL,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACvD,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY;YAE/C,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU;YACvD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,gBAAgB;YAC5D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO;YAChD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAa,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa;YACzE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;;;SAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValueObject = void 0;
|
|
4
|
+
var shallow_equal_object_1 = require("shallow-equal-object");
|
|
5
|
+
var ValueObject = /** @class */ (function () {
|
|
6
|
+
function ValueObject(props) {
|
|
7
|
+
this.props = Object.freeze(props);
|
|
8
|
+
}
|
|
9
|
+
ValueObject.prototype.equals = function (vo) {
|
|
10
|
+
var props = (vo === null || vo === void 0 ? void 0 : vo.props) || vo;
|
|
11
|
+
if (vo === null || vo === undefined) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (props === undefined) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return (0, shallow_equal_object_1.shallowEqual)(this.props, props);
|
|
18
|
+
};
|
|
19
|
+
return ValueObject;
|
|
20
|
+
}());
|
|
21
|
+
exports.ValueObject = ValueObject;
|
|
22
|
+
//# sourceMappingURL=ValueObject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValueObject.js","sourceRoot":"","sources":["../src/ValueObject.ts"],"names":[],"mappings":";;;AAAA,6DAAoD;AAOpD;IAGE,qBAAuB,KAAQ;QAC7B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAEM,4BAAM,GAAb,UAAe,EAAmB;QAChC,IAAM,KAAK,GAAG,CAAA,EAAE,aAAF,EAAE,uBAAF,EAAE,CAAE,KAAK,KAAI,EAAE,CAAC;QAC9B,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAA,mCAAY,EAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IACxC,CAAC;IACH,kBAAC;AAAD,CAAC,AAjBD,IAiBC;AAjBqB,kCAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
var ValueObject_1 = require("./ValueObject");
|
|
5
|
+
var TestValueObject = /** @class */ (function (_super) {
|
|
6
|
+
tslib_1.__extends(TestValueObject, _super);
|
|
7
|
+
function TestValueObject() {
|
|
8
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
9
|
+
}
|
|
10
|
+
TestValueObject.create = function (props) {
|
|
11
|
+
return new TestValueObject(props);
|
|
12
|
+
};
|
|
13
|
+
return TestValueObject;
|
|
14
|
+
}(ValueObject_1.ValueObject));
|
|
15
|
+
describe('ValueObject', function () {
|
|
16
|
+
var entity;
|
|
17
|
+
beforeAll(function () {
|
|
18
|
+
entity = TestValueObject.create({ name: 'test' });
|
|
19
|
+
});
|
|
20
|
+
test('base', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
21
|
+
var entity2;
|
|
22
|
+
return tslib_1.__generator(this, function (_a) {
|
|
23
|
+
entity2 = TestValueObject.create({ name: 'test2' });
|
|
24
|
+
expect(entity.equals(entity2)).toBeFalsy(); // same id
|
|
25
|
+
expect(entity.equals(entity)).toBeTruthy(); // same instance
|
|
26
|
+
expect(entity.equals(null)).toBeFalsy(); // null
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
expect(entity.equals({ name: 'test' })).toBeTruthy(); // same fields
|
|
29
|
+
return [2 /*return*/];
|
|
30
|
+
});
|
|
31
|
+
}); });
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=ValueObject.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValueObject.spec.js","sourceRoot":"","sources":["../src/ValueObject.spec.ts"],"names":[],"mappings":";;;AAAA,6CAA4C;AAK5C;IAA8B,2CAAsB;IAApD;;IAIA,CAAC;IAHQ,sBAAM,GAAb,UAAc,KAAgB;QAC5B,OAAO,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IACH,sBAAC;AAAD,CAAC,AAJD,CAA8B,yBAAW,GAIxC;AAED,QAAQ,CAAC,aAAa,EAAE;IACtB,IAAI,MAAuB,CAAC;IAE5B,SAAS,CAAC;QACR,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,EAAE;;;YACL,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU;YACtD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,gBAAgB;YAC5D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO;YAChD,+DAA+D;YAC/D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,cAAc;;;SAC1E,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateRoot = exports.ValueObject = exports.Entity = void 0;
|
|
4
|
+
var Entity_1 = require("./Entity");
|
|
5
|
+
Object.defineProperty(exports, "Entity", { enumerable: true, get: function () { return Entity_1.Entity; } });
|
|
6
|
+
var ValueObject_1 = require("./ValueObject");
|
|
7
|
+
Object.defineProperty(exports, "ValueObject", { enumerable: true, get: function () { return ValueObject_1.ValueObject; } });
|
|
8
|
+
var AggregateRoot_1 = require("./AggregateRoot");
|
|
9
|
+
Object.defineProperty(exports, "AggregateRoot", { enumerable: true, get: function () { return AggregateRoot_1.AggregateRoot; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAA4C;AAK1C,uFALO,eAAM,OAKP;AAJR,6CAA4C;AAM1C,4FANO,yBAAW,OAMP;AALb,iDAAgD;AAM9C,8FANO,6BAAa,OAMP"}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
testEnvironment: 'node',
|
|
3
|
+
preset: 'ts-jest/presets/default-esm',
|
|
4
|
+
transform: {
|
|
5
|
+
'^.+\\.m?[tj]s?$': ['ts-jest', { useESM: true }],
|
|
6
|
+
},
|
|
7
|
+
moduleNameMapper: {
|
|
8
|
+
'^(\\.{1,2}/.*)\\.(m)?js$': '$1',
|
|
9
|
+
},
|
|
10
|
+
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(m)?ts$',
|
|
11
|
+
coverageDirectory: 'coverage',
|
|
12
|
+
collectCoverageFrom: [
|
|
13
|
+
'src/**/*.ts',
|
|
14
|
+
'src/**/*.mts',
|
|
15
|
+
'!src/**/*.d.ts',
|
|
16
|
+
'!src/**/*.d.mts',
|
|
17
|
+
],
|
|
18
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pocket-architect/core",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"prepublishOnly": "npm run build && npm version patch",
|
|
8
|
+
"clean": "rimraf coverage build tmp",
|
|
9
|
+
"prebuild": "npm run lint",
|
|
10
|
+
"build": "tsc -p tsconfig.json",
|
|
11
|
+
"build:watch": "tsc -w -p tsconfig.json",
|
|
12
|
+
"build:release": "npm run clean && tsc -p tsconfig.release.json",
|
|
13
|
+
"lint": "eslint . --ext .ts --ext .mts",
|
|
14
|
+
"test": "jest --coverage",
|
|
15
|
+
"prettier": "prettier --config .prettierrc --write .",
|
|
16
|
+
"test:watch": "jest --watch"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@paralleldrive/cuid2": "^2.2.2",
|
|
20
|
+
"shallow-equal-object": "^1.1.1",
|
|
21
|
+
"uuid-by-string": "^4.0.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/jest": "^29.5.11",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^6.18.0",
|
|
26
|
+
"@typescript-eslint/parser": "^6.18.0",
|
|
27
|
+
"eslint": "^8.56.0",
|
|
28
|
+
"eslint-config-prettier": "^9.1.0",
|
|
29
|
+
"eslint-plugin-jest": "^27.6.1",
|
|
30
|
+
"jest": "^29.7.0",
|
|
31
|
+
"rimraf": "^5.0.5",
|
|
32
|
+
"ts-jest": "^29.1.0",
|
|
33
|
+
"ts-node": "^10.9.1",
|
|
34
|
+
"tslib": "^2.6.2",
|
|
35
|
+
"typescript": "^5.2.2"
|
|
36
|
+
},
|
|
37
|
+
"author": "Vitalii Savchuk <esvit666@gmail.com>",
|
|
38
|
+
"license": "MIT"
|
|
39
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Entity } from './Entity';
|
|
2
|
+
|
|
3
|
+
interface TestProps {
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
class TestEntity extends Entity<TestProps> {
|
|
7
|
+
static create(props: TestProps, id?:string): TestEntity {
|
|
8
|
+
return new TestEntity(props, id);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe('Entity', () => {
|
|
13
|
+
let entity: TestEntity;
|
|
14
|
+
|
|
15
|
+
beforeAll(() => {
|
|
16
|
+
entity = TestEntity.create({ name: 'test' }, '1');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('base', async () => {
|
|
20
|
+
const entityNew = TestEntity.create({ name: 'test2' });
|
|
21
|
+
expect(entityNew.id.length).toEqual(36); // random id
|
|
22
|
+
|
|
23
|
+
const entity2 = TestEntity.create({ name: 'test2' }, '1');
|
|
24
|
+
expect(entity.equals(entity2)).toBeTruthy(); // same id
|
|
25
|
+
expect(entity.equals(entity)).toBeTruthy(); // same instance
|
|
26
|
+
expect(entity.equals(null)).toBeFalsy(); // null
|
|
27
|
+
expect(entity.equals(<TestEntity>{ id: '1' })).toBeFalsy(); // not Entity
|
|
28
|
+
expect(entity.id).toEqual('1');
|
|
29
|
+
});
|
|
30
|
+
});
|
package/src/Entity.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import createUUID from 'uuid-by-string'
|
|
2
|
+
import { createId } from '@paralleldrive/cuid2'
|
|
3
|
+
|
|
4
|
+
const isEntity = <T>(v: Entity<T>): v is Entity<T> => {
|
|
5
|
+
return v instanceof Entity
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type EntityId = string;
|
|
9
|
+
|
|
10
|
+
export abstract class Entity<T> {
|
|
11
|
+
protected readonly _id: EntityId;
|
|
12
|
+
protected props: T
|
|
13
|
+
|
|
14
|
+
protected constructor(props: T, id?: EntityId) {
|
|
15
|
+
this._id = id ? id : createUUID(createId(), createUUID(this.constructor.name));
|
|
16
|
+
this.props = props
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public equals(object?: Entity<T>): boolean {
|
|
20
|
+
if (object === null || object === undefined) {
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (this === object) {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!isEntity(object)) {
|
|
29
|
+
return false
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return this._id == object._id
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get id(): EntityId {
|
|
36
|
+
return this._id
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ValueObject } from './ValueObject';
|
|
2
|
+
|
|
3
|
+
interface TestProps {
|
|
4
|
+
name: string;
|
|
5
|
+
}
|
|
6
|
+
class TestValueObject extends ValueObject<TestProps> {
|
|
7
|
+
static create(props: TestProps): TestValueObject {
|
|
8
|
+
return new TestValueObject(props);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe('ValueObject', () => {
|
|
13
|
+
let entity: TestValueObject;
|
|
14
|
+
|
|
15
|
+
beforeAll(() => {
|
|
16
|
+
entity = TestValueObject.create({ name: 'test' });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('base', async () => {
|
|
20
|
+
const entity2 = TestValueObject.create({ name: 'test2' });
|
|
21
|
+
expect(entity.equals(entity2)).toBeFalsy(); // same id
|
|
22
|
+
expect(entity.equals(entity)).toBeTruthy(); // same instance
|
|
23
|
+
expect(entity.equals(null)).toBeFalsy(); // null
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
expect(entity.equals(<any>{ name: 'test' })).toBeTruthy(); // same fields
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { shallowEqual } from "shallow-equal-object";
|
|
2
|
+
|
|
3
|
+
interface ValueObjectProps {
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
[index: string]: any;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export abstract class ValueObject<T extends ValueObjectProps> {
|
|
9
|
+
public readonly props: T;
|
|
10
|
+
|
|
11
|
+
protected constructor (props: T) {
|
|
12
|
+
this.props = Object.freeze(props);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public equals (vo?: ValueObject<T>) : boolean {
|
|
16
|
+
const props = vo?.props || vo;
|
|
17
|
+
if (vo === null || vo === undefined) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (props === undefined) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return shallowEqual(this.props, props)
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es5",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": [
|
|
6
|
+
"es2017",
|
|
7
|
+
"es2018.asynciterable"
|
|
8
|
+
],
|
|
9
|
+
"moduleResolution": "node",
|
|
10
|
+
"rootDir": "./src",
|
|
11
|
+
"outDir": "build",
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"importHelpers": true,
|
|
14
|
+
"alwaysStrict": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"esModuleInterop": true,
|
|
18
|
+
"forceConsistentCasingInFileNames": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"noImplicitReturns": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"noImplicitAny": false,
|
|
24
|
+
"noImplicitThis": false,
|
|
25
|
+
"strictNullChecks": false,
|
|
26
|
+
"experimentalDecorators": true,
|
|
27
|
+
"skipLibCheck": true
|
|
28
|
+
},
|
|
29
|
+
"include": ["**/*", "__tests__/**/*"]
|
|
30
|
+
}
|