@zeniai/client-epic-state 5.1.45-betaDI2 → 5.1.45-betaDI3

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.
@@ -53,7 +53,14 @@ const mapTaskPayloadToTask = (payload, previousTask) => ({
53
53
  depth: payload.depth !== undefined
54
54
  ? (payload.depth ?? undefined)
55
55
  : previousTask?.depth,
56
- parentTaskId: payload.parent_task_id ?? undefined,
56
+ // `parent_task_id` may be absent on partial updates (e.g. pusher-driven
57
+ // task refreshes). Falling back to `undefined` there would make a real
58
+ // subtask look like a top-level row — breaking the depth-cap gate,
59
+ // `getGroupedTaskIds`'s nested-subtask filter, and the sibling
60
+ // `updateTasks` guard. Explicit `null` from the BE still clears it.
61
+ parentTaskId: payload.parent_task_id !== undefined
62
+ ? (payload.parent_task_id ?? undefined)
63
+ : previousTask?.parentTaskId,
57
64
  recurringSourceTaskId: payload.recurring_source_task_id != null
58
65
  ? payload.recurring_source_task_id
59
66
  : undefined,
@@ -50,7 +50,14 @@ export const mapTaskPayloadToTask = (payload, previousTask) => ({
50
50
  depth: payload.depth !== undefined
51
51
  ? (payload.depth ?? undefined)
52
52
  : previousTask?.depth,
53
- parentTaskId: payload.parent_task_id ?? undefined,
53
+ // `parent_task_id` may be absent on partial updates (e.g. pusher-driven
54
+ // task refreshes). Falling back to `undefined` there would make a real
55
+ // subtask look like a top-level row — breaking the depth-cap gate,
56
+ // `getGroupedTaskIds`'s nested-subtask filter, and the sibling
57
+ // `updateTasks` guard. Explicit `null` from the BE still clears it.
58
+ parentTaskId: payload.parent_task_id !== undefined
59
+ ? (payload.parent_task_id ?? undefined)
60
+ : previousTask?.parentTaskId,
54
61
  recurringSourceTaskId: payload.recurring_source_task_id != null
55
62
  ? payload.recurring_source_task_id
56
63
  : undefined,
@@ -29,7 +29,6 @@ export const initializeTaskToLocalStoreEpic = (actions$, state$) => actions$.pip
29
29
  timeSpent: task.timeSpent,
30
30
  isPrivate: task.isPrivate,
31
31
  taskGroupId: task.taskGroupIds[0],
32
- depth: task.depth,
33
32
  };
34
33
  const actions = [
35
34
  saveTaskUpdatesToLocalStore({ taskDetailLocalData, taskId }),
@@ -24,6 +24,7 @@ export const getTaskDetail = (state, taskId) => {
24
24
  let createdByUser = undefined;
25
25
  let isArchived = undefined;
26
26
  let isDeleted = undefined;
27
+ let depth = undefined;
27
28
  let recurringSourceTaskId = undefined;
28
29
  let snoozedUntil = undefined;
29
30
  let taskGroupId = undefined;
@@ -37,6 +38,7 @@ export const getTaskDetail = (state, taskId) => {
37
38
  const fileIdsInEntity = taskEntity?.fileIds ?? [];
38
39
  if (taskEntity != null) {
39
40
  createdByUser = getUserAndUserRole(userState, userRoleState, addressState, taskEntity.createdBy);
41
+ depth = taskEntity.depth;
40
42
  isArchived = taskEntity.isArchived;
41
43
  isDeleted = taskEntity.isDeleted;
42
44
  recurringSourceTaskId = taskEntity.recurringSourceTaskId;
@@ -100,6 +102,7 @@ export const getTaskDetail = (state, taskId) => {
100
102
  error: fetchStatus.error,
101
103
  version: 0,
102
104
  createdByUser,
105
+ depth,
103
106
  isArchived,
104
107
  isDeleted,
105
108
  recurringSourceTaskId,
@@ -105,21 +105,34 @@ const taskList = createSlice({
105
105
  const { data, archived, completed, deleted, snoozed } = action.payload;
106
106
  draft.fetchState = 'Completed';
107
107
  draft.error = undefined;
108
+ // Build the nested-subtask set from the UNION of every bucket in
109
+ // this payload — not per-bucket. A resolved subtask can arrive in
110
+ // `completed` while its parent (which claims it via `subtasks`)
111
+ // is still in `data`; a per-bucket scan would miss the cross-tab
112
+ // claim and surface the subtask as a phantom top-level row in
113
+ // the Completed tab.
114
+ const nestedSubtaskIds = collectNestedSubtaskIds([
115
+ data,
116
+ completed,
117
+ archived,
118
+ deleted,
119
+ snoozed,
120
+ ]);
108
121
  // Group live tasks
109
- const liveGrouped = getGroupedTaskIds(data);
122
+ const liveGrouped = getGroupedTaskIds(data, nestedSubtaskIds);
110
123
  draft.byTab.live = toTabData(liveGrouped);
111
124
  // Group other tabs if provided
112
125
  if (completed != null) {
113
- draft.byTab.completed = toTabData(getGroupedTaskIds(completed));
126
+ draft.byTab.completed = toTabData(getGroupedTaskIds(completed, nestedSubtaskIds));
114
127
  }
115
128
  if (archived != null) {
116
- draft.byTab.archived = toTabData(getGroupedTaskIds(archived));
129
+ draft.byTab.archived = toTabData(getGroupedTaskIds(archived, nestedSubtaskIds));
117
130
  }
118
131
  if (deleted != null) {
119
- draft.byTab.deleted = toTabData(getGroupedTaskIds(deleted));
132
+ draft.byTab.deleted = toTabData(getGroupedTaskIds(deleted, nestedSubtaskIds));
120
133
  }
121
134
  if (snoozed != null) {
122
- draft.byTab.snoozed = toTabData(getGroupedTaskIds(snoozed));
135
+ draft.byTab.snoozed = toTabData(getGroupedTaskIds(snoozed, nestedSubtaskIds));
123
136
  }
124
137
  // Copy active tab data to top-level fields
125
138
  const activeTabData = draft.byTab[draft.currentTab];
@@ -418,10 +431,17 @@ const taskList = createSlice({
418
431
  // fetch. Mirrors backend split in task_handler.py: only
419
432
  // `resolved` counts as completed; `done` stays Active.
420
433
  //
421
- // Subtasks travel with their parent they appear nested under
422
- // the parent row, not as standalone entries in byTab.taskIds.
423
- // So we only rebucket parent tasks (tasks with no parentTaskId).
424
- const isTopLevelTask = task.parentTaskId == null;
434
+ // "Top-level" here means: currently rendered as a standalone
435
+ // row in the live or completed tab (i.e. present in
436
+ // `byTab.<tab>.taskIds`). We use presence in byTab NOT a
437
+ // `parent_task_id == null` check — so orphan subtasks (parent
438
+ // hidden from the customer's payload, so we render them flat)
439
+ // ALSO migrate between tabs on status flip. This matches the
440
+ // criterion `getGroupedTaskIds` uses when it builds byTab from
441
+ // the initial fetch — a task is nested iff a visible parent's
442
+ // `subtasks` array claims it, otherwise it's top-level here.
443
+ const isTopLevelTask = draft.byTab.live.taskIds.includes(taskId) ||
444
+ draft.byTab.completed.taskIds.includes(taskId);
425
445
  const wasCompleted = prevStatusCode === 'resolved';
426
446
  const isCompleted = newStatusCode === 'resolved';
427
447
  if (isTopLevelTask && wasCompleted !== isCompleted) {
@@ -518,19 +538,22 @@ const taskList = createSlice({
518
538
  },
519
539
  extraReducers: (builder) => {
520
540
  // When the entity store receives updated tasks (e.g. from task detail
521
- // save, snooze/archive/unarchive, etc.), re-bucket parent tasks between
522
- // the live and completed tabs based on the new status. Mirrors the
523
- // backend split in task_handler.py: only `resolved` parents count as
524
- // completed. Subtasks are nested under their parent row, so they
525
- // never move between tabs on their own.
541
+ // save, snooze/archive/unarchive, etc.), re-bucket top-level tasks
542
+ // between the live and completed tabs based on the new status. Mirrors
543
+ // the backend split in task_handler.py: only `resolved` counts as
544
+ // completed.
545
+ //
546
+ // "Top-level" here means: currently rendered as a standalone row in
547
+ // the live or completed tab (i.e. present in
548
+ // `byTab.<tab>.taskIds`). Tasks that are nested under a parent's
549
+ // expanded subtask row live outside byTab.taskIds and are silently
550
+ // skipped by the "in-bucket" check below. This uses the same
551
+ // criterion as `getGroupedTaskIds` — a task is nested iff a visible
552
+ // parent's `subtasks` array claims it, otherwise it's top-level —
553
+ // so orphan subtasks (parent hidden from the customer's payload)
554
+ // migrate correctly on status flip via pusher / detail-save.
526
555
  builder.addCase(updateTasks, (draft, action) => {
527
556
  action.payload.forEach((taskPayload) => {
528
- // Only re-bucket parents; subtasks (parent_task_id is a non-empty
529
- // string) are nested under their parent row and don't move tabs.
530
- if (taskPayload.parent_task_id != null &&
531
- taskPayload.parent_task_id !== '') {
532
- return;
533
- }
534
557
  const taskId = taskPayload.task_id;
535
558
  // `TaskPayload.status` is required per the type — every producer
536
559
  // in this repo sends it, and `mapTaskPayloadToTask` dereferences
@@ -810,7 +833,39 @@ const removeTaskIds = (draft, taskIds) => {
810
833
  removeIdsFromTabData(draft, taskIds);
811
834
  removeIdsFromTabData(draft.byTab[draft.currentTab], taskIds);
812
835
  };
813
- const getGroupedTaskIds = (tasks) => {
836
+ // Collect the union of subtask ids claimed by any parent across every
837
+ // bucket in the payload. See the callsite in `updateTaskList` for why
838
+ // this must be cross-bucket rather than per-bucket.
839
+ const collectNestedSubtaskIds = (buckets) => {
840
+ const nestedSubtaskIds = new Set();
841
+ buckets.forEach((bucket) => {
842
+ if (bucket == null) {
843
+ return;
844
+ }
845
+ bucket.forEach((task) => {
846
+ (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
847
+ });
848
+ });
849
+ return nestedSubtaskIds;
850
+ };
851
+ // A task is a "nested subtask" (hidden from the flat top-level list +
852
+ // dropped from the tab count) iff a parent in the same payload claims
853
+ // it via its `subtasks: [...]` array. Match this criterion exactly to
854
+ // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
855
+ // the tab count and the visible top-level row count disagree
856
+ // whenever the BE emits `parent_task_id` on a subtask but omits it
857
+ // from the parent's `subtasks` array (a real inconsistency this UI
858
+ // sees today).
859
+ //
860
+ // Using `parent_task_id` here would sometimes drop a task from the
861
+ // count that WC still renders as a flat top-level row — that's the
862
+ // bug we're fixing.
863
+ //
864
+ // `nestedSubtaskIds` is passed in from the caller and covers subtasks
865
+ // claimed by parents in ANY bucket (live/completed/archived/deleted/
866
+ // snoozed), so a subtask resolved into `completed` while its parent
867
+ // stays in `data` is still correctly recognized as nested.
868
+ const getGroupedTaskIds = (tasks, nestedSubtaskIds) => {
814
869
  const taskIds = [];
815
870
  const taskIdsByGroupIds = {};
816
871
  const taskIdsByAssignees = {};
@@ -824,22 +879,6 @@ const getGroupedTaskIds = (tasks) => {
824
879
  ...initialTaskIdsByDueDate,
825
880
  };
826
881
  const taskIdsByTags = {};
827
- // A task is a "nested subtask" (hidden from the flat top-level list +
828
- // dropped from the tab count) iff a parent in the same payload claims
829
- // it via its `subtasks: [...]` array. Match this criterion exactly to
830
- // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
831
- // the tab count and the visible top-level row count disagree
832
- // whenever the BE emits `parent_task_id` on a subtask but omits it
833
- // from the parent's `subtasks` array (a real inconsistency this UI
834
- // sees today).
835
- //
836
- // Using `parent_task_id` here would sometimes drop a task from the
837
- // count that WC still renders as a flat top-level row — that's the
838
- // bug we're fixing.
839
- const nestedSubtaskIds = new Set();
840
- tasks.forEach((task) => {
841
- (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
842
- });
843
882
  tasks.forEach((task) => {
844
883
  const isNestedSubtask = nestedSubtaskIds.has(task.task_id);
845
884
  // Subtasks stay in every groupBy array so the UI can render them
@@ -35,7 +35,6 @@ const initializeTaskToLocalStoreEpic = (actions$, state$) => actions$.pipe((0, o
35
35
  timeSpent: task.timeSpent,
36
36
  isPrivate: task.isPrivate,
37
37
  taskGroupId: task.taskGroupIds[0],
38
- depth: task.depth,
39
38
  };
40
39
  const actions = [
41
40
  (0, taskDetailReducer_1.saveTaskUpdatesToLocalStore)({ taskDetailLocalData, taskId }),
@@ -47,7 +47,6 @@ export interface EditTaskLocalData {
47
47
  tagIds: ID[];
48
48
  timeSpent: string;
49
49
  type: TaskType;
50
- depth?: number;
51
50
  dueDate?: ZeniDate;
52
51
  isPrivate?: boolean;
53
52
  recurringDaysOfWeek?: DayOfWeek[];
@@ -20,6 +20,7 @@ export interface TaskDetailSelectorView extends SelectorView {
20
20
  updateFileStatusById: Record<ID, FetchStateAndError | undefined>;
21
21
  userList: UserListSelectorView;
22
22
  createdByUser?: UserAndRole;
23
+ depth?: number;
23
24
  isArchived?: boolean;
24
25
  isDeleted?: boolean;
25
26
  recurringSourceTaskId?: ID;
@@ -30,6 +30,7 @@ const getTaskDetail = (state, taskId) => {
30
30
  let createdByUser = undefined;
31
31
  let isArchived = undefined;
32
32
  let isDeleted = undefined;
33
+ let depth = undefined;
33
34
  let recurringSourceTaskId = undefined;
34
35
  let snoozedUntil = undefined;
35
36
  let taskGroupId = undefined;
@@ -43,6 +44,7 @@ const getTaskDetail = (state, taskId) => {
43
44
  const fileIdsInEntity = taskEntity?.fileIds ?? [];
44
45
  if (taskEntity != null) {
45
46
  createdByUser = (0, userAndRole_1.getUserAndUserRole)(userState, userRoleState, addressState, taskEntity.createdBy);
47
+ depth = taskEntity.depth;
46
48
  isArchived = taskEntity.isArchived;
47
49
  isDeleted = taskEntity.isDeleted;
48
50
  recurringSourceTaskId = taskEntity.recurringSourceTaskId;
@@ -106,6 +108,7 @@ const getTaskDetail = (state, taskId) => {
106
108
  error: fetchStatus.error,
107
109
  version: 0,
108
110
  createdByUser,
111
+ depth,
109
112
  isArchived,
110
113
  isDeleted,
111
114
  recurringSourceTaskId,
@@ -109,21 +109,34 @@ const taskList = (0, toolkit_1.createSlice)({
109
109
  const { data, archived, completed, deleted, snoozed } = action.payload;
110
110
  draft.fetchState = 'Completed';
111
111
  draft.error = undefined;
112
+ // Build the nested-subtask set from the UNION of every bucket in
113
+ // this payload — not per-bucket. A resolved subtask can arrive in
114
+ // `completed` while its parent (which claims it via `subtasks`)
115
+ // is still in `data`; a per-bucket scan would miss the cross-tab
116
+ // claim and surface the subtask as a phantom top-level row in
117
+ // the Completed tab.
118
+ const nestedSubtaskIds = collectNestedSubtaskIds([
119
+ data,
120
+ completed,
121
+ archived,
122
+ deleted,
123
+ snoozed,
124
+ ]);
112
125
  // Group live tasks
113
- const liveGrouped = getGroupedTaskIds(data);
126
+ const liveGrouped = getGroupedTaskIds(data, nestedSubtaskIds);
114
127
  draft.byTab.live = toTabData(liveGrouped);
115
128
  // Group other tabs if provided
116
129
  if (completed != null) {
117
- draft.byTab.completed = toTabData(getGroupedTaskIds(completed));
130
+ draft.byTab.completed = toTabData(getGroupedTaskIds(completed, nestedSubtaskIds));
118
131
  }
119
132
  if (archived != null) {
120
- draft.byTab.archived = toTabData(getGroupedTaskIds(archived));
133
+ draft.byTab.archived = toTabData(getGroupedTaskIds(archived, nestedSubtaskIds));
121
134
  }
122
135
  if (deleted != null) {
123
- draft.byTab.deleted = toTabData(getGroupedTaskIds(deleted));
136
+ draft.byTab.deleted = toTabData(getGroupedTaskIds(deleted, nestedSubtaskIds));
124
137
  }
125
138
  if (snoozed != null) {
126
- draft.byTab.snoozed = toTabData(getGroupedTaskIds(snoozed));
139
+ draft.byTab.snoozed = toTabData(getGroupedTaskIds(snoozed, nestedSubtaskIds));
127
140
  }
128
141
  // Copy active tab data to top-level fields
129
142
  const activeTabData = draft.byTab[draft.currentTab];
@@ -422,10 +435,17 @@ const taskList = (0, toolkit_1.createSlice)({
422
435
  // fetch. Mirrors backend split in task_handler.py: only
423
436
  // `resolved` counts as completed; `done` stays Active.
424
437
  //
425
- // Subtasks travel with their parent they appear nested under
426
- // the parent row, not as standalone entries in byTab.taskIds.
427
- // So we only rebucket parent tasks (tasks with no parentTaskId).
428
- const isTopLevelTask = task.parentTaskId == null;
438
+ // "Top-level" here means: currently rendered as a standalone
439
+ // row in the live or completed tab (i.e. present in
440
+ // `byTab.<tab>.taskIds`). We use presence in byTab NOT a
441
+ // `parent_task_id == null` check — so orphan subtasks (parent
442
+ // hidden from the customer's payload, so we render them flat)
443
+ // ALSO migrate between tabs on status flip. This matches the
444
+ // criterion `getGroupedTaskIds` uses when it builds byTab from
445
+ // the initial fetch — a task is nested iff a visible parent's
446
+ // `subtasks` array claims it, otherwise it's top-level here.
447
+ const isTopLevelTask = draft.byTab.live.taskIds.includes(taskId) ||
448
+ draft.byTab.completed.taskIds.includes(taskId);
429
449
  const wasCompleted = prevStatusCode === 'resolved';
430
450
  const isCompleted = newStatusCode === 'resolved';
431
451
  if (isTopLevelTask && wasCompleted !== isCompleted) {
@@ -522,19 +542,22 @@ const taskList = (0, toolkit_1.createSlice)({
522
542
  },
523
543
  extraReducers: (builder) => {
524
544
  // When the entity store receives updated tasks (e.g. from task detail
525
- // save, snooze/archive/unarchive, etc.), re-bucket parent tasks between
526
- // the live and completed tabs based on the new status. Mirrors the
527
- // backend split in task_handler.py: only `resolved` parents count as
528
- // completed. Subtasks are nested under their parent row, so they
529
- // never move between tabs on their own.
545
+ // save, snooze/archive/unarchive, etc.), re-bucket top-level tasks
546
+ // between the live and completed tabs based on the new status. Mirrors
547
+ // the backend split in task_handler.py: only `resolved` counts as
548
+ // completed.
549
+ //
550
+ // "Top-level" here means: currently rendered as a standalone row in
551
+ // the live or completed tab (i.e. present in
552
+ // `byTab.<tab>.taskIds`). Tasks that are nested under a parent's
553
+ // expanded subtask row live outside byTab.taskIds and are silently
554
+ // skipped by the "in-bucket" check below. This uses the same
555
+ // criterion as `getGroupedTaskIds` — a task is nested iff a visible
556
+ // parent's `subtasks` array claims it, otherwise it's top-level —
557
+ // so orphan subtasks (parent hidden from the customer's payload)
558
+ // migrate correctly on status flip via pusher / detail-save.
530
559
  builder.addCase(taskReducer_1.updateTasks, (draft, action) => {
531
560
  action.payload.forEach((taskPayload) => {
532
- // Only re-bucket parents; subtasks (parent_task_id is a non-empty
533
- // string) are nested under their parent row and don't move tabs.
534
- if (taskPayload.parent_task_id != null &&
535
- taskPayload.parent_task_id !== '') {
536
- return;
537
- }
538
561
  const taskId = taskPayload.task_id;
539
562
  // `TaskPayload.status` is required per the type — every producer
540
563
  // in this repo sends it, and `mapTaskPayloadToTask` dereferences
@@ -814,7 +837,39 @@ const removeTaskIds = (draft, taskIds) => {
814
837
  removeIdsFromTabData(draft, taskIds);
815
838
  removeIdsFromTabData(draft.byTab[draft.currentTab], taskIds);
816
839
  };
817
- const getGroupedTaskIds = (tasks) => {
840
+ // Collect the union of subtask ids claimed by any parent across every
841
+ // bucket in the payload. See the callsite in `updateTaskList` for why
842
+ // this must be cross-bucket rather than per-bucket.
843
+ const collectNestedSubtaskIds = (buckets) => {
844
+ const nestedSubtaskIds = new Set();
845
+ buckets.forEach((bucket) => {
846
+ if (bucket == null) {
847
+ return;
848
+ }
849
+ bucket.forEach((task) => {
850
+ (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
851
+ });
852
+ });
853
+ return nestedSubtaskIds;
854
+ };
855
+ // A task is a "nested subtask" (hidden from the flat top-level list +
856
+ // dropped from the tab count) iff a parent in the same payload claims
857
+ // it via its `subtasks: [...]` array. Match this criterion exactly to
858
+ // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
859
+ // the tab count and the visible top-level row count disagree
860
+ // whenever the BE emits `parent_task_id` on a subtask but omits it
861
+ // from the parent's `subtasks` array (a real inconsistency this UI
862
+ // sees today).
863
+ //
864
+ // Using `parent_task_id` here would sometimes drop a task from the
865
+ // count that WC still renders as a flat top-level row — that's the
866
+ // bug we're fixing.
867
+ //
868
+ // `nestedSubtaskIds` is passed in from the caller and covers subtasks
869
+ // claimed by parents in ANY bucket (live/completed/archived/deleted/
870
+ // snoozed), so a subtask resolved into `completed` while its parent
871
+ // stays in `data` is still correctly recognized as nested.
872
+ const getGroupedTaskIds = (tasks, nestedSubtaskIds) => {
818
873
  const taskIds = [];
819
874
  const taskIdsByGroupIds = {};
820
875
  const taskIdsByAssignees = {};
@@ -828,22 +883,6 @@ const getGroupedTaskIds = (tasks) => {
828
883
  ...initialTaskIdsByDueDate,
829
884
  };
830
885
  const taskIdsByTags = {};
831
- // A task is a "nested subtask" (hidden from the flat top-level list +
832
- // dropped from the tab count) iff a parent in the same payload claims
833
- // it via its `subtasks: [...]` array. Match this criterion exactly to
834
- // WC's `allSubtaskIds` union in TaskManagementPage.tsx — otherwise
835
- // the tab count and the visible top-level row count disagree
836
- // whenever the BE emits `parent_task_id` on a subtask but omits it
837
- // from the parent's `subtasks` array (a real inconsistency this UI
838
- // sees today).
839
- //
840
- // Using `parent_task_id` here would sometimes drop a task from the
841
- // count that WC still renders as a flat top-level row — that's the
842
- // bug we're fixing.
843
- const nestedSubtaskIds = new Set();
844
- tasks.forEach((task) => {
845
- (task.subtasks ?? []).forEach((subtaskId) => nestedSubtaskIds.add(subtaskId));
846
- });
847
886
  tasks.forEach((task) => {
848
887
  const isNestedSubtask = nestedSubtaskIds.has(task.task_id);
849
888
  // Subtasks stay in every groupBy array so the UI can render them
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.45-betaDI2",
3
+ "version": "5.1.45-betaDI3",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",