@retailcrm/embed-ui-v1-contexts 0.9.18 → 0.9.21

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.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const pinia = require("pinia");
4
- const CustomContextAccessorKey = Symbol("CustomContextAccessor");
4
+ const CustomContextAccessorKey = /* @__PURE__ */ Symbol("CustomContextAccessor");
5
5
  const injectAccessor = (endpoint) => {
6
6
  return (context) => {
7
7
  context.store[CustomContextAccessorKey] = endpoint.call;
@@ -1,5 +1,5 @@
1
1
  import { defineStore } from "pinia";
2
- const CustomContextAccessorKey = Symbol("CustomContextAccessor");
2
+ const CustomContextAccessorKey = /* @__PURE__ */ Symbol("CustomContextAccessor");
3
3
  const injectAccessor = (endpoint) => {
4
4
  return (context) => {
5
5
  context.store[CustomContextAccessorKey] = endpoint.call;
@@ -0,0 +1,13 @@
1
+ # Концепт [DRAFT]
2
+
3
+ Данный пакет предоставляет логику и типы для host и remote окружения. Часть предложенных типов используются одновременно
4
+ в обоих окружениях, в частности `ContextAccessor` и `CustomContextAccessor` – на стороне host'а создаются два таких
5
+ объекта и смешиваются в один, чтобы затем их методы предоставить в качестве удаленного API, который потребляется
6
+ расширениями в remote окружении.
7
+
8
+ `ContextAccessor` используется для получения/изменения данных некоторого предустановленного контекста, состав которого
9
+ известен заранее. Для доступа к полям указывается название частичного контекста, например, `order/card` и название поля
10
+ в частичном контексте.
11
+
12
+ `CustomContextAccessor` используется для получения/изменения данных некоторого пользовательского контекста, который
13
+ основан на пользовательских полях. Состав такого контекста заранее неизвестен.
@@ -0,0 +1,122 @@
1
+ # Пользовательский контекст
2
+
3
+ В JS API существует специальный тип реактивного контекста, который используется для взаимодействия с пользовательскими
4
+ полями, определенными в CRM.
5
+
6
+ Для контекста этого типа существует лишь обобщенное определение, в котором наименования полей и их типы не фиксированы,
7
+ фиксирован лишь список возможных типов полей и как с ними можно взаимодействовать.
8
+
9
+ > [!NOTE]
10
+ > На данный момент доступен контекст для сущности `order` в целях встраивания `order/card:*`.
11
+
12
+ ## Схема контекста
13
+
14
+ Схема контекста служит описанием того, как строить начальное состояние контекста на стороне расширения.
15
+ Схема включает:
16
+
17
+ * Символьный код контекста
18
+ * Массив описаний полей, каждое из которых содержит:
19
+ * Тип поля
20
+ * Символьный код поля
21
+ * Флаг доступности только для чтения
22
+ * Начальное значение
23
+ Также описание поля может включать дополнительные сведения, такие как символьный код словаря возможных значений
24
+
25
+ Определение схемы контекста можно обнаружить здесь (`CustomContextSchema`):
26
+ [https://github.com/retailcrm/embed-ui/packages/v1-types/context.d.ts#L169-L169](https://github.com/retailcrm/embed-ui/blob/82477ce0a9124e598d3a84db3739c850509c0fcc/packages/v1-types/context.d.ts#L169-L169)
27
+
28
+ ## Хранилище и работа контекста
29
+
30
+ Для взаимодействия с контекстом на стороне расширения используются хранилища `Pinia`, опирающиеся на определения,
31
+ получаемые по запросу со стороны CRM.
32
+
33
+ В начальном состоянии хранилище контекста содержит только символьный код для идентификации при общении расширения с CRM.
34
+ На этой фазе значения полей и их состав не определен. Для того чтобы произвести заполнение хранилища, нужно произвести
35
+ инициализацию, при которой расширение посылает CRM postMessage событие с запросом на получение схемы.
36
+ Если символьный код корректный и требуемый контекст на странице существует, то CRM отдаст схему контекста, на основе
37
+ которой хранилище сформирует реактивные данные и подпишется на события об изменениях, присылаемых CRM.
38
+ После чего можно приступать к взаимодействию.
39
+
40
+ ```typescript
41
+ /** Импорт composable-утилиты для получения пользовательского контекста. */
42
+ import { useContext } from '@retailcrm/embed-ui-v1-contexts/remote/custom'
43
+
44
+ /** Импорт composable-утилиты для получения вычисляемого поля для пользовательского контекста. */
45
+ import { useCustomField } from '@retailcrm/embed-ui'
46
+
47
+ /**
48
+ * Для получения контекста нужно указать его символьный код. useContext возвращает pinia хранилище
49
+ */
50
+ const custom = useContext('order')
51
+
52
+ /**
53
+ * Метод возвращает `Promise<CustomContextSchema>`
54
+ *
55
+ * Также схему после инициализации можно получить из хранилища: `custom.schema`
56
+ *
57
+ * В метод можно передать в качестве аргумента метод с сигнатурой `(rejection: Rejection) => void` для обработки ошибки,
58
+ * которую может сгенерировать CRM, если указанный контекст не существует.
59
+ * Определение для `Rejection` можно найти здесь:
60
+ * https://github.com/retailcrm/embed-ui/blob/82477ce0a9124e598d3a84db3739c850509c0fcc/packages/v1-types/context.d.ts#L101-L101
61
+ */
62
+ custom.initialize()
63
+
64
+ /**
65
+ * Вычисляемое поле на основе пользовательского контекста.
66
+ * В useCustomField указываем сначала контекст, затем код поля в контексте.
67
+ * Если код не существует (или контекст еще не инициализирован), значение в поле будет равно `null`
68
+ * Если не указывать третьим параметром опции, то утилита вернет WritableComputedRef. Но это не значит, что setter будет
69
+ * гарантированного работать. Если в настройках поля, пришедших из CRM указан флаг `readonly` равный true, то код
70
+ * будет вызывать ошибку. Также ошибка будет появляться при попытки записи, если контекст еще не проинициализирован.
71
+ */
72
+ const someField = useCustomField(custom, 'code')
73
+
74
+ /**
75
+ * Можно указать, какой тип для конкретного поля ожидается, чтобы дальше TypeScript
76
+ * корректно подсвечивал его. Также можно указать дополнительные опции:
77
+ * `readonly` - логический флаг, который укажет, что поле только для чтения; если этот флаг указан как `true`,
78
+ * вместо WritableComputedRef будет возвращен ComputedRef
79
+ * `onReject` - обработчик отклонения попытки записи в поле на стороне CRM
80
+ *
81
+ * Список доступных значений для параметра kind можно найти здесь:
82
+ * https://github.com/retailcrm/embed-ui/blob/82477ce0a9124e598d3a84db3739c850509c0fcc/packages/v1-types/context.d.ts#L153-L153
83
+ *
84
+ * Если тип поля не совпадает с указанным в присланной CRM схеме, то значение поля всегда будет null
85
+ */
86
+ const viewedAt = useCustomField(custom, 'viewedAt', { kind: 'date' })
87
+ ```
88
+
89
+ ## Работа со словарями
90
+
91
+ Для полей `dictionary` и `multiselect_dictionary` можно загрузить список значений, используя утилиту
92
+ `useDictionary`, которая предоставляет клиент для осуществления запросов списков значений к CRM.
93
+
94
+ Ниже представлен пример:
95
+
96
+ ```typescript
97
+ import type { CustomDictionary } from '@retailcrm/embed-ui-v1-types/context'
98
+
99
+ import { useContext } from '@retailcrm/embed-ui-v1-contexts/remote/custom'
100
+ import { useCustomField } from '@retailcrm/embed-ui'
101
+ import { useDictionary } from '@retailcrm/embed-ui-v1-contexts/remote/custom'
102
+
103
+ const custom = useContext('order')
104
+
105
+ const dictionary = useDictionary()
106
+ const options = ref<CustomDictionary>([])
107
+ const loaded = ref(false)
108
+
109
+ custom.initialize().then(schema => {
110
+ const descriptor = schema?.fields.find(f => f.code === 'accessory')
111
+ if (descriptor && 'dictionaryCode' in descriptor) {
112
+ dictionary.query(descriptor.dictionaryCode).then((result) => {
113
+ options.value = result
114
+ loaded.value = true
115
+ })
116
+ } else {
117
+ throw new Error('No dictionary for field with code ' + props.code)
118
+ }
119
+ })
120
+
121
+ const accessory = useCustomField(custom, 'accessory', { kind: 'dictionary' })
122
+ ```
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@retailcrm/embed-ui-v1-contexts",
3
3
  "description": "Reactive contexts for RetailCRM JS API",
4
4
  "type": "module",
5
- "version": "0.9.18",
5
+ "version": "0.9.21",
6
6
  "license": "MIT",
7
7
  "author": "RetailDriverLLC <integration@retailcrm.ru>",
8
8
  "repository": "git@github.com:retailcrm/embed-ui.git",
@@ -85,6 +85,7 @@
85
85
  },
86
86
  "files": [
87
87
  "dist",
88
+ "docs",
88
89
  "types",
89
90
  "README.md"
90
91
  ],
@@ -102,16 +103,16 @@
102
103
  },
103
104
  "dependencies": {
104
105
  "@omnicajs/symfony-router": "^1.0.0",
105
- "@retailcrm/embed-ui-v1-types": "^0.9.18"
106
+ "@retailcrm/embed-ui-v1-types": "^0.9.21"
106
107
  },
107
108
  "devDependencies": {
108
109
  "@remote-ui/rpc": "^1.4.7",
109
- "@retailcrm/embed-ui-v1-testing": "^0.9.18",
110
+ "@retailcrm/embed-ui-v1-testing": "^0.9.21",
110
111
  "tsx": "^4.21.0",
111
112
  "typescript": "^5.9.3",
112
- "vite": "^7.2.7",
113
+ "vite": "^7.3.2",
113
114
  "vite-plugin-dts": "^4.5.4",
114
- "vitest": "^4.0.15",
115
- "vue": "^3.5.25"
115
+ "vitest": "^4.1.3",
116
+ "vue": "^3.5.32"
116
117
  }
117
118
  }