@axi-engine/utils 0.1.3 → 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/README.md CHANGED
@@ -30,7 +30,7 @@ const isSame = haveSameElements(['a', 'b'], ['b', 'a']); // Returns true
30
30
  ```
31
31
 
32
32
 
33
- API Reference
33
+ ## API Reference
34
34
 
35
35
  Will be available when code and repository will be fully published
36
36
 
package/dist/index.d.mts CHANGED
@@ -83,8 +83,32 @@ declare function getRandomElement<T>(array: T[]): T | undefined;
83
83
  * Throws an error if the condition is true.
84
84
  * @param conditionForThrow - If true, an error will be thrown.
85
85
  * @param exceptionMessage - The message for the error.
86
+ * @throws {Error} if the value is true
86
87
  */
87
88
  declare function throwIf(conditionForThrow: boolean, exceptionMessage: string): void | never;
89
+ /**
90
+ * Throws an error if the value is null, undefined, or an empty array.
91
+ *
92
+ * @template T The type of the value being checked.
93
+ * @param value The value to check.
94
+ * @param exceptionMessage The message for the error.
95
+ * @throws {Error} if the value is null, undefined, or an empty array.
96
+ *
97
+ * @example
98
+ * // Example with a potentially undefined variable
99
+ * const user: { name: string } | undefined = findUser();
100
+ * throwIfEmpty(user, 'User not found');
101
+ * // From here, TypeScript knows `user` is not undefined.
102
+ * console.log(user.name);
103
+ *
104
+ * @example
105
+ * // Example with an array
106
+ * const items: string[] = getItems();
107
+ * throwIfEmpty(items, 'Items array cannot be empty');
108
+ * // From here, you can safely access items[0] without checking for an empty array again.
109
+ * console.log('First item:', items[0]);
110
+ */
111
+ declare function throwIfEmpty<T>(value: T, exceptionMessage: string): asserts value is NonNullable<T>;
88
112
 
89
113
  interface AxiEngineConfig {
90
114
  pathSeparator: string;
@@ -96,6 +120,37 @@ declare const axiSettings: AxiEngineConfig;
96
120
  */
97
121
  declare function configure(newConfig: Partial<AxiEngineConfig>): void;
98
122
 
123
+ /**
124
+ * A minimal, type-safe event emitter for a single event.
125
+ * It does not manage state, it only manages subscribers and event dispatching.
126
+ * @template T A tuple representing the types of the event arguments.
127
+ */
128
+ declare class Emitter<T extends any[]> {
129
+ private listeners;
130
+ /**
131
+ * Subscribes a listener to this event.
132
+ * @returns A function to unsubscribe the listener.
133
+ */
134
+ subscribe(listener: (...args: T) => void): () => void;
135
+ /**
136
+ * Manually unsubscribe by listener
137
+ * @returns returns true if an listener has been removed, or false if the listener does not exist.
138
+ */
139
+ unsubscribe(listener: (...args: T) => void): boolean;
140
+ /**
141
+ * Dispatches the event to all subscribed listeners.
142
+ */
143
+ emit(...args: T): void;
144
+ /**
145
+ * Clears all listeners.
146
+ */
147
+ clear(): void;
148
+ /**
149
+ * Returns the number of listeners.
150
+ */
151
+ get listenerCount(): number;
152
+ }
153
+
99
154
  declare function isNullOrUndefined(val: unknown): val is null | undefined;
100
155
  declare function isUndefined(val: unknown): val is undefined;
101
156
  declare function isNumber(val: unknown): val is number;
@@ -155,4 +210,4 @@ declare function randInt(min: number, max: number): number;
155
210
  */
156
211
  declare function randId(): string;
157
212
 
158
- export { type AxiEngineConfig, type PathType, areArraysEqual, axiSettings, clampNumber, configure, ensurePathArray, ensurePathString, firstKeyOf, genArray, getPercentOf, getRandomElement, haveSameElements, isBoolean, isNullOrUndefined, isNumber, isPercentageString, isSequentialStart, isString, isUndefined, last, randId, randInt, shuffleArray, throwIf, unique };
213
+ export { type AxiEngineConfig, Emitter, type PathType, areArraysEqual, axiSettings, clampNumber, configure, ensurePathArray, ensurePathString, firstKeyOf, genArray, getPercentOf, getRandomElement, haveSameElements, isBoolean, isNullOrUndefined, isNumber, isPercentageString, isSequentialStart, isString, isUndefined, last, randId, randInt, shuffleArray, throwIf, throwIfEmpty, unique };
package/dist/index.d.ts CHANGED
@@ -83,8 +83,32 @@ declare function getRandomElement<T>(array: T[]): T | undefined;
83
83
  * Throws an error if the condition is true.
84
84
  * @param conditionForThrow - If true, an error will be thrown.
85
85
  * @param exceptionMessage - The message for the error.
86
+ * @throws {Error} if the value is true
86
87
  */
87
88
  declare function throwIf(conditionForThrow: boolean, exceptionMessage: string): void | never;
89
+ /**
90
+ * Throws an error if the value is null, undefined, or an empty array.
91
+ *
92
+ * @template T The type of the value being checked.
93
+ * @param value The value to check.
94
+ * @param exceptionMessage The message for the error.
95
+ * @throws {Error} if the value is null, undefined, or an empty array.
96
+ *
97
+ * @example
98
+ * // Example with a potentially undefined variable
99
+ * const user: { name: string } | undefined = findUser();
100
+ * throwIfEmpty(user, 'User not found');
101
+ * // From here, TypeScript knows `user` is not undefined.
102
+ * console.log(user.name);
103
+ *
104
+ * @example
105
+ * // Example with an array
106
+ * const items: string[] = getItems();
107
+ * throwIfEmpty(items, 'Items array cannot be empty');
108
+ * // From here, you can safely access items[0] without checking for an empty array again.
109
+ * console.log('First item:', items[0]);
110
+ */
111
+ declare function throwIfEmpty<T>(value: T, exceptionMessage: string): asserts value is NonNullable<T>;
88
112
 
89
113
  interface AxiEngineConfig {
90
114
  pathSeparator: string;
@@ -96,6 +120,37 @@ declare const axiSettings: AxiEngineConfig;
96
120
  */
97
121
  declare function configure(newConfig: Partial<AxiEngineConfig>): void;
98
122
 
123
+ /**
124
+ * A minimal, type-safe event emitter for a single event.
125
+ * It does not manage state, it only manages subscribers and event dispatching.
126
+ * @template T A tuple representing the types of the event arguments.
127
+ */
128
+ declare class Emitter<T extends any[]> {
129
+ private listeners;
130
+ /**
131
+ * Subscribes a listener to this event.
132
+ * @returns A function to unsubscribe the listener.
133
+ */
134
+ subscribe(listener: (...args: T) => void): () => void;
135
+ /**
136
+ * Manually unsubscribe by listener
137
+ * @returns returns true if an listener has been removed, or false if the listener does not exist.
138
+ */
139
+ unsubscribe(listener: (...args: T) => void): boolean;
140
+ /**
141
+ * Dispatches the event to all subscribed listeners.
142
+ */
143
+ emit(...args: T): void;
144
+ /**
145
+ * Clears all listeners.
146
+ */
147
+ clear(): void;
148
+ /**
149
+ * Returns the number of listeners.
150
+ */
151
+ get listenerCount(): number;
152
+ }
153
+
99
154
  declare function isNullOrUndefined(val: unknown): val is null | undefined;
100
155
  declare function isUndefined(val: unknown): val is undefined;
101
156
  declare function isNumber(val: unknown): val is number;
@@ -155,4 +210,4 @@ declare function randInt(min: number, max: number): number;
155
210
  */
156
211
  declare function randId(): string;
157
212
 
158
- export { type AxiEngineConfig, type PathType, areArraysEqual, axiSettings, clampNumber, configure, ensurePathArray, ensurePathString, firstKeyOf, genArray, getPercentOf, getRandomElement, haveSameElements, isBoolean, isNullOrUndefined, isNumber, isPercentageString, isSequentialStart, isString, isUndefined, last, randId, randInt, shuffleArray, throwIf, unique };
213
+ export { type AxiEngineConfig, Emitter, type PathType, areArraysEqual, axiSettings, clampNumber, configure, ensurePathArray, ensurePathString, firstKeyOf, genArray, getPercentOf, getRandomElement, haveSameElements, isBoolean, isNullOrUndefined, isNumber, isPercentageString, isSequentialStart, isString, isUndefined, last, randId, randInt, shuffleArray, throwIf, throwIfEmpty, unique };
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ Emitter: () => Emitter,
23
24
  areArraysEqual: () => areArraysEqual,
24
25
  axiSettings: () => axiSettings,
25
26
  clampNumber: () => clampNumber,
@@ -43,6 +44,7 @@ __export(index_exports, {
43
44
  randInt: () => randInt,
44
45
  shuffleArray: () => shuffleArray,
45
46
  throwIf: () => throwIf,
47
+ throwIfEmpty: () => throwIfEmpty,
46
48
  unique: () => unique
47
49
  });
48
50
  module.exports = __toCommonJS(index_exports);
@@ -93,22 +95,6 @@ function getRandomElement(array) {
93
95
  return array[index];
94
96
  }
95
97
 
96
- // src/assertion.ts
97
- function throwIf(conditionForThrow, exceptionMessage) {
98
- if (conditionForThrow) {
99
- throw new Error(exceptionMessage);
100
- }
101
- }
102
-
103
- // src/config.ts
104
- var defaultConfig = {
105
- pathSeparator: "/"
106
- };
107
- var axiSettings = { ...defaultConfig };
108
- function configure(newConfig) {
109
- Object.assign(axiSettings, newConfig);
110
- }
111
-
112
98
  // src/guards.ts
113
99
  function isNullOrUndefined(val) {
114
100
  return val === void 0 || val === null;
@@ -129,6 +115,68 @@ function isPercentageString(val) {
129
115
  return typeof val === "string" && val.endsWith("%");
130
116
  }
131
117
 
118
+ // src/assertion.ts
119
+ function throwIf(conditionForThrow, exceptionMessage) {
120
+ if (conditionForThrow) {
121
+ throw new Error(exceptionMessage);
122
+ }
123
+ }
124
+ function throwIfEmpty(value, exceptionMessage) {
125
+ const isArrayAndEmpty = Array.isArray(value) && value.length === 0;
126
+ if (isNullOrUndefined(value) || isArrayAndEmpty) {
127
+ throw new Error(exceptionMessage);
128
+ }
129
+ }
130
+
131
+ // src/config.ts
132
+ var defaultConfig = {
133
+ pathSeparator: "/"
134
+ };
135
+ var axiSettings = { ...defaultConfig };
136
+ function configure(newConfig) {
137
+ Object.assign(axiSettings, newConfig);
138
+ }
139
+
140
+ // src/emitter.ts
141
+ var Emitter = class {
142
+ constructor() {
143
+ this.listeners = /* @__PURE__ */ new Set();
144
+ }
145
+ /**
146
+ * Subscribes a listener to this event.
147
+ * @returns A function to unsubscribe the listener.
148
+ */
149
+ subscribe(listener) {
150
+ this.listeners.add(listener);
151
+ return () => this.listeners.delete(listener);
152
+ }
153
+ /**
154
+ * Manually unsubscribe by listener
155
+ * @returns returns true if an listener has been removed, or false if the listener does not exist.
156
+ */
157
+ unsubscribe(listener) {
158
+ return this.listeners.delete(listener);
159
+ }
160
+ /**
161
+ * Dispatches the event to all subscribed listeners.
162
+ */
163
+ emit(...args) {
164
+ this.listeners.forEach((listener) => listener(...args));
165
+ }
166
+ /**
167
+ * Clears all listeners.
168
+ */
169
+ clear() {
170
+ this.listeners.clear();
171
+ }
172
+ /**
173
+ * Returns the number of listeners.
174
+ */
175
+ get listenerCount() {
176
+ return this.listeners.size;
177
+ }
178
+ };
179
+
132
180
  // src/math.ts
133
181
  function clampNumber(val, min, max) {
134
182
  if (!isNullOrUndefined(min)) val = Math.max(val, min);
@@ -164,6 +212,7 @@ function randId() {
164
212
  }
165
213
  // Annotate the CommonJS export names for ESM import in node:
166
214
  0 && (module.exports = {
215
+ Emitter,
167
216
  areArraysEqual,
168
217
  axiSettings,
169
218
  clampNumber,
@@ -187,5 +236,6 @@ function randId() {
187
236
  randInt,
188
237
  shuffleArray,
189
238
  throwIf,
239
+ throwIfEmpty,
190
240
  unique
191
241
  });
package/dist/index.mjs CHANGED
@@ -44,22 +44,6 @@ function getRandomElement(array) {
44
44
  return array[index];
45
45
  }
46
46
 
47
- // src/assertion.ts
48
- function throwIf(conditionForThrow, exceptionMessage) {
49
- if (conditionForThrow) {
50
- throw new Error(exceptionMessage);
51
- }
52
- }
53
-
54
- // src/config.ts
55
- var defaultConfig = {
56
- pathSeparator: "/"
57
- };
58
- var axiSettings = { ...defaultConfig };
59
- function configure(newConfig) {
60
- Object.assign(axiSettings, newConfig);
61
- }
62
-
63
47
  // src/guards.ts
64
48
  function isNullOrUndefined(val) {
65
49
  return val === void 0 || val === null;
@@ -80,6 +64,68 @@ function isPercentageString(val) {
80
64
  return typeof val === "string" && val.endsWith("%");
81
65
  }
82
66
 
67
+ // src/assertion.ts
68
+ function throwIf(conditionForThrow, exceptionMessage) {
69
+ if (conditionForThrow) {
70
+ throw new Error(exceptionMessage);
71
+ }
72
+ }
73
+ function throwIfEmpty(value, exceptionMessage) {
74
+ const isArrayAndEmpty = Array.isArray(value) && value.length === 0;
75
+ if (isNullOrUndefined(value) || isArrayAndEmpty) {
76
+ throw new Error(exceptionMessage);
77
+ }
78
+ }
79
+
80
+ // src/config.ts
81
+ var defaultConfig = {
82
+ pathSeparator: "/"
83
+ };
84
+ var axiSettings = { ...defaultConfig };
85
+ function configure(newConfig) {
86
+ Object.assign(axiSettings, newConfig);
87
+ }
88
+
89
+ // src/emitter.ts
90
+ var Emitter = class {
91
+ constructor() {
92
+ this.listeners = /* @__PURE__ */ new Set();
93
+ }
94
+ /**
95
+ * Subscribes a listener to this event.
96
+ * @returns A function to unsubscribe the listener.
97
+ */
98
+ subscribe(listener) {
99
+ this.listeners.add(listener);
100
+ return () => this.listeners.delete(listener);
101
+ }
102
+ /**
103
+ * Manually unsubscribe by listener
104
+ * @returns returns true if an listener has been removed, or false if the listener does not exist.
105
+ */
106
+ unsubscribe(listener) {
107
+ return this.listeners.delete(listener);
108
+ }
109
+ /**
110
+ * Dispatches the event to all subscribed listeners.
111
+ */
112
+ emit(...args) {
113
+ this.listeners.forEach((listener) => listener(...args));
114
+ }
115
+ /**
116
+ * Clears all listeners.
117
+ */
118
+ clear() {
119
+ this.listeners.clear();
120
+ }
121
+ /**
122
+ * Returns the number of listeners.
123
+ */
124
+ get listenerCount() {
125
+ return this.listeners.size;
126
+ }
127
+ };
128
+
83
129
  // src/math.ts
84
130
  function clampNumber(val, min, max) {
85
131
  if (!isNullOrUndefined(min)) val = Math.max(val, min);
@@ -114,6 +160,7 @@ function randId() {
114
160
  return uuidv4();
115
161
  }
116
162
  export {
163
+ Emitter,
117
164
  areArraysEqual,
118
165
  axiSettings,
119
166
  clampNumber,
@@ -137,5 +184,6 @@ export {
137
184
  randInt,
138
185
  shuffleArray,
139
186
  throwIf,
187
+ throwIfEmpty,
140
188
  unique
141
189
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axi-engine/utils",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Core utility library for Axi Engine, providing common functions for arrays, math, type guards, and more.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -9,14 +9,14 @@
9
9
  "gamedev",
10
10
  "utils"
11
11
  ],
12
+ "types": "./dist/index.d.ts",
12
13
  "main": "./dist/index.js",
13
14
  "module": "./dist/index.mjs",
14
- "types": "./dist/index.d.ts",
15
15
  "exports": {
16
16
  ".": {
17
+ "types": "./dist/index.d.ts",
17
18
  "import": "./dist/index.mjs",
18
- "require": "./dist/index.js",
19
- "types": "./dist/index.d.ts"
19
+ "require": "./dist/index.js"
20
20
  }
21
21
  },
22
22
  "scripts": {