@coast/core-utils 0.0.3 → 0.0.6

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.
@@ -0,0 +1,9 @@
1
+ import { NonEmptyArray } from './NonEmptyArray';
2
+ type FirstElement<ARR> = ARR extends NonEmptyArray<infer U> ? U : ARR extends Array<infer U> ? U | null | undefined : never;
3
+ export declare class ArrayUtils {
4
+ static liftNonEmpty<T>(data: T[]): NonEmptyArray<T>;
5
+ static first<T, Y extends T[]>(data: Y | null | undefined): FirstElement<Y>;
6
+ static isNonEmptyArray<T>(data: T[] | null | undefined): data is NonEmptyArray<T>;
7
+ static isUniformArray<E>(value: unknown, itemGuard?: (item: unknown) => item is E): value is E[];
8
+ }
9
+ export {};
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ArrayUtils = void 0;
7
+ const CoastException_1 = require("@coast/core-types/exception/CoastException");
8
+ const lodash_1 = __importDefault(require("lodash"));
9
+ class ArrayUtils {
10
+ static liftNonEmpty(data) {
11
+ if (ArrayUtils.isNonEmptyArray(data)) {
12
+ return data;
13
+ }
14
+ throw new CoastException_1.CoastException('Cannot lift empty array');
15
+ }
16
+ static first(data) {
17
+ if (ArrayUtils.isNonEmptyArray(data)) {
18
+ return data[0];
19
+ }
20
+ return lodash_1.default.first(data);
21
+ }
22
+ static isNonEmptyArray(data) {
23
+ if (lodash_1.default.isNil(data)) {
24
+ return false;
25
+ }
26
+ return data.length > 0;
27
+ }
28
+ static isUniformArray(value, itemGuard) {
29
+ if (!lodash_1.default.isArray(value)) {
30
+ return false;
31
+ }
32
+ if (value.length === 0) {
33
+ return true;
34
+ }
35
+ if (itemGuard !== undefined) {
36
+ return value.every((item) => itemGuard(item));
37
+ }
38
+ const valueTypes = new Set(value.map((item) => typeof item));
39
+ return valueTypes.size === 1;
40
+ }
41
+ }
42
+ exports.ArrayUtils = ArrayUtils;
43
+ //# sourceMappingURL=ArrayUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArrayUtils.js","sourceRoot":"","sources":["../src/ArrayUtils.ts"],"names":[],"mappings":";;;;;;AAAA,+EAA4E;AAC5E,oDAAuB;AAYvB,MAAa,UAAU;IAOZ,MAAM,CAAC,YAAY,CAAI,IAAS;QACnC,IAAI,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,+BAAc,CAAC,yBAAyB,CAAC,CAAC;IACxD,CAAC;IAEM,MAAM,CAAC,KAAK,CAAmB,IAA0B;QAC5D,IAAI,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,CAAC,CAAoB,CAAC;QACtC,CAAC;QAED,OAAO,gBAAC,CAAC,KAAK,CAAC,IAAI,CAAoB,CAAC;IAC5C,CAAC;IAEM,MAAM,CAAC,eAAe,CAAI,IAA4B;QACzD,IAAI,gBAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEM,MAAM,CAAC,cAAc,CAAI,KAAc,EAAE,SAAwC;QACpF,IAAI,CAAC,gBAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAEtE,OAAO,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC;IACjC,CAAC;CACJ;AAhDD,gCAgDC"}
@@ -0,0 +1,11 @@
1
+ import { EntityType } from '@coast/core-types/common/EntityType';
2
+ import { CoastException } from '@coast/core-types/exception/CoastException';
3
+ export declare class AssertionUtils {
4
+ static assertIsDefined<T>(x: T | null | undefined, error?: CoastException | string): asserts x is T;
5
+ static assertValidEntityReference<T extends object>(entity: T | null | undefined, entityType: EntityType, options?: {
6
+ id?: string;
7
+ message?: string;
8
+ }): asserts entity is T;
9
+ static assert(value: unknown, error?: CoastException | string): asserts value;
10
+ static assertUnreachable(x: never): never;
11
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AssertionUtils = void 0;
7
+ const GeneralErrorCode_1 = require("@coast/core-types/error/GeneralErrorCode");
8
+ const AssertionFailedException_1 = require("@coast/core-types/exception/AssertionFailedException");
9
+ const CoastException_1 = require("@coast/core-types/exception/CoastException");
10
+ const InvalidEntityReferenceException_1 = require("@coast/core-types/exception/InvalidEntityReferenceException");
11
+ const NotDefinedException_1 = require("@coast/core-types/exception/NotDefinedException");
12
+ const DeepLogObject_1 = require("@coast/service-common/logger/DeepLogObject");
13
+ const lodash_1 = __importDefault(require("lodash"));
14
+ const node_assert_1 = __importDefault(require("node:assert"));
15
+ class AssertionUtils {
16
+ static assertIsDefined(x, error) {
17
+ if (lodash_1.default.isNil(x)) {
18
+ if (error instanceof CoastException_1.CoastException) {
19
+ throw error;
20
+ }
21
+ throw new NotDefinedException_1.NotDefinedException(error);
22
+ }
23
+ }
24
+ static assertValidEntityReference(entity, entityType, options = {}) {
25
+ AssertionUtils.assertIsDefined(entity, new InvalidEntityReferenceException_1.InvalidEntityReferenceException({
26
+ entityType,
27
+ id: options?.id,
28
+ message: options?.message,
29
+ }));
30
+ }
31
+ static assert(value, error) {
32
+ try {
33
+ (0, node_assert_1.default)(value);
34
+ }
35
+ catch {
36
+ if (error instanceof CoastException_1.CoastException) {
37
+ throw error;
38
+ }
39
+ throw new AssertionFailedException_1.AssertionFailedException(error);
40
+ }
41
+ }
42
+ static assertUnreachable(x) {
43
+ throw new CoastException_1.CoastException({
44
+ message: 'Unexpected unreachable value',
45
+ code: GeneralErrorCode_1.GeneralErrorCode.INTERNAL_ERROR,
46
+ additionalData: (0, DeepLogObject_1.DeepLogObject)(x),
47
+ });
48
+ }
49
+ }
50
+ exports.AssertionUtils = AssertionUtils;
51
+ //# sourceMappingURL=AssertionUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssertionUtils.js","sourceRoot":"","sources":["../src/AssertionUtils.ts"],"names":[],"mappings":";;;;;;AACA,+EAA4E;AAC5E,mGAAgG;AAChG,+EAA4E;AAC5E,iHAA8G;AAC9G,yFAAsF;AACtF,8EAA2E;AAC3E,oDAAuB;AACvB,8DAAqC;AAErC,MAAa,cAAc;IACvB,MAAM,CAAC,eAAe,CAAI,CAAuB,EAAE,KAA+B;QAC9E,IAAI,gBAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACb,IAAI,KAAK,YAAY,+BAAc,EAAE,CAAC;gBAClC,MAAM,KAAK,CAAC;YAChB,CAAC;YACD,MAAM,IAAI,yCAAmB,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,0BAA0B,CAC7B,MAA4B,EAC5B,UAAsB,EACtB,UAA6C,EAAE;QAE/C,cAAc,CAAC,eAAe,CAC1B,MAAM,EACN,IAAI,iEAA+B,CAAC;YAChC,UAAU;YACV,EAAE,EAAE,OAAO,EAAE,EAAE;YACf,OAAO,EAAE,OAAO,EAAE,OAAO;SAC5B,CAAC,CACL,CAAC;IACN,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,KAAc,EAAE,KAA+B;QACzD,IAAI,CAAC;YACD,IAAA,qBAAU,EAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,KAAK,YAAY,+BAAc,EAAE,CAAC;gBAClC,MAAM,KAAK,CAAC;YAChB,CAAC;YACD,MAAM,IAAI,mDAAwB,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,CAAQ;QAC7B,MAAM,IAAI,+BAAc,CAAC;YACrB,OAAO,EAAE,8BAA8B;YACvC,IAAI,EAAE,mCAAgB,CAAC,cAAc;YACrC,cAAc,EAAE,IAAA,6BAAa,EAAC,CAAC,CAAC;SACnC,CAAC,CAAC;IACP,CAAC;CACJ;AA3CD,wCA2CC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const CoastException_1 = require("@coast/core-types/exception/CoastException");
4
+ const ArrayUtils_1 = require("../ArrayUtils");
5
+ describe('ArrayUtils', () => {
6
+ describe('liftNonEmpty', () => {
7
+ it('returns the same array as a NonEmptyArray when given a non-empty array', () => {
8
+ const input = [1, 2, 3];
9
+ const result = ArrayUtils_1.ArrayUtils.liftNonEmpty(input);
10
+ expect(result).toEqual([1, 2, 3]);
11
+ });
12
+ it('returns a single-element array', () => {
13
+ const input = ['only'];
14
+ const result = ArrayUtils_1.ArrayUtils.liftNonEmpty(input);
15
+ expect(result).toEqual(['only']);
16
+ });
17
+ it('throws a CoastException when given an empty array', () => {
18
+ expect(() => ArrayUtils_1.ArrayUtils.liftNonEmpty([])).toThrow(CoastException_1.CoastException);
19
+ expect(() => ArrayUtils_1.ArrayUtils.liftNonEmpty([])).toThrow('Cannot lift empty array');
20
+ });
21
+ });
22
+ describe('first', () => {
23
+ it('returns the first element of a non-empty array', () => {
24
+ expect(ArrayUtils_1.ArrayUtils.first([10, 20, 30])).toEqual(10);
25
+ });
26
+ it('returns the first element of a single-element array', () => {
27
+ expect(ArrayUtils_1.ArrayUtils.first(['hello'])).toEqual('hello');
28
+ });
29
+ it('returns undefined for an empty array', () => {
30
+ expect(ArrayUtils_1.ArrayUtils.first([])).toBeUndefined();
31
+ });
32
+ it('returns undefined when given undefined', () => {
33
+ expect(ArrayUtils_1.ArrayUtils.first(undefined)).toBeUndefined();
34
+ });
35
+ it('returns undefined when given null', () => {
36
+ expect(ArrayUtils_1.ArrayUtils.first(null)).toBeUndefined();
37
+ });
38
+ });
39
+ describe('isNonEmptyArray', () => {
40
+ it('returns true for a non-empty array', () => {
41
+ expect(ArrayUtils_1.ArrayUtils.isNonEmptyArray([1, 2, 3])).toEqual(true);
42
+ });
43
+ it('returns true for a single-element array', () => {
44
+ expect(ArrayUtils_1.ArrayUtils.isNonEmptyArray(['item'])).toEqual(true);
45
+ });
46
+ it('returns false for an empty array', () => {
47
+ expect(ArrayUtils_1.ArrayUtils.isNonEmptyArray([])).toEqual(false);
48
+ });
49
+ it('returns false for null', () => {
50
+ expect(ArrayUtils_1.ArrayUtils.isNonEmptyArray(null)).toEqual(false);
51
+ });
52
+ it('returns false for undefined', () => {
53
+ expect(ArrayUtils_1.ArrayUtils.isNonEmptyArray(undefined)).toEqual(false);
54
+ });
55
+ });
56
+ describe('isUniformArray', () => {
57
+ it('returns true for an empty array', () => {
58
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([])).toEqual(true);
59
+ });
60
+ it('returns false for a non-array value', () => {
61
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray('not an array')).toEqual(false);
62
+ });
63
+ it('returns false for null', () => {
64
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray(null)).toEqual(false);
65
+ });
66
+ it('returns false for undefined', () => {
67
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray(undefined)).toEqual(false);
68
+ });
69
+ it('returns true for an array of uniform string types', () => {
70
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray(['a', 'b', 'c'])).toEqual(true);
71
+ });
72
+ it('returns true for an array of uniform number types', () => {
73
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([1, 2, 3])).toEqual(true);
74
+ });
75
+ it('returns false for an array of mixed types', () => {
76
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([1, 'two', 3])).toEqual(false);
77
+ });
78
+ it('returns false for an array mixing numbers and booleans', () => {
79
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([1, true, 3])).toEqual(false);
80
+ });
81
+ describe('with itemGuard', () => {
82
+ const isString = (item) => typeof item === 'string';
83
+ const isNumber = (item) => typeof item === 'number';
84
+ it('returns true when all items satisfy the guard', () => {
85
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray(['a', 'b', 'c'], isString)).toEqual(true);
86
+ });
87
+ it('returns false when any item fails the guard', () => {
88
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray(['a', 1, 'c'], isString)).toEqual(false);
89
+ });
90
+ it('returns true for an empty array regardless of guard', () => {
91
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([], isNumber)).toEqual(true);
92
+ });
93
+ it('returns true when all items satisfy a number guard', () => {
94
+ expect(ArrayUtils_1.ArrayUtils.isUniformArray([1, 2, 3], isNumber)).toEqual(true);
95
+ });
96
+ it('narrowing: correctly types result as string[] when guard passes', () => {
97
+ const value = ['x', 'y'];
98
+ if (ArrayUtils_1.ArrayUtils.isUniformArray(value, isString)) {
99
+ expect(value[0]).toEqual('x');
100
+ }
101
+ });
102
+ });
103
+ });
104
+ });
105
+ //# sourceMappingURL=ArrayUtilsTest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArrayUtilsTest.js","sourceRoot":"","sources":["../../src/test/ArrayUtilsTest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const EntityType_1 = require("@coast/core-types/common/EntityType");
4
+ const EntityTypeLabels_1 = require("@coast/core-types/common/EntityTypeLabels");
5
+ const AssertionFailedException_1 = require("@coast/core-types/exception/AssertionFailedException");
6
+ const CoastException_1 = require("@coast/core-types/exception/CoastException");
7
+ const InvalidEntityReferenceException_1 = require("@coast/core-types/exception/InvalidEntityReferenceException");
8
+ const NotDefinedException_1 = require("@coast/core-types/exception/NotDefinedException");
9
+ const assertType_1 = require("@coast/service-common/types/assertType");
10
+ const common_test_1 = require("@paradoxical-io/common-test");
11
+ const AssertionUtils_1 = require("../AssertionUtils");
12
+ describe('AssertionUtils', () => {
13
+ describe('assertIsDefined', () => {
14
+ it('should throw if value is not defined', () => {
15
+ const x = undefined;
16
+ try {
17
+ AssertionUtils_1.AssertionUtils.assertIsDefined(x);
18
+ }
19
+ catch (error) {
20
+ expect(error).toBeInstanceOf(NotDefinedException_1.NotDefinedException);
21
+ (0, common_test_1.safeExpect)(error.message).toEqual('Value is not defined');
22
+ }
23
+ });
24
+ it('should use custom error message', () => {
25
+ const x = undefined;
26
+ try {
27
+ AssertionUtils_1.AssertionUtils.assertIsDefined(x, 'x should exist...');
28
+ }
29
+ catch (error) {
30
+ expect(error).toBeInstanceOf(NotDefinedException_1.NotDefinedException);
31
+ (0, common_test_1.safeExpect)(error.message).toEqual('x should exist...');
32
+ }
33
+ });
34
+ it('should use custom Exception', () => {
35
+ const x = undefined;
36
+ try {
37
+ AssertionUtils_1.AssertionUtils.assertIsDefined(x, new CoastException_1.CoastException('custom exception'));
38
+ }
39
+ catch (error) {
40
+ expect(error).toBeInstanceOf(CoastException_1.CoastException);
41
+ (0, common_test_1.safeExpect)(error.message).toEqual('custom exception');
42
+ }
43
+ });
44
+ it('should not throw and should type narrow if value is defined', () => {
45
+ const x = '';
46
+ (0, assertType_1.assertType)();
47
+ AssertionUtils_1.AssertionUtils.assertIsDefined(x);
48
+ (0, assertType_1.assertType)();
49
+ });
50
+ });
51
+ describe('assert', () => {
52
+ it('should throw AssertionFailedException if value is falsy', () => {
53
+ try {
54
+ AssertionUtils_1.AssertionUtils.assert(false);
55
+ }
56
+ catch (error) {
57
+ expect(error).toBeInstanceOf(AssertionFailedException_1.AssertionFailedException);
58
+ }
59
+ });
60
+ it('should use custom error message', () => {
61
+ try {
62
+ AssertionUtils_1.AssertionUtils.assert(false, 'value must be truthy');
63
+ }
64
+ catch (error) {
65
+ expect(error).toBeInstanceOf(AssertionFailedException_1.AssertionFailedException);
66
+ (0, common_test_1.safeExpect)(error.message).toEqual('value must be truthy');
67
+ }
68
+ });
69
+ it('should use custom CoastException', () => {
70
+ try {
71
+ AssertionUtils_1.AssertionUtils.assert(false, new CoastException_1.CoastException('custom coast exception'));
72
+ }
73
+ catch (error) {
74
+ expect(error).toBeInstanceOf(CoastException_1.CoastException);
75
+ (0, common_test_1.safeExpect)(error.message).toEqual('custom coast exception');
76
+ }
77
+ });
78
+ it('should not throw if value is truthy', () => {
79
+ (0, common_test_1.safeExpect)(() => AssertionUtils_1.AssertionUtils.assert(true)).not.toThrow();
80
+ (0, common_test_1.safeExpect)(() => AssertionUtils_1.AssertionUtils.assert(1)).not.toThrow();
81
+ (0, common_test_1.safeExpect)(() => AssertionUtils_1.AssertionUtils.assert('hello')).not.toThrow();
82
+ (0, common_test_1.safeExpect)(() => AssertionUtils_1.AssertionUtils.assert({})).not.toThrow();
83
+ });
84
+ it('should type narrow to exclude falsy', () => {
85
+ const x = 'hello';
86
+ (0, assertType_1.assertType)();
87
+ AssertionUtils_1.AssertionUtils.assert(x);
88
+ (0, assertType_1.assertType)();
89
+ });
90
+ });
91
+ describe('assertValidEntityReference', () => {
92
+ it('should throw if value is not defined', () => {
93
+ const x = undefined;
94
+ try {
95
+ AssertionUtils_1.AssertionUtils.assertValidEntityReference(x, EntityType_1.EntityType.WORKFLOW_ENTITY);
96
+ }
97
+ catch (error) {
98
+ expect(error).toBeInstanceOf(InvalidEntityReferenceException_1.InvalidEntityReferenceException);
99
+ (0, common_test_1.safeExpect)(error.message).toEqual(`Invalid entity reference: ${EntityTypeLabels_1.EntityTypeLabels[EntityType_1.EntityType.WORKFLOW_ENTITY]} not found`);
100
+ (0, common_test_1.safeExpect)(error.additionalData).toMatchObject({
101
+ entityType: EntityType_1.EntityType.WORKFLOW_ENTITY,
102
+ });
103
+ }
104
+ });
105
+ it('should use custom error message', () => {
106
+ const x = undefined;
107
+ try {
108
+ AssertionUtils_1.AssertionUtils.assertValidEntityReference(x, EntityType_1.EntityType.WORKFLOW_ENTITY, {
109
+ message: 'x should exist...',
110
+ id: 'abc-123',
111
+ });
112
+ }
113
+ catch (error) {
114
+ expect(error).toBeInstanceOf(InvalidEntityReferenceException_1.InvalidEntityReferenceException);
115
+ (0, common_test_1.safeExpect)(error.message).toEqual('x should exist...');
116
+ (0, common_test_1.safeExpect)(error.additionalData).toMatchObject({
117
+ entityType: EntityType_1.EntityType.WORKFLOW_ENTITY,
118
+ id: 'abc-123',
119
+ });
120
+ }
121
+ });
122
+ it('should not throw and should type narrow if value is defined', () => {
123
+ const x = { id: 'abc' };
124
+ (0, assertType_1.assertType)();
125
+ AssertionUtils_1.AssertionUtils.assertValidEntityReference(x, EntityType_1.EntityType.COMPONENT);
126
+ (0, assertType_1.assertType)();
127
+ });
128
+ });
129
+ });
130
+ //# sourceMappingURL=AssertionUtilsTest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssertionUtilsTest.js","sourceRoot":"","sources":["../../src/test/AssertionUtilsTest.ts"],"names":[],"mappings":"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"}
package/jest.config.js CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  module.exports = {
2
3
  preset: 'ts-jest',
3
4
  testEnvironment: 'node',
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@coast/core-utils",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "author": "Coast Engineering",
5
5
  "license": "MIT",
6
6
  "dependencies": {
7
+ "@coast/core-types": "0.0.16",
8
+ "@coast/service-common": "^2.0.65",
7
9
  "lodash": "^4.17.21"
8
10
  },
9
11
  "scripts": {
@@ -20,6 +22,7 @@
20
22
  "strict:count": "echo \"$(grep -l \"ts-strict-ignore\" **/*.ts | wc -l) non-strict files\""
21
23
  },
22
24
  "devDependencies": {
25
+ "@paradoxical-io/common-test": "^2.7.0",
23
26
  "@types/lodash": "^4.17.7",
24
27
  "cross-env": "^7.0.3",
25
28
  "jest": "^29.7.0",
@@ -0,0 +1,62 @@
1
+ import { CoastException } from '@coast/core-types/exception/CoastException';
2
+ import _ from 'lodash';
3
+
4
+ import { NonEmptyArray } from './NonEmptyArray';
5
+
6
+ /**
7
+ * Determine the first element type of an array. If the array is a regular array type the element type is nullable when acting on
8
+ * indexing/first. If the array is a non-empty array type the element type is not nullable for the first element.
9
+ *
10
+ * This allows for safe indexing of the first element of a non-empty array type without needing to check for null or undefined.
11
+ */
12
+ type FirstElement<ARR> = ARR extends NonEmptyArray<infer U> ? U : ARR extends Array<infer U> ? U | null | undefined : never;
13
+
14
+ export class ArrayUtils {
15
+ /**
16
+ * Lift an array into a non-empty array. Checking ahead of time needs to be done to ensure this is valid as this puts
17
+ * the responsibility onto a user of knowing that the array is non-empty.
18
+ *
19
+ * If an empty array is attempted to be lifted this call will throw an error.
20
+ */
21
+ public static liftNonEmpty<T>(data: T[]): NonEmptyArray<T> {
22
+ if (ArrayUtils.isNonEmptyArray(data)) {
23
+ return data;
24
+ }
25
+
26
+ throw new CoastException('Cannot lift empty array');
27
+ }
28
+
29
+ public static first<T, Y extends T[]>(data: Y | null | undefined): FirstElement<Y> {
30
+ if (ArrayUtils.isNonEmptyArray(data)) {
31
+ return data[0] as FirstElement<Y>;
32
+ }
33
+
34
+ return _.first(data) as FirstElement<Y>;
35
+ }
36
+
37
+ public static isNonEmptyArray<T>(data: T[] | null | undefined): data is NonEmptyArray<T> {
38
+ if (_.isNil(data)) {
39
+ return false;
40
+ }
41
+
42
+ return data.length > 0;
43
+ }
44
+
45
+ public static isUniformArray<E>(value: unknown, itemGuard?: (item: unknown) => item is E): value is E[] {
46
+ if (!_.isArray(value)) {
47
+ return false;
48
+ }
49
+
50
+ if (value.length === 0) {
51
+ return true;
52
+ }
53
+
54
+ if (itemGuard !== undefined) {
55
+ return value.every((item: unknown) => itemGuard(item));
56
+ }
57
+
58
+ const valueTypes = new Set(value.map((item: unknown) => typeof item));
59
+
60
+ return valueTypes.size === 1;
61
+ }
62
+ }
@@ -0,0 +1,54 @@
1
+ import { EntityType } from '@coast/core-types/common/EntityType';
2
+ import { GeneralErrorCode } from '@coast/core-types/error/GeneralErrorCode';
3
+ import { AssertionFailedException } from '@coast/core-types/exception/AssertionFailedException';
4
+ import { CoastException } from '@coast/core-types/exception/CoastException';
5
+ import { InvalidEntityReferenceException } from '@coast/core-types/exception/InvalidEntityReferenceException';
6
+ import { NotDefinedException } from '@coast/core-types/exception/NotDefinedException';
7
+ import { DeepLogObject } from '@coast/service-common/logger/DeepLogObject';
8
+ import _ from 'lodash';
9
+ import nodeAssert from 'node:assert';
10
+
11
+ export class AssertionUtils {
12
+ static assertIsDefined<T>(x: T | null | undefined, error?: CoastException | string): asserts x is T {
13
+ if (_.isNil(x)) {
14
+ if (error instanceof CoastException) {
15
+ throw error;
16
+ }
17
+ throw new NotDefinedException(error);
18
+ }
19
+ }
20
+
21
+ static assertValidEntityReference<T extends object>(
22
+ entity: T | null | undefined,
23
+ entityType: EntityType,
24
+ options: { id?: string; message?: string } = {}
25
+ ): asserts entity is T {
26
+ AssertionUtils.assertIsDefined(
27
+ entity,
28
+ new InvalidEntityReferenceException({
29
+ entityType,
30
+ id: options?.id,
31
+ message: options?.message,
32
+ })
33
+ );
34
+ }
35
+
36
+ static assert(value: unknown, error?: CoastException | string): asserts value {
37
+ try {
38
+ nodeAssert(value);
39
+ } catch {
40
+ if (error instanceof CoastException) {
41
+ throw error;
42
+ }
43
+ throw new AssertionFailedException(error);
44
+ }
45
+ }
46
+
47
+ static assertUnreachable(x: never): never {
48
+ throw new CoastException({
49
+ message: 'Unexpected unreachable value',
50
+ code: GeneralErrorCode.INTERNAL_ERROR,
51
+ additionalData: DeepLogObject(x),
52
+ });
53
+ }
54
+ }