@naturalcycles/js-lib 14.96.1 → 14.98.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.
@@ -0,0 +1,104 @@
1
+ import { UnixTimestampNumber } from '../types'
2
+ import { Inclusiveness } from './localDate'
3
+ import { LocalTime, LocalTimeConfig } from './localTime'
4
+
5
+ export type TimeIntervalConfig = TimeInterval | TimeIntervalString
6
+ export type TimeIntervalString = string
7
+
8
+ /**
9
+ * Class that supports an "interval of time" between 2 timestamps - start and end.
10
+ * Example: `1649267185/1649267187`.
11
+ *
12
+ * @experimental
13
+ */
14
+ export class TimeInterval {
15
+ private constructor(private $start: UnixTimestampNumber, private $end: UnixTimestampNumber) {}
16
+
17
+ static of(start: LocalTimeConfig, end: LocalTimeConfig): TimeInterval {
18
+ return new TimeInterval(
19
+ LocalTime.parseToUnixTimestamp(start),
20
+ LocalTime.parseToUnixTimestamp(end),
21
+ )
22
+ }
23
+
24
+ get start(): UnixTimestampNumber {
25
+ return this.$start
26
+ }
27
+
28
+ get end(): UnixTimestampNumber {
29
+ return this.$end
30
+ }
31
+
32
+ get startTime(): LocalTime {
33
+ return LocalTime.of(this.$start)
34
+ }
35
+
36
+ get endTime(): LocalTime {
37
+ return LocalTime.of(this.$end)
38
+ }
39
+
40
+ /**
41
+ * Parses string like `1649267185/1649267187` into a TimeInterval.
42
+ */
43
+ static parse(d: TimeIntervalConfig): TimeInterval {
44
+ if (d instanceof TimeInterval) return d
45
+
46
+ const [start, end] = d.split('/').map(Number)
47
+
48
+ if (!end || !start) {
49
+ throw new Error(`Cannot parse "${d}" into TimeInterval`)
50
+ }
51
+
52
+ return new TimeInterval(start, end)
53
+ }
54
+
55
+ isSame(d: TimeIntervalConfig): boolean {
56
+ return this.cmp(d) === 0
57
+ }
58
+
59
+ isBefore(d: TimeIntervalConfig, inclusive = false): boolean {
60
+ const r = this.cmp(d)
61
+ return r === -1 || (r === 0 && inclusive)
62
+ }
63
+
64
+ isSameOrBefore(d: TimeIntervalConfig): boolean {
65
+ return this.cmp(d) <= 0
66
+ }
67
+
68
+ isAfter(d: TimeIntervalConfig, inclusive = false): boolean {
69
+ const r = this.cmp(d)
70
+ return r === 1 || (r === 0 && inclusive)
71
+ }
72
+
73
+ isSameOrAfter(d: TimeIntervalConfig): boolean {
74
+ return this.cmp(d) >= 0
75
+ }
76
+
77
+ includes(d: LocalTimeConfig, incl: Inclusiveness = '[)'): boolean {
78
+ d = LocalTime.parseToUnixTimestamp(d)
79
+ if (d < this.$start || (d === this.$start && incl[0] === '(')) return false
80
+ if (d > this.$end || (d === this.$end && incl[1] === ')')) return false
81
+ return true
82
+ }
83
+
84
+ /**
85
+ * TimeIntervals compare by start date.
86
+ * If it's the same - then by end date.
87
+ */
88
+ cmp(d: TimeIntervalConfig): -1 | 0 | 1 {
89
+ d = TimeInterval.parse(d)
90
+ if (this.$start > d.$start) return 1
91
+ if (this.$start < d.$start) return -1
92
+ if (this.$end > d.$end) return 1
93
+ if (this.$end < d.$end) return -1
94
+ return 0
95
+ }
96
+
97
+ toString(): TimeIntervalString {
98
+ return [this.$start, this.$end].join('/')
99
+ }
100
+
101
+ toJSON(): TimeIntervalString {
102
+ return this.toString()
103
+ }
104
+ }
package/src/index.ts CHANGED
@@ -105,7 +105,8 @@ import {
105
105
  BatchResult,
106
106
  InstanceId,
107
107
  IsoDate,
108
- IsoDateTime,
108
+ IsoDateString,
109
+ IsoDateTimeString,
109
110
  KeyValueTuple,
110
111
  Mapper,
111
112
  ObjectMapper,
@@ -117,6 +118,7 @@ import {
117
118
  Reviver,
118
119
  SavedDBEntity,
119
120
  StringMap,
121
+ UnixTimestampNumber,
120
122
  UnixTimestamp,
121
123
  Integer,
122
124
  ValueOf,
@@ -158,13 +160,17 @@ export * from './string/leven'
158
160
  export * from './datetime/localDate'
159
161
  export * from './datetime/localTime'
160
162
  export * from './datetime/dateInterval'
163
+ export * from './datetime/timeInterval'
161
164
  import { LocalDateConfig, LocalDateUnit, Inclusiveness } from './datetime/localDate'
162
165
  import { LocalTimeConfig, LocalTimeUnit, LocalTimeComponents } from './datetime/localTime'
163
166
  import { DateIntervalConfig, DateIntervalString } from './datetime/dateInterval'
167
+ import { TimeIntervalConfig, TimeIntervalString } from './datetime/timeInterval'
164
168
 
165
169
  export type {
166
170
  DateIntervalConfig,
167
171
  DateIntervalString,
172
+ TimeIntervalConfig,
173
+ TimeIntervalString,
168
174
  LocalDateConfig,
169
175
  LocalDateUnit,
170
176
  Inclusiveness,
@@ -197,7 +203,8 @@ export type {
197
203
  ObjectPredicate,
198
204
  InstanceId,
199
205
  IsoDate,
200
- IsoDateTime,
206
+ IsoDateString,
207
+ IsoDateTimeString,
201
208
  Reviver,
202
209
  PMapOptions,
203
210
  Mapper,
@@ -218,6 +225,7 @@ export type {
218
225
  ConditionalPick,
219
226
  ConditionalExcept,
220
227
  Class,
228
+ UnixTimestampNumber,
221
229
  UnixTimestamp,
222
230
  Integer,
223
231
  BaseDBEntity,
@@ -365,7 +365,9 @@ export class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyB
365
365
  return this
366
366
  }
367
367
 
368
- baseDBEntity<ID = string>(idType = 'string'): JsonSchemaObjectBuilder<T & BaseDBEntity<ID>> {
368
+ baseDBEntity<ID extends string | number = string>(
369
+ idType = 'string',
370
+ ): JsonSchemaObjectBuilder<T & BaseDBEntity<ID>> {
369
371
  Object.assign(this.schema.properties, {
370
372
  id: { type: idType },
371
373
  created: { type: 'number', format: 'unixTimestamp' },
@@ -375,7 +377,9 @@ export class JsonSchemaObjectBuilder<T extends AnyObject> extends JsonSchemaAnyB
375
377
  return this
376
378
  }
377
379
 
378
- savedDBEntity<ID = string>(idType = 'string'): JsonSchemaObjectBuilder<T & SavedDBEntity<ID>> {
380
+ savedDBEntity<ID extends string | number = string>(
381
+ idType = 'string',
382
+ ): JsonSchemaObjectBuilder<T & SavedDBEntity<ID>> {
379
383
  return this.baseDBEntity(idType).addRequired(['id', 'created', 'updated']) as any
380
384
  }
381
385
 
@@ -12,6 +12,13 @@ export function _average(values: number[]): number {
12
12
  return values.reduce((a, b) => a + b) / values.length
13
13
  }
14
14
 
15
+ /**
16
+ * Same as _average, but safely returns null if input array is empty or nullish.
17
+ */
18
+ export function _averageOrNull(values: number[] | undefined | null): number | null {
19
+ return values?.length ? values.reduce((a, b) => a + b) / values.length : null
20
+ }
21
+
15
22
  /**
16
23
  * valuesArray and weightsArray length is expected to be the same.
17
24
  */
package/src/math/sma.ts CHANGED
@@ -15,6 +15,10 @@ export class SimpleMovingAverage {
15
15
  */
16
16
  avg = 0
17
17
 
18
+ /**
19
+ * Push new value.
20
+ * Returns newly calculated average (using newly pushed value).
21
+ */
18
22
  push(n: number): number {
19
23
  this.data[this.nextIndex] = n
20
24
  this.nextIndex =
package/src/types.ts CHANGED
@@ -6,7 +6,7 @@ import { Merge, Promisable } from './typeFest'
6
6
  * Alternative: Record<string, T | undefined>
7
7
  */
8
8
  export interface StringMap<T = string> {
9
- [k: string]: T | undefined
9
+ [k: string | number]: T | undefined
10
10
  }
11
11
 
12
12
  /**
@@ -29,15 +29,17 @@ export interface CreatedUpdated {
29
29
  updated: number
30
30
  }
31
31
 
32
- export interface CreatedUpdatedId<ID = string> extends CreatedUpdated {
32
+ export interface CreatedUpdatedId<ID extends string | number = string> extends CreatedUpdated {
33
33
  id: ID
34
34
  }
35
35
 
36
- export interface ObjectWithId<ID = string> {
36
+ export interface ObjectWithId<ID extends string | number = string> {
37
37
  id: ID
38
38
  }
39
39
 
40
- export interface AnyObjectWithId<ID = string> extends AnyObject, ObjectWithId<ID> {}
40
+ export interface AnyObjectWithId<ID extends string | number = string>
41
+ extends AnyObject,
42
+ ObjectWithId<ID> {}
41
43
 
42
44
  /**
43
45
  * Convenience type shorthand.
@@ -150,6 +152,11 @@ export interface InstanceId {
150
152
  *
151
153
  * @example '2019-06-21'
152
154
  */
155
+ export type IsoDateString = string
156
+
157
+ /**
158
+ * @deprecated use IsoDateString
159
+ */
153
160
  export type IsoDate = string
154
161
 
155
162
  /**
@@ -157,13 +164,18 @@ export type IsoDate = string
157
164
  *
158
165
  * @example '2019-06-21T05:21:73Z'
159
166
  */
160
- export type IsoDateTime = string
167
+ export type IsoDateTimeString = string
161
168
 
162
169
  /**
163
170
  * Interface explicitly states that the value is a Unix timestamp (in seconds).
164
171
  *
165
172
  * @example 1628945450
166
173
  */
174
+ export type UnixTimestampNumber = number
175
+
176
+ /**
177
+ * @deprecated use UnixTimestampNumber
178
+ */
167
179
  export type UnixTimestamp = number
168
180
 
169
181
  /**
@@ -174,18 +186,18 @@ export type Integer = number
174
186
  /**
175
187
  * Base interface for any Entity that was saved to DB.
176
188
  */
177
- export interface SavedDBEntity<ID = string> {
189
+ export interface SavedDBEntity<ID extends string | number = string> {
178
190
  id: ID
179
191
 
180
192
  /**
181
193
  * unixTimestamp of when the entity was first created (in the DB).
182
194
  */
183
- created: UnixTimestamp
195
+ created: UnixTimestampNumber
184
196
 
185
197
  /**
186
198
  * unixTimestamp of when the entity was last updated (in the DB).
187
199
  */
188
- updated: UnixTimestamp
200
+ updated: UnixTimestampNumber
189
201
  }
190
202
 
191
203
  /**
@@ -194,10 +206,10 @@ export interface SavedDBEntity<ID = string> {
194
206
  * hence `id`, `created` and `updated` fields CAN BE undefined (yet).
195
207
  * When it's known to be saved - `SavedDBEntity` interface can be used instead.
196
208
  */
197
- export type BaseDBEntity<ID = string> = Partial<SavedDBEntity<ID>>
209
+ export type BaseDBEntity<ID extends string | number = string> = Partial<SavedDBEntity<ID>>
198
210
 
199
- export type Saved<E, ID = string> = Merge<E, SavedDBEntity<ID>>
200
- export type Unsaved<E, ID = string> = Merge<E, BaseDBEntity<ID>>
211
+ export type Saved<E, ID extends string | number = string> = Merge<E, SavedDBEntity<ID>>
212
+ export type Unsaved<E, ID extends string | number = string> = Merge<E, BaseDBEntity<ID>>
201
213
 
202
214
  /**
203
215
  * Named type for JSON.parse / JSON.stringify second argument