@oscarpalmer/atoms 0.197.0 → 0.199.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.
@@ -10,14 +10,14 @@ type Parameters = {
10
10
  key?: unknown;
11
11
  value?: unknown;
12
12
  };
13
+ declare function createFindParameters(original: unknown[]): Parameters;
13
14
  declare function findValue(type: Exclude<FindValueType, 'item'>, array: unknown[], parameters: unknown[], reversed: boolean): number;
14
15
  declare function findValue(type: Exclude<FindValueType, 'index'>, array: unknown[], parameters: unknown[], reversed: boolean): unknown;
15
16
  declare function findAbsoluteValueOrDefault(array: unknown[], parameters: unknown[], defaultValue: unknown, useDefaultValue: boolean, reversed: boolean): unknown;
16
17
  declare function findValues(type: FindValuesType, array: unknown[], parameters: unknown[], mapper?: unknown): FindValuesResult;
17
- declare function getFindParameters(original: unknown[]): Parameters;
18
18
  declare const FIND_VALUE_INDEX = "index";
19
19
  declare const FIND_VALUE_ITEM = "item";
20
20
  declare const FIND_VALUES_ALL: FindValuesType;
21
21
  declare const FIND_VALUES_UNIQUE: FindValuesType;
22
22
  //#endregion
23
- export { FIND_VALUES_ALL, FIND_VALUES_UNIQUE, FIND_VALUE_INDEX, FIND_VALUE_ITEM, findAbsoluteValueOrDefault, findValue, findValues, getFindParameters };
23
+ export { FIND_VALUES_ALL, FIND_VALUES_UNIQUE, FIND_VALUE_INDEX, FIND_VALUE_ITEM, createFindParameters, findAbsoluteValueOrDefault, findValue, findValues };
@@ -1,9 +1,17 @@
1
1
  import { getArrayCallback, getArrayCallbacks } from "./callbacks.mjs";
2
2
  //#region src/internal/array/find.ts
3
+ function createFindParameters(original) {
4
+ const { length } = original;
5
+ return {
6
+ bool: length === 1 && typeof original[0] === "function" ? original[0] : void 0,
7
+ key: length === 2 ? original[0] : void 0,
8
+ value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
9
+ };
10
+ }
3
11
  function findValue(type, array, parameters, reversed) {
4
12
  const findIndex = type === FIND_VALUE_INDEX;
5
13
  if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
6
- const { bool, key, value } = getFindParameters(parameters);
14
+ const { bool, key, value } = createFindParameters(parameters);
7
15
  const callbacks = getArrayCallbacks(bool, key);
8
16
  if (callbacks?.bool == null && callbacks?.keyed == null) {
9
17
  if (findIndex) return reversed ? array.lastIndexOf(value) : array.indexOf(value);
@@ -38,7 +46,7 @@ function findValues(type, array, parameters, mapper) {
38
46
  };
39
47
  if (!Array.isArray(array) || array.length === 0) return result;
40
48
  const { length } = array;
41
- const { bool, key, value } = getFindParameters(parameters);
49
+ const { bool, key, value } = createFindParameters(parameters);
42
50
  const callbacks = getArrayCallbacks(bool, key);
43
51
  if (type === "unique" && callbacks?.keyed == null && length >= FIND_UNIQUE_THRESHOLD) {
44
52
  result.matched = [...new Set(array)];
@@ -65,18 +73,10 @@ function findValues(type, array, parameters, mapper) {
65
73
  }
66
74
  return result;
67
75
  }
68
- function getFindParameters(original) {
69
- const { length } = original;
70
- return {
71
- bool: length === 1 && typeof original[0] === "function" ? original[0] : void 0,
72
- key: length === 2 ? original[0] : void 0,
73
- value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
74
- };
75
- }
76
76
  const FIND_VALUE_INDEX = "index";
77
77
  const FIND_VALUE_ITEM = "item";
78
78
  const FIND_VALUES_ALL = "all";
79
79
  const FIND_VALUES_UNIQUE = "unique";
80
80
  const FIND_UNIQUE_THRESHOLD = 100;
81
81
  //#endregion
82
- export { FIND_VALUES_ALL, FIND_VALUES_UNIQUE, FIND_VALUE_INDEX, FIND_VALUE_ITEM, findAbsoluteValueOrDefault, findValue, findValues, getFindParameters };
82
+ export { FIND_VALUES_ALL, FIND_VALUES_UNIQUE, FIND_VALUE_INDEX, FIND_VALUE_ITEM, createFindParameters, findAbsoluteValueOrDefault, findValue, findValues };
@@ -1,12 +1,13 @@
1
1
  import { isPlainObject } from "../is.mjs";
2
2
  import { getString, join } from "../string/misc.mjs";
3
+ import { getNumberOrDefault } from "../defaults.mjs";
3
4
  import { SizedMap } from "../sized/map.mjs";
4
5
  //#region src/internal/function/memoize.ts
5
- function getMemoizationOptions(input) {
6
+ function createMemoizationOptions(input) {
6
7
  const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
7
8
  return {
8
9
  cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
9
- cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : MEMOIZED_CACHE_SIZE_DEFAULT
10
+ cacheSize: getNumberOrDefault(cacheSize, MEMOIZED_CACHE_SIZE_DEFAULT)
10
11
  };
11
12
  }
12
13
  /**
@@ -21,7 +22,7 @@ function memoize(callback, options) {
21
22
  const state = {
22
23
  cache: void 0,
23
24
  getter: void 0,
24
- options: getMemoizationOptions(options)
25
+ options: createMemoizationOptions(options)
25
26
  };
26
27
  state.cache = new SizedMap(state.options.cacheSize);
27
28
  state.getter = (...parameters) => {
@@ -1,3 +1,4 @@
1
+ import { getNumberOrDefault } from "../defaults.mjs";
1
2
  //#region src/internal/function/timer.ts
2
3
  function getAsyncTimer(type, callback, time) {
3
4
  function cancel() {
@@ -24,7 +25,7 @@ function getAsyncTimer(type, callback, time) {
24
25
  }
25
26
  } else id = startTimer(() => run(item));
26
27
  }
27
- const interval = getInterval(time);
28
+ const interval = getNumberOrDefault(time, 0);
28
29
  const throttle = type === TIMER_THROTTLE;
29
30
  let id;
30
31
  let last;
@@ -47,9 +48,6 @@ function getAsyncTimer(type, callback, time) {
47
48
  Object.defineProperty(timer, TIMER_CANCEL, { value: () => cancel() });
48
49
  return timer;
49
50
  }
50
- function getInterval(value) {
51
- return typeof value === "number" && value > 0 ? value : 0;
52
- }
53
51
  function getTimer(type, callback, time) {
54
52
  function cancel() {
55
53
  clearTimer(id);
@@ -62,7 +60,7 @@ function getTimer(type, callback, time) {
62
60
  callback(...args);
63
61
  } else id = startTimer(run);
64
62
  }
65
- const interval = getInterval(time);
63
+ const interval = getNumberOrDefault(time, 0);
66
64
  const throttle = type === TIMER_THROTTLE;
67
65
  let args;
68
66
  let id;
@@ -1,5 +1,5 @@
1
1
  import { isPlainObject } from "./is.mjs";
2
- import { createSubscriptions, isSubscription } from "./subscription.mjs";
2
+ import { SUBSCRIPTION_NAME, isSubscription, subscriptions } from "./subscription.mjs";
3
3
  //#region src/internal/herald.ts
4
4
  function createEvents(herald, state) {
5
5
  const events = {};
@@ -7,35 +7,35 @@ function createEvents(herald, state) {
7
7
  for (const key of state.keys) events[key] = (callback, signal) => herald.subscribe(key, callback, signal);
8
8
  return Object.freeze(events);
9
9
  }
10
- function emitForHerald(state, event, ...parameters) {
11
- const items = state.subscriptions.state.values.from.keyed?.get(event);
12
- if (items == null || items.size === 0) return;
13
- for (const [callback] of items) callback(...parameters);
14
- }
15
- function getHeraldSubscriptionProperty(input) {
16
- if (input == null) return heraldSubscription;
17
- const property = isPlainObject(input) ? input : {};
18
- if (typeof property.key !== "string" || property.value != null && typeof property.value !== "string") throw new Error(HERALD_MESSAGE_PROPERTY);
19
- return {
20
- key: property.key,
21
- value: property.value
22
- };
23
- }
24
- function getHeraldState(input) {
10
+ function createHeraldState(input) {
25
11
  const options = isPlainObject(input) ? input : {};
26
12
  if (!Array.isArray(options.names) || options.names.length === 0 || !options.names.every((name) => typeof name === "string")) throw new Error(HERALD_MESSAGE_ARRAY);
27
13
  if (options.onCreate != null && typeof options.onCreate !== "function") throw new Error(HERALD_MESSAGE_ONCREATE);
28
14
  const keys = new Set(options.names);
29
- const property = getHeraldSubscriptionProperty(options.property);
15
+ const property = createHeraldSubscriptionProperty(options.property);
30
16
  return {
31
17
  keys,
32
- subscriptions: createSubscriptions({
18
+ store: subscriptions({
33
19
  keys,
34
20
  property
35
21
  }),
36
22
  onCreate: options.onCreate
37
23
  };
38
24
  }
25
+ function createHeraldSubscriptionProperty(input) {
26
+ if (input == null) return heraldSubscription;
27
+ const property = isPlainObject(input) ? input : {};
28
+ if (typeof property.key !== "string" || property.value != null && typeof property.value !== "string") throw new Error(HERALD_MESSAGE_PROPERTY);
29
+ return {
30
+ key: property.key,
31
+ value: property.value
32
+ };
33
+ }
34
+ function emitForHerald(state, event, ...parameters) {
35
+ const items = state.store.values.from.keyed?.get(event);
36
+ if (items == null || items.size === 0) return;
37
+ for (const [callback] of items) callback(...parameters);
38
+ }
39
39
  /**
40
40
  * Create a _Herald_ for announcing named events
41
41
  *
@@ -44,11 +44,11 @@ function getHeraldState(input) {
44
44
  * @returns _Herald_ instance
45
45
  */
46
46
  function herald(options) {
47
- const state = getHeraldState(options);
47
+ const state = createHeraldState(options);
48
48
  const instance = {
49
- clear: () => state.subscriptions.clear(),
49
+ clear: () => state.store.clear(),
50
50
  emit: (event, ...parameters) => emitForHerald(state, event, ...parameters),
51
- observed: (event) => (state.subscriptions.state.items.keyed?.get(event)?.size ?? 0) > 0,
51
+ observed: (event) => (state.store.items.keyed?.get(event)?.size ?? 0) > 0,
52
52
  subscribe: (key, callback, signal) => subscribeToHerald(state, key, callback, signal)
53
53
  };
54
54
  Object.defineProperties(instance, {
@@ -91,7 +91,7 @@ function isHeraldSubscription(value) {
91
91
  return isSubscription(value) && value[HERALD_PROPERTY] === "subscription";
92
92
  }
93
93
  function subscribeToHerald(state, key, callback, signal) {
94
- const [subscription, existing] = state.subscriptions.create({
94
+ const [subscription, existing] = state.store.create({
95
95
  key,
96
96
  signal,
97
97
  value: callback
@@ -105,6 +105,9 @@ const HERALD_MESSAGE_ONCREATE = `Herald requires a valid onCreate callback for s
105
105
  const HERALD_MESSAGE_PROPERTY = `Herald requires valid property information for subscription identification`;
106
106
  const HERALD_NAME_EVENTS = "events";
107
107
  const HERALD_NAME_HERALD = "herald";
108
- const heraldSubscription = { key: HERALD_PROPERTY };
108
+ const heraldSubscription = {
109
+ key: HERALD_PROPERTY,
110
+ value: SUBSCRIPTION_NAME
111
+ };
109
112
  //#endregion
110
113
  export { herald, isHerald, isHeraldEvents, isHeraldSubscription };
@@ -10,10 +10,25 @@ type Subscription = {
10
10
  */
11
11
  unsubscribe(): void;
12
12
  };
13
+ /**
14
+ * Parameters for creating a subscription
15
+ */
13
16
  type SubscriptionParameters = {
17
+ /**
18
+ * Is the owner of the subscription alive? _(defaults to `true`)_
19
+ */
14
20
  isActive?: () => boolean;
21
+ /**
22
+ * Key used to identify a subscription _(defaults to `undefined`)_
23
+ */
15
24
  key?: unknown;
25
+ /**
26
+ * Signal used to abort the subscription _(defaults to `undefined`)_
27
+ */
16
28
  signal?: AbortSignal;
29
+ /**
30
+ * Value used to identify a subscription
31
+ */
17
32
  value: unknown;
18
33
  };
19
34
  /**
@@ -25,37 +40,64 @@ type SubscriptionProperty = {
25
40
  */
26
41
  key: string;
27
42
  /**
28
- * Value of the property used to identify a subscription _(defaults to `subscription`)_
43
+ * Value of the property used to identify a subscription
29
44
  */
30
- value?: unknown;
45
+ value: unknown;
31
46
  };
32
- type Subscriptions<Value = unknown> = {
33
- state: SubscriptionsState<Value>;
47
+ type Subscriptions = {
48
+ /**
49
+ * Items of the subscriptions store
50
+ *
51
+ * - `any` - Set of subscriptions _(for unkeyed subscriptions)_
52
+ * - `keyed` - Map of keys to sets of subscriptions _(for keyed subscriptions)_
53
+ */
54
+ readonly items: Readonly<SubscriptionsItems>;
55
+ /**
56
+ * Values of the subscriptions store
57
+ *
58
+ * - `from.any` - Map of values to subscriptions _(for unkeyed subscriptions)_
59
+ * - `from.keyed` - Map of keys to maps of values to subscriptions _(for keyed subscriptions)_
60
+ * - `to.any` - Map of subscriptions to values _(for unkeyed subscriptions)_
61
+ * - `to.keyed` - Map of keys to maps of subscriptions to values _(for keyed subscriptions)_
62
+ */
63
+ readonly values: Readonly<SubscriptionsValues>;
64
+ /**
65
+ * Clear all subscriptions
66
+ */
34
67
  clear: () => void;
68
+ /**
69
+ * Create _(or retrieve)_ a subscription
70
+ *
71
+ * @param parameters Subscription parameters
72
+ * @returns Tuple holding subsccription and existing boolean
73
+ */
35
74
  create: (parameters: SubscriptionParameters) => [Subscription, boolean];
36
75
  };
76
+ /**
77
+ * Parameters for creating a subscription store
78
+ */
37
79
  type SubscriptionsParameters = {
38
- keys?: Set<Key>;
39
- property: SubscriptionProperty;
40
- };
41
- type SubscriptionsState<Value = unknown> = {
42
- items: SubscriptionsItems;
43
- keys?: Set<Key>;
44
- values: SubscriptionsValues<Value>;
80
+ /**
81
+ * Allow any or specific keys for subscriptions? _(defaults to `false`, which prevents keyed subscriptions)_
82
+ */
83
+ keys?: boolean | Set<Key>;
84
+ /**
85
+ * Property information for subscription identification
86
+ */
87
+ property?: SubscriptionProperty;
45
88
  };
46
89
  type SubscriptionsItems = {
47
90
  any: Set<Subscription>;
48
91
  keyed?: Map<Key, Set<Subscription>>;
49
92
  };
50
- type SubscriptionsValues<Value = unknown> = {
51
- from: SubscriptionsValuesItem<Value, Subscription>;
52
- to: SubscriptionsValuesItem<Subscription, Value>;
93
+ type SubscriptionsValues = {
94
+ from: SubscriptionsValuesItem<unknown, Subscription>;
95
+ to: SubscriptionsValuesItem<Subscription, unknown>;
53
96
  };
54
97
  type SubscriptionsValuesItem<MapKey, MapValue> = {
55
98
  any: Map<MapKey, MapValue>;
56
99
  keyed?: Map<Key, Map<MapKey, MapValue>>;
57
100
  };
58
- declare function createSubscriptions<Value = unknown>(parameters: SubscriptionsParameters): Subscriptions<Value>;
59
101
  /**
60
102
  * Is the value a subscription?
61
103
  *
@@ -63,6 +105,20 @@ declare function createSubscriptions<Value = unknown>(parameters: SubscriptionsP
63
105
  * @returns `true` if the value is a subscription, otherwise `false`
64
106
  */
65
107
  declare function isSubscription(value: unknown): value is Subscription;
108
+ /**
109
+ * Is the value a subscriptions store?
110
+ *
111
+ * @param value Value to check
112
+ * @returns `true` if the value is a subscriptions store, otherwise `false`
113
+ */
114
+ declare function isSubscriptions(value: unknown): value is Subscriptions;
115
+ /**
116
+ * Create a subscription store
117
+ *
118
+ * @param parameters Store parameters
119
+ * @returns Subscription store
120
+ */
121
+ declare function subscriptions(parameters?: SubscriptionsParameters): Subscriptions;
66
122
  declare const SUBSCRIPTION_NAME = "subscription";
67
123
  //#endregion
68
- export { SUBSCRIPTION_NAME, Subscription, SubscriptionParameters, SubscriptionProperty, Subscriptions, createSubscriptions, isSubscription };
124
+ export { SUBSCRIPTION_NAME, Subscription, SubscriptionParameters, SubscriptionProperty, Subscriptions, SubscriptionsParameters, isSubscription, isSubscriptions, subscriptions };
@@ -2,8 +2,8 @@ import { isKey, isPlainObject } from "./is.mjs";
2
2
  import { createAborter } from "./abort.mjs";
3
3
  //#region src/internal/subscription.ts
4
4
  function addSubscription(subscriptions, subscription, state) {
5
+ const { items, values } = subscriptions;
5
6
  const { key, value } = state.parameters;
6
- const { items, values } = subscriptions.state;
7
7
  if (!isKey(key)) {
8
8
  items.any.add(subscription);
9
9
  values.from.any.set(value, subscription);
@@ -37,7 +37,8 @@ function clearSubscriptions(store) {
37
37
  for (const susbcription of store.values.to.any.keys()) susbcription.unsubscribe();
38
38
  if (store.values.to.keyed != null) for (const values of store.values.to.keyed.values()) for (const susbcription of values.keys()) susbcription.unsubscribe();
39
39
  }
40
- function createSubscription(subscriptions, property, parameters) {
40
+ function createSubscription(subscriptions, property, params) {
41
+ const parameters = createSubscriptionParameters(params);
41
42
  if (parameters.signal?.aborted ?? false) throw new Error(parameters.signal?.reason);
42
43
  const state = {
43
44
  parameters,
@@ -45,12 +46,15 @@ function createSubscription(subscriptions, property, parameters) {
45
46
  };
46
47
  const existing = getExistingSubscription(subscriptions, state);
47
48
  if (existing != null) return [existing, true];
48
- if (subscriptions.state.keys != null && isKey(parameters.key) && !subscriptions.state.keys.has(parameters.key)) throw new Error(SUBSCRIPTION_INVALID_KEY);
49
+ if (subscriptions.keys != null && isKey(parameters.key)) {
50
+ if (subscriptions.keys === false) throw new Error(SUBSCRIPTION_DISALLOWED_KEY);
51
+ else if (subscriptions.keys !== true && !subscriptions.keys.has(parameters.key)) throw new Error(SUBSCRIPTION_INVALID_KEY);
52
+ }
49
53
  state.aborter = createAborter(parameters.signal, () => unsubscribe(subscriptions, instance, state));
50
54
  const instance = { unsubscribe: () => unsubscribe(subscriptions, instance, state) };
51
55
  Object.defineProperties(instance, {
52
- [SUBSCRIPTION_PROPERTY]: { value: true },
53
- [property.key]: { value: property.value ?? "subscription" },
56
+ [SUBSCRIPTION_PROPERTY]: { value: SUBSCRIPTION_NAME },
57
+ [property.key]: { value: property.value },
54
58
  active: {
55
59
  enumerable: true,
56
60
  get: () => (parameters.isActive?.() ?? true) && state.active
@@ -59,36 +63,56 @@ function createSubscription(subscriptions, property, parameters) {
59
63
  addSubscription(subscriptions, instance, state);
60
64
  return [Object.freeze(instance), false];
61
65
  }
62
- function createSubscriptions(parameters) {
63
- const { keys, property } = parameters;
64
- const state = {
66
+ function getExistingSubscription(subscriptions, state) {
67
+ const { values } = subscriptions;
68
+ const { parameters } = state;
69
+ return isKey(parameters.key) ? values.from.keyed?.get(parameters.key)?.get(parameters.value) : values.from.any.get(parameters.value);
70
+ }
71
+ function createSubscriptionParameters(input) {
72
+ const values = isPlainObject(input) ? input : {};
73
+ if (values.value == null) throw new Error(SUBSCRIPTION_INVALID_VALUE);
74
+ return {
75
+ isActive: typeof values.isActive === "function" ? values.isActive : void 0,
76
+ key: isKey(values.key) ? values.key : void 0,
77
+ signal: values.signal instanceof AbortSignal ? values.signal : void 0,
78
+ value: values.value
79
+ };
80
+ }
81
+ function createSubscriptionsParameters(input) {
82
+ const values = isPlainObject(input) ? input : {};
83
+ let keys;
84
+ if (values.keys instanceof Set) keys = values.keys;
85
+ else keys = typeof values.keys === "boolean" ? values.keys : false;
86
+ return {
87
+ keys,
88
+ property: createSubscriptionsProperty(values.property)
89
+ };
90
+ }
91
+ function createSubscriptionsProperty(input) {
92
+ const values = isPlainObject(input) ? input : {};
93
+ return {
94
+ key: typeof values.key === "string" ? values.key : SUBSCRIPTION_PROPERTY,
95
+ value: values.value == null ? SUBSCRIPTION_NAME : values.value
96
+ };
97
+ }
98
+ function createSubscriptionsState(keys) {
99
+ return {
65
100
  keys,
66
101
  items: {
67
102
  any: /* @__PURE__ */ new Set(),
68
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
103
+ keyed: keys === false ? void 0 : /* @__PURE__ */ new Map()
69
104
  },
70
105
  values: {
71
106
  from: {
72
107
  any: /* @__PURE__ */ new Map(),
73
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
108
+ keyed: keys === false ? void 0 : /* @__PURE__ */ new Map()
74
109
  },
75
110
  to: {
76
111
  any: /* @__PURE__ */ new Map(),
77
- keyed: keys == null ? void 0 : /* @__PURE__ */ new Map()
112
+ keyed: keys === false ? void 0 : /* @__PURE__ */ new Map()
78
113
  }
79
114
  }
80
115
  };
81
- const instance = {
82
- state,
83
- clear: () => clearSubscriptions(state),
84
- create: (parameters) => createSubscription(instance, property, parameters)
85
- };
86
- return instance;
87
- }
88
- function getExistingSubscription(subscriptions, state) {
89
- const { parameters } = state;
90
- const { values } = subscriptions.state;
91
- return isKey(parameters.key) ? values.from.keyed?.get(parameters.key)?.get(parameters.value) : values.from.any.get(parameters.value);
92
116
  }
93
117
  /**
94
118
  * Is the value a subscription?
@@ -97,7 +121,19 @@ function getExistingSubscription(subscriptions, state) {
97
121
  * @returns `true` if the value is a subscription, otherwise `false`
98
122
  */
99
123
  function isSubscription(value) {
100
- return isPlainObject(value) && SUBSCRIPTION_PROPERTY in value && value[SUBSCRIPTION_PROPERTY] === true;
124
+ return isSubscriptionInstance(value, SUBSCRIPTION_NAME);
125
+ }
126
+ function isSubscriptionInstance(value, name) {
127
+ return isPlainObject(value) && SUBSCRIPTION_PROPERTY in value && value[SUBSCRIPTION_PROPERTY] === name;
128
+ }
129
+ /**
130
+ * Is the value a subscriptions store?
131
+ *
132
+ * @param value Value to check
133
+ * @returns `true` if the value is a subscriptions store, otherwise `false`
134
+ */
135
+ function isSubscriptions(value) {
136
+ return isSubscriptionInstance(value, SUBSCRIPTION_STORE);
101
137
  }
102
138
  function removeFromStore(items, values, subscription, value, key) {
103
139
  items.delete(subscription);
@@ -109,14 +145,14 @@ function removeFromStore(items, values, subscription, value, key) {
109
145
  values.to.keyed?.get(key)?.delete(subscription);
110
146
  }
111
147
  }
112
- function removeSubscription(subscriptions, subscription, state) {
148
+ function removeSubscription(subscriptionsState, subscription, state) {
113
149
  if (!state.active) return;
114
150
  state.aborter = void 0;
115
151
  state.active = false;
116
152
  state.parameters.isActive = void 0;
117
153
  state.parameters.signal = void 0;
154
+ const { items, values } = subscriptionsState;
118
155
  const { key, value } = state.parameters;
119
- const { items, values } = subscriptions.state;
120
156
  if (!isKey(key)) {
121
157
  removeFromStore(items.any, values, subscription, value);
122
158
  return;
@@ -129,12 +165,41 @@ function removeSubscription(subscriptions, subscription, state) {
129
165
  removeFromStore(keyed, values, subscription, value, key);
130
166
  if (keyed.size === 0) items.keyed.delete(key);
131
167
  }
132
- function unsubscribe(subscriptions, subscription, state) {
168
+ /**
169
+ * Create a subscription store
170
+ *
171
+ * @param parameters Store parameters
172
+ * @returns Subscription store
173
+ */
174
+ function subscriptions(parameters) {
175
+ const { keys, property } = createSubscriptionsParameters(parameters);
176
+ const state = createSubscriptionsState(keys);
177
+ const instance = {
178
+ clear: () => clearSubscriptions(state),
179
+ create: (parameters) => createSubscription(state, property, parameters)
180
+ };
181
+ Object.defineProperties(instance, {
182
+ [SUBSCRIPTION_PROPERTY]: { value: SUBSCRIPTION_STORE },
183
+ items: {
184
+ enumerable: true,
185
+ value: state.items
186
+ },
187
+ values: {
188
+ enumerable: true,
189
+ value: state.values
190
+ }
191
+ });
192
+ return Object.freeze(instance);
193
+ }
194
+ function unsubscribe(subscriptionsState, subscription, state) {
133
195
  state.aborter?.cancel();
134
- removeSubscription(subscriptions, subscription, state);
196
+ removeSubscription(subscriptionsState, subscription, state);
135
197
  }
198
+ const SUBSCRIPTION_DISALLOWED_KEY = "Disallowed key for subscription";
136
199
  const SUBSCRIPTION_INVALID_KEY = "Invalid key for subscription";
200
+ const SUBSCRIPTION_INVALID_VALUE = "A subscription requires a non-null value to identify it";
137
201
  const SUBSCRIPTION_NAME = "subscription";
138
- const SUBSCRIPTION_PROPERTY = "$subscription";
202
+ const SUBSCRIPTION_PROPERTY = "$subscriptions";
203
+ const SUBSCRIPTION_STORE = "subscriptions";
139
204
  //#endregion
140
- export { SUBSCRIPTION_NAME, createSubscriptions, isSubscription };
205
+ export { SUBSCRIPTION_NAME, isSubscription, isSubscriptions, subscriptions };
@@ -1,6 +1,6 @@
1
1
  import { max } from "../math/aggregate.mjs";
2
2
  import { getString, words } from "../string/misc.mjs";
3
- import { getCompareHandlers } from "./handlers.mjs";
3
+ import { createCompareHandlers } from "./handlers.mjs";
4
4
  //#region src/internal/value/compare.ts
5
5
  const COMPARE_NAME = "compare";
6
6
  /**
@@ -78,7 +78,7 @@ const comparators = {
78
78
  number: compareNumbers,
79
79
  symbol: compareSymbols
80
80
  };
81
- const compareHandlers = getCompareHandlers(compare, {
81
+ const compareHandlers = createCompareHandlers(compare, {
82
82
  callback: (first, second, compareStrings) => compareStrings ? getString(first).localeCompare(getString(second)) : void 0,
83
83
  method: COMPARE_NAME
84
84
  });
@@ -1,6 +1,32 @@
1
1
  import { isNonPlainObject, isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
2
- import { getCompareHandlers } from "./handlers.mjs";
2
+ import { createCompareHandlers } from "./handlers.mjs";
3
3
  //#region src/internal/value/equal.ts
4
+ function createEqualOptions(input) {
5
+ const options = {
6
+ ignoreCase: false,
7
+ ignoreExpressions: {
8
+ enabled: false,
9
+ values: []
10
+ },
11
+ ignoreKeys: {
12
+ enabled: false,
13
+ values: /* @__PURE__ */ new Set()
14
+ },
15
+ relaxedNullish: false
16
+ };
17
+ if (typeof input === "boolean") {
18
+ options.ignoreCase = input;
19
+ return options;
20
+ }
21
+ if (isNonPlainObject(input)) return options;
22
+ options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
23
+ options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
24
+ options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
25
+ options.ignoreExpressions.enabled = options.ignoreExpressions.values.length > 0;
26
+ options.ignoreKeys.enabled = options.ignoreKeys.values.size > 0;
27
+ options.relaxedNullish = input.relaxedNullish === true;
28
+ return options;
29
+ }
4
30
  /**
5
31
  * Deregister a equality comparison handler for a specific class
6
32
  *
@@ -18,9 +44,9 @@ function filterKey(key, options) {
18
44
  return true;
19
45
  }
20
46
  function equal(first, second, options) {
21
- return equalValue(first, second, getEqualOptions(options));
47
+ return equalValue(first, second, createEqualOptions(options));
22
48
  }
23
- equal.handlers = getCompareHandlers(equal, { callback: Object.is });
49
+ equal.handlers = createCompareHandlers(equal, { callback: Object.is });
24
50
  equal.deregister = deregisterEqualizer;
25
51
  equal.initialize = initializeEqualizer;
26
52
  equal.register = registerEqualizer;
@@ -115,32 +141,6 @@ function equalValue(first, second, options) {
115
141
  default: return equal.handlers.handle(first, second, options);
116
142
  }
117
143
  }
118
- function getEqualOptions(input) {
119
- const options = {
120
- ignoreCase: false,
121
- ignoreExpressions: {
122
- enabled: false,
123
- values: []
124
- },
125
- ignoreKeys: {
126
- enabled: false,
127
- values: /* @__PURE__ */ new Set()
128
- },
129
- relaxedNullish: false
130
- };
131
- if (typeof input === "boolean") {
132
- options.ignoreCase = input;
133
- return options;
134
- }
135
- if (isNonPlainObject(input)) return options;
136
- options.ignoreCase = typeof input.ignoreCase === "boolean" ? input.ignoreCase : false;
137
- options.ignoreExpressions.values = (Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => key instanceof RegExp);
138
- options.ignoreKeys.values = new Set((Array.isArray(input.ignoreKeys) ? input.ignoreKeys : [input.ignoreKeys]).filter((key) => typeof key === "string"));
139
- options.ignoreExpressions.enabled = options.ignoreExpressions.values.length > 0;
140
- options.ignoreKeys.enabled = options.ignoreKeys.values.size > 0;
141
- options.relaxedNullish = input.relaxedNullish === true;
142
- return options;
143
- }
144
144
  /**
145
145
  * Create an equalizer with predefined options
146
146
  *
@@ -150,7 +150,7 @@ function getEqualOptions(input) {
150
150
  * @returns Equalizer function
151
151
  */
152
152
  function initializeEqualizer(options) {
153
- const actual = getEqualOptions(options);
153
+ const actual = createEqualOptions(options);
154
154
  const equalizer = (first, second) => equalValue(first, second, actual);
155
155
  equalizer.deregister = deregisterEqualizer;
156
156
  equalizer.register = registerEqualizer;
@@ -4,15 +4,15 @@ type Options = {
4
4
  callback: GenericCallback;
5
5
  method?: string;
6
6
  };
7
- declare function getCompareHandlers<Value>(owner: GenericCallback, options: Options): {
7
+ declare function createCompareHandlers<Value>(owner: GenericCallback, options: Options): {
8
8
  deregister(constructor: Constructor): void;
9
9
  handle(first: unknown, second: unknown, ...parameters: unknown[]): Value;
10
10
  register(constructor: Constructor, handler?: string | GenericCallback): void;
11
11
  };
12
- declare function getSelfHandlers(owner: GenericCallback, options: Options): {
12
+ declare function createSelfHandlers(owner: GenericCallback, options: Options): {
13
13
  deregister(constructor: Constructor): void;
14
14
  handle(value: unknown, ...parameters: unknown[]): unknown;
15
15
  register(constructor: Constructor, handler?: string | GenericCallback): void;
16
16
  };
17
17
  //#endregion
18
- export { getCompareHandlers, getSelfHandlers };
18
+ export { createCompareHandlers, createSelfHandlers };