@milaboratories/pl-client 2.11.8 → 2.11.9

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.
Files changed (242) hide show
  1. package/dist/core/auth.cjs +24 -0
  2. package/dist/core/auth.cjs.map +1 -0
  3. package/dist/core/auth.d.ts +0 -1
  4. package/dist/core/auth.js +21 -0
  5. package/dist/core/auth.js.map +1 -0
  6. package/dist/core/cache.d.ts +0 -1
  7. package/dist/core/client.cjs +288 -0
  8. package/dist/core/client.cjs.map +1 -0
  9. package/dist/core/client.d.ts +0 -1
  10. package/dist/core/client.js +267 -0
  11. package/dist/core/client.js.map +1 -0
  12. package/dist/core/config.cjs +111 -0
  13. package/dist/core/config.cjs.map +1 -0
  14. package/dist/core/config.d.ts +0 -1
  15. package/dist/core/config.js +95 -0
  16. package/dist/core/config.js.map +1 -0
  17. package/dist/core/default_client.cjs +143 -0
  18. package/dist/core/default_client.cjs.map +1 -0
  19. package/dist/core/default_client.d.ts +0 -1
  20. package/dist/core/default_client.js +120 -0
  21. package/dist/core/default_client.js.map +1 -0
  22. package/dist/core/driver.cjs +14 -0
  23. package/dist/core/driver.cjs.map +1 -0
  24. package/dist/core/driver.d.ts +0 -1
  25. package/dist/core/driver.js +12 -0
  26. package/dist/core/driver.js.map +1 -0
  27. package/dist/core/error_resource.cjs +9 -0
  28. package/dist/core/error_resource.cjs.map +1 -0
  29. package/dist/core/error_resource.d.ts +0 -1
  30. package/dist/core/error_resource.js +7 -0
  31. package/dist/core/error_resource.js.map +1 -0
  32. package/dist/core/errors.cjs +106 -0
  33. package/dist/core/errors.cjs.map +1 -0
  34. package/dist/core/errors.d.ts +0 -1
  35. package/dist/core/errors.js +93 -0
  36. package/dist/core/errors.js.map +1 -0
  37. package/dist/core/final.cjs +98 -0
  38. package/dist/core/final.cjs.map +1 -0
  39. package/dist/core/final.d.ts +0 -1
  40. package/dist/core/final.js +96 -0
  41. package/dist/core/final.js.map +1 -0
  42. package/dist/core/grpc.d.ts +0 -1
  43. package/dist/core/http.d.ts +1 -1
  44. package/dist/core/ll_client.cjs +266 -0
  45. package/dist/core/ll_client.cjs.map +1 -0
  46. package/dist/core/ll_client.d.ts +0 -1
  47. package/dist/core/ll_client.js +264 -0
  48. package/dist/core/ll_client.js.map +1 -0
  49. package/dist/core/ll_transaction.cjs +236 -0
  50. package/dist/core/ll_transaction.cjs.map +1 -0
  51. package/dist/core/ll_transaction.d.ts +0 -1
  52. package/dist/core/ll_transaction.js +233 -0
  53. package/dist/core/ll_transaction.js.map +1 -0
  54. package/dist/core/stat.cjs +74 -0
  55. package/dist/core/stat.cjs.map +1 -0
  56. package/dist/core/stat.d.ts +0 -1
  57. package/dist/core/stat.js +70 -0
  58. package/dist/core/stat.js.map +1 -0
  59. package/dist/core/transaction.cjs +626 -0
  60. package/dist/core/transaction.cjs.map +1 -0
  61. package/dist/core/transaction.d.ts +0 -1
  62. package/dist/core/transaction.js +613 -0
  63. package/dist/core/transaction.js.map +1 -0
  64. package/dist/core/type_conversion.cjs +106 -0
  65. package/dist/core/type_conversion.cjs.map +1 -0
  66. package/dist/core/type_conversion.d.ts +0 -1
  67. package/dist/core/type_conversion.js +102 -0
  68. package/dist/core/type_conversion.js.map +1 -0
  69. package/dist/core/types.cjs +159 -0
  70. package/dist/core/types.cjs.map +1 -0
  71. package/dist/core/types.d.ts +0 -1
  72. package/dist/core/types.js +134 -0
  73. package/dist/core/types.js.map +1 -0
  74. package/dist/core/unauth_client.cjs +43 -0
  75. package/dist/core/unauth_client.cjs.map +1 -0
  76. package/dist/core/unauth_client.d.ts +0 -1
  77. package/dist/core/unauth_client.js +41 -0
  78. package/dist/core/unauth_client.js.map +1 -0
  79. package/dist/helpers/pl.cjs +124 -0
  80. package/dist/helpers/pl.cjs.map +1 -0
  81. package/dist/helpers/pl.d.ts +0 -1
  82. package/dist/helpers/pl.js +94 -0
  83. package/dist/helpers/pl.js.map +1 -0
  84. package/dist/helpers/poll.cjs +148 -0
  85. package/dist/helpers/poll.cjs.map +1 -0
  86. package/dist/helpers/poll.d.ts +0 -1
  87. package/dist/helpers/poll.js +123 -0
  88. package/dist/helpers/poll.js.map +1 -0
  89. package/dist/helpers/rich_resource_types.d.ts +1 -1
  90. package/dist/helpers/smart_accessors.d.ts +1 -1
  91. package/dist/helpers/state_helpers.d.ts +0 -1
  92. package/dist/helpers/tx_helpers.cjs +25 -0
  93. package/dist/helpers/tx_helpers.cjs.map +1 -0
  94. package/dist/helpers/tx_helpers.d.ts +0 -1
  95. package/dist/helpers/tx_helpers.js +23 -0
  96. package/dist/helpers/tx_helpers.js.map +1 -0
  97. package/dist/index.cjs +99 -0
  98. package/dist/index.cjs.map +1 -0
  99. package/dist/index.d.ts +0 -1
  100. package/dist/index.js +16 -1
  101. package/dist/index.js.map +1 -1
  102. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.cjs +71 -0
  103. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.cjs.map +1 -0
  104. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.d.ts +0 -1
  105. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.js +69 -0
  106. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.js.map +1 -0
  107. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.d.ts +3 -5
  108. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts +0 -1
  109. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.d.ts +3 -5
  110. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts +0 -1
  111. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.d.ts +3 -5
  112. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts +0 -1
  113. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.d.ts +3 -5
  114. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts +0 -1
  115. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +12238 -0
  116. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -0
  117. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs +223 -0
  118. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.cjs.map +1 -0
  119. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts +3 -5
  120. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.js +221 -0
  121. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.js.map +1 -0
  122. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +0 -1
  123. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.js +12086 -0
  124. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -0
  125. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs +1127 -0
  126. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.cjs.map +1 -0
  127. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts +0 -1
  128. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.js +1113 -0
  129. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.js.map +1 -0
  130. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs +152 -0
  131. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.cjs.map +1 -0
  132. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts +0 -1
  133. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.js +149 -0
  134. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.js.map +1 -0
  135. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/import.d.ts +0 -1
  136. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs +500 -0
  137. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.cjs.map +1 -0
  138. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts +0 -1
  139. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js +496 -0
  140. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.js.map +1 -0
  141. package/dist/proto/google/api/http.d.ts +0 -1
  142. package/dist/proto/google/protobuf/any.cjs +151 -0
  143. package/dist/proto/google/protobuf/any.cjs.map +1 -0
  144. package/dist/proto/google/protobuf/any.d.ts +0 -1
  145. package/dist/proto/google/protobuf/any.js +149 -0
  146. package/dist/proto/google/protobuf/any.js.map +1 -0
  147. package/dist/proto/google/protobuf/descriptor.d.ts +0 -1
  148. package/dist/proto/google/protobuf/duration.cjs +105 -0
  149. package/dist/proto/google/protobuf/duration.cjs.map +1 -0
  150. package/dist/proto/google/protobuf/duration.d.ts +0 -1
  151. package/dist/proto/google/protobuf/duration.js +103 -0
  152. package/dist/proto/google/protobuf/duration.js.map +1 -0
  153. package/dist/proto/google/protobuf/empty.d.ts +0 -1
  154. package/dist/proto/google/protobuf/struct.d.ts +0 -1
  155. package/dist/proto/google/protobuf/timestamp.cjs +133 -0
  156. package/dist/proto/google/protobuf/timestamp.cjs.map +1 -0
  157. package/dist/proto/google/protobuf/timestamp.d.ts +0 -1
  158. package/dist/proto/google/protobuf/timestamp.js +131 -0
  159. package/dist/proto/google/protobuf/timestamp.js.map +1 -0
  160. package/dist/proto/google/protobuf/wrappers.d.ts +0 -1
  161. package/dist/test/test_config.cjs +149 -0
  162. package/dist/test/test_config.cjs.map +1 -0
  163. package/dist/test/test_config.d.ts +0 -1
  164. package/dist/test/test_config.js +123 -0
  165. package/dist/test/test_config.js.map +1 -0
  166. package/dist/util/branding.d.ts +0 -1
  167. package/dist/util/pl.cjs +8 -0
  168. package/dist/util/pl.cjs.map +1 -0
  169. package/dist/util/pl.d.ts +0 -1
  170. package/dist/util/pl.js +6 -0
  171. package/dist/util/pl.js.map +1 -0
  172. package/dist/util/util.cjs +17 -0
  173. package/dist/util/util.cjs.map +1 -0
  174. package/dist/util/util.d.ts +0 -1
  175. package/dist/util/util.js +15 -0
  176. package/dist/util/util.js.map +1 -0
  177. package/package.json +14 -11
  178. package/src/core/client.test.ts +1 -0
  179. package/src/core/config.test.ts +1 -0
  180. package/src/core/error.test.ts +1 -0
  181. package/src/core/ll_client.test.ts +1 -0
  182. package/src/core/ll_transaction.test.ts +1 -0
  183. package/src/core/transaction.test.ts +1 -0
  184. package/src/core/types.test.ts +1 -0
  185. package/src/core/unauth_client.test.ts +1 -0
  186. package/src/helpers/rich_resource_types.test.ts +2 -0
  187. package/src/test/test_config.test.ts +1 -0
  188. package/src/util/util.test.ts +1 -0
  189. package/dist/core/auth.d.ts.map +0 -1
  190. package/dist/core/cache.d.ts.map +0 -1
  191. package/dist/core/client.d.ts.map +0 -1
  192. package/dist/core/config.d.ts.map +0 -1
  193. package/dist/core/default_client.d.ts.map +0 -1
  194. package/dist/core/driver.d.ts.map +0 -1
  195. package/dist/core/error_resource.d.ts.map +0 -1
  196. package/dist/core/errors.d.ts.map +0 -1
  197. package/dist/core/final.d.ts.map +0 -1
  198. package/dist/core/grpc.d.ts.map +0 -1
  199. package/dist/core/http.d.ts.map +0 -1
  200. package/dist/core/ll_client.d.ts.map +0 -1
  201. package/dist/core/ll_transaction.d.ts.map +0 -1
  202. package/dist/core/stat.d.ts.map +0 -1
  203. package/dist/core/transaction.d.ts.map +0 -1
  204. package/dist/core/type_conversion.d.ts.map +0 -1
  205. package/dist/core/types.d.ts.map +0 -1
  206. package/dist/core/unauth_client.d.ts.map +0 -1
  207. package/dist/helpers/pl.d.ts.map +0 -1
  208. package/dist/helpers/poll.d.ts.map +0 -1
  209. package/dist/helpers/rich_resource_types.d.ts.map +0 -1
  210. package/dist/helpers/smart_accessors.d.ts.map +0 -1
  211. package/dist/helpers/state_helpers.d.ts.map +0 -1
  212. package/dist/helpers/tx_helpers.d.ts.map +0 -1
  213. package/dist/index.d.ts.map +0 -1
  214. package/dist/index.mjs +0 -14537
  215. package/dist/index.mjs.map +0 -1
  216. package/dist/proto/github.com/googleapis/googleapis/google/rpc/status.d.ts.map +0 -1
  217. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.d.ts.map +0 -1
  218. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts.map +0 -1
  219. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.d.ts.map +0 -1
  220. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts.map +0 -1
  221. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.d.ts.map +0 -1
  222. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts.map +0 -1
  223. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.d.ts.map +0 -1
  224. package/dist/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts.map +0 -1
  225. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.d.ts.map +0 -1
  226. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +0 -1
  227. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.d.ts.map +0 -1
  228. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.d.ts.map +0 -1
  229. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/import.d.ts.map +0 -1
  230. package/dist/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.d.ts.map +0 -1
  231. package/dist/proto/google/api/http.d.ts.map +0 -1
  232. package/dist/proto/google/protobuf/any.d.ts.map +0 -1
  233. package/dist/proto/google/protobuf/descriptor.d.ts.map +0 -1
  234. package/dist/proto/google/protobuf/duration.d.ts.map +0 -1
  235. package/dist/proto/google/protobuf/empty.d.ts.map +0 -1
  236. package/dist/proto/google/protobuf/struct.d.ts.map +0 -1
  237. package/dist/proto/google/protobuf/timestamp.d.ts.map +0 -1
  238. package/dist/proto/google/protobuf/wrappers.d.ts.map +0 -1
  239. package/dist/test/test_config.d.ts.map +0 -1
  240. package/dist/util/branding.d.ts.map +0 -1
  241. package/dist/util/pl.d.ts.map +0 -1
  242. package/dist/util/util.d.ts.map +0 -1
@@ -0,0 +1,626 @@
1
+ 'use strict';
2
+
3
+ var types = require('./types.cjs');
4
+ var api = require('../proto/github.com/milaboratory/pl/plapi/plapiproto/api.cjs');
5
+ var util = require('../util/util.cjs');
6
+ var type_conversion = require('./type_conversion.cjs');
7
+ var tsHelpers = require('@milaboratories/ts-helpers');
8
+ var errors = require('./errors.cjs');
9
+ var stat = require('./stat.cjs');
10
+ var error_resource = require('./error_resource.cjs');
11
+ var pl = require('../helpers/pl.cjs');
12
+
13
+ function isField(ref) {
14
+ return ref.hasOwnProperty('resourceId') && ref.hasOwnProperty('fieldName');
15
+ }
16
+ function isResource(ref) {
17
+ return (typeof ref === 'bigint' || (ref.hasOwnProperty('globalId') && ref.hasOwnProperty('localId')));
18
+ }
19
+ function isResourceId(ref) {
20
+ return typeof ref === 'bigint' && !types.isLocalResourceId(ref) && !types.isNullResourceId(ref);
21
+ }
22
+ function isFieldRef(ref) {
23
+ return isResourceRef(ref.resourceId);
24
+ }
25
+ function isResourceRef(ref) {
26
+ return ref.hasOwnProperty('globalId') && ref.hasOwnProperty('localId');
27
+ }
28
+ function toFieldId(ref) {
29
+ if (isFieldRef(ref))
30
+ return { resourceId: ref.resourceId.localId, fieldName: ref.fieldName };
31
+ else
32
+ return ref;
33
+ }
34
+ async function toGlobalFieldId(ref) {
35
+ if (isFieldRef(ref))
36
+ return { resourceId: await ref.resourceId.globalId, fieldName: ref.fieldName };
37
+ else
38
+ return ref;
39
+ }
40
+ function toResourceId(ref) {
41
+ if (isResourceRef(ref))
42
+ return ref.localId;
43
+ else
44
+ return ref;
45
+ }
46
+ async function toGlobalResourceId(ref) {
47
+ if (isResourceRef(ref))
48
+ return await ref.globalId;
49
+ else
50
+ return ref;
51
+ }
52
+ function field(resourceId, fieldName) {
53
+ return { resourceId, fieldName };
54
+ }
55
+ /** If transaction commit failed due to write conflicts */
56
+ class TxCommitConflict extends Error {
57
+ name = 'TxCommitConflict';
58
+ }
59
+ async function notFoundToUndefined(cb) {
60
+ try {
61
+ return await cb();
62
+ }
63
+ catch (e) {
64
+ if (errors.isNotFoundError(e))
65
+ return undefined;
66
+ throw e;
67
+ }
68
+ }
69
+ /**
70
+ * Each platform transaction has 3 stages:
71
+ * - initialization (txOpen message -> txInfo response)
72
+ * - communication (create resources, fields, references and so on)
73
+ * - finalization (txCommit or txDiscard message)
74
+ *
75
+ * This class encapsulates finalization stage and provides ready-to-communication transaction object.
76
+ * */
77
+ class PlTransaction {
78
+ ll;
79
+ name;
80
+ writable;
81
+ _clientRoot;
82
+ finalPredicate;
83
+ sharedResourceDataCache;
84
+ enableFormattedErrors;
85
+ globalTxId;
86
+ localTxId = PlTransaction.nextLocalTxId();
87
+ /** Used in caching */
88
+ txOpenTimestamp = Date.now();
89
+ localResourceIdCounter = 0;
90
+ /** Store logical tx open / closed state to prevent invalid sequence of requests.
91
+ * True means output stream was completed.
92
+ * Contract: there must be no async operations between setting this field to true and sending complete signal to stream. */
93
+ _completed = false;
94
+ /** Void operation futures are placed into this pool, and corresponding method return immediately.
95
+ * This is done to save number of round-trips. Next operation producing result will also await those
96
+ * pending ops, to throw any pending errors. */
97
+ pendingVoidOps = [];
98
+ globalTxIdWasAwaited = false;
99
+ _startTime = Date.now();
100
+ _stat = stat.initialTxStatWithoutTime();
101
+ get stat() {
102
+ return {
103
+ ...this._stat,
104
+ timeMs: Date.now() - this._startTime,
105
+ };
106
+ }
107
+ constructor(ll, name, writable, _clientRoot, finalPredicate, sharedResourceDataCache, enableFormattedErrors = false) {
108
+ this.ll = ll;
109
+ this.name = name;
110
+ this.writable = writable;
111
+ this._clientRoot = _clientRoot;
112
+ this.finalPredicate = finalPredicate;
113
+ this.sharedResourceDataCache = sharedResourceDataCache;
114
+ this.enableFormattedErrors = enableFormattedErrors;
115
+ // initiating transaction
116
+ this.globalTxId = this.sendSingleAndParse({
117
+ oneofKind: 'txOpen',
118
+ txOpen: {
119
+ name,
120
+ enableFormattedErrors,
121
+ writable: writable
122
+ ? api.TxAPI_Open_Request_WritableTx.WRITABLE
123
+ : api.TxAPI_Open_Request_WritableTx.NOT_WRITABLE,
124
+ },
125
+ }, (r) => tsHelpers.notEmpty(r.txOpen.tx?.id));
126
+ // To avoid floating promise
127
+ this.globalTxId.catch((err) => {
128
+ if (!this.globalTxIdWasAwaited) {
129
+ console.warn(err);
130
+ }
131
+ });
132
+ // Adding stats
133
+ this._stat.txCount++;
134
+ }
135
+ async drainAndAwaitPendingOps() {
136
+ if (this.pendingVoidOps.length === 0)
137
+ return;
138
+ // drain pending operations into temp array
139
+ const pending = this.pendingVoidOps;
140
+ this.pendingVoidOps = [];
141
+ // awaiting these pending operations first, to catch any errors
142
+ await Promise.all(pending);
143
+ }
144
+ async sendSingleAndParse(r, parser) {
145
+ // pushing operation packet to server
146
+ const rawResponsePromise = this.ll.send(r, false);
147
+ await this.drainAndAwaitPendingOps();
148
+ // awaiting our result, and parsing the response
149
+ return parser(await rawResponsePromise);
150
+ }
151
+ async sendMultiAndParse(r, parser) {
152
+ // pushing operation packet to server
153
+ const rawResponsePromise = this.ll.send(r, true);
154
+ await this.drainAndAwaitPendingOps();
155
+ // awaiting our result, and parsing the response
156
+ return parser(await rawResponsePromise);
157
+ }
158
+ async sendVoidSync(r) {
159
+ await this.ll.send(r, false);
160
+ }
161
+ /** Requests sent with this method should never produce recoverable errors */
162
+ sendVoidAsync(r) {
163
+ this.pendingVoidOps.push(this.sendVoidSync(r));
164
+ }
165
+ checkTxOpen() {
166
+ if (this._completed)
167
+ throw new Error('Transaction already closed');
168
+ }
169
+ get completed() {
170
+ return this._completed;
171
+ }
172
+ /** Commit & closes transaction. {@link TxCommitConflict} is thrown on
173
+ * commit conflicts. */
174
+ async commit() {
175
+ this.checkTxOpen();
176
+ // tx will accept no requests after this one
177
+ this._completed = true;
178
+ if (!this.writable) {
179
+ // no need to explicitly commit or reject read-only tx
180
+ const completeResult = this.ll.complete();
181
+ await this.drainAndAwaitPendingOps();
182
+ await completeResult;
183
+ await this.ll.await();
184
+ }
185
+ else {
186
+ // @TODO, also floating promises
187
+ const commitResponse = this.sendSingleAndParse({ oneofKind: 'txCommit', txCommit: {} }, (r) => r.txCommit.success);
188
+ // send closing frame right after commit to save some time on round-trips
189
+ const completeResult = this.ll.complete();
190
+ // now when we pushed all packets into the stream, we should wait for any
191
+ // pending void operations from before, to catch any errors
192
+ await this.drainAndAwaitPendingOps();
193
+ if (!(await commitResponse))
194
+ throw new TxCommitConflict();
195
+ await completeResult;
196
+ // await event-loop completion
197
+ await this.ll.await();
198
+ }
199
+ }
200
+ async discard() {
201
+ this.checkTxOpen();
202
+ // tx will accept no requests after this one
203
+ this._completed = true;
204
+ const discardResponse = this.sendVoidSync({ oneofKind: 'txDiscard', txDiscard: {} });
205
+ // send closing frame right after commit to save some time on round-trips
206
+ const completeResult = this.ll.complete();
207
+ // now when we pushed all packets into the stream, we should wait for any
208
+ // pending void operations from before, to catch any errors
209
+ await this.drainAndAwaitPendingOps();
210
+ await discardResponse;
211
+ await completeResult;
212
+ await this.ll.await();
213
+ }
214
+ //
215
+ // Main tx methods
216
+ //
217
+ get clientRoot() {
218
+ return types.ensureResourceIdNotNull(this._clientRoot);
219
+ }
220
+ //
221
+ // Resources
222
+ //
223
+ createSingleton(name, type, errorIfExists = false) {
224
+ const localId = this.nextLocalResourceId(false);
225
+ const globalId = this.sendSingleAndParse({
226
+ oneofKind: 'resourceCreateSingleton',
227
+ resourceCreateSingleton: {
228
+ type,
229
+ id: localId,
230
+ data: Buffer.from(name),
231
+ errorIfExists,
232
+ },
233
+ }, (r) => r.resourceCreateSingleton.resourceId);
234
+ return { globalId, localId };
235
+ }
236
+ async getSingleton(name, loadFields = true) {
237
+ return await this.sendSingleAndParse({
238
+ oneofKind: 'resourceGetSingleton',
239
+ resourceGetSingleton: {
240
+ data: Buffer.from(name),
241
+ loadFields,
242
+ },
243
+ }, (r) => type_conversion.protoToResource(tsHelpers.notEmpty(r.resourceGetSingleton.resource)));
244
+ }
245
+ createResource(root, req, parser) {
246
+ const localId = this.nextLocalResourceId(root);
247
+ const globalId = this.sendSingleAndParse(req(localId), (r) => parser(r));
248
+ return { globalId, localId };
249
+ }
250
+ createRoot(type) {
251
+ this._stat.rootsCreated++;
252
+ return this.createResource(true, (localId) => ({ oneofKind: 'resourceCreateRoot', resourceCreateRoot: { type, id: localId } }), (r) => r.resourceCreateRoot.resourceId);
253
+ }
254
+ createStruct(type, data) {
255
+ this._stat.structsCreated++;
256
+ this._stat.structsCreatedDataBytes += data?.length ?? 0;
257
+ return this.createResource(false, (localId) => ({
258
+ oneofKind: 'resourceCreateStruct',
259
+ resourceCreateStruct: {
260
+ type,
261
+ id: localId,
262
+ data: data === undefined ? undefined : typeof data === 'string' ? Buffer.from(data) : data,
263
+ },
264
+ }), (r) => r.resourceCreateStruct.resourceId);
265
+ }
266
+ createEphemeral(type, data) {
267
+ this._stat.ephemeralsCreated++;
268
+ this._stat.ephemeralsCreatedDataBytes += data?.length ?? 0;
269
+ return this.createResource(false, (localId) => ({
270
+ oneofKind: 'resourceCreateEphemeral',
271
+ resourceCreateEphemeral: {
272
+ type,
273
+ id: localId,
274
+ data: data === undefined ? undefined : typeof data === 'string' ? Buffer.from(data) : data,
275
+ },
276
+ }), (r) => r.resourceCreateEphemeral.resourceId);
277
+ }
278
+ createValue(type, data, errorIfExists = false) {
279
+ this._stat.valuesCreated++;
280
+ this._stat.valuesCreatedDataBytes += data?.length ?? 0;
281
+ return this.createResource(false, (localId) => ({
282
+ oneofKind: 'resourceCreateValue',
283
+ resourceCreateValue: {
284
+ type,
285
+ id: localId,
286
+ data: typeof data === 'string' ? Buffer.from(data) : data,
287
+ errorIfExists,
288
+ },
289
+ }), (r) => r.resourceCreateValue.resourceId);
290
+ }
291
+ createJsonValue(data) {
292
+ const jsonData = tsHelpers.canonicalJsonBytes(data);
293
+ return this.createValue(pl.JsonObject, jsonData, false);
294
+ }
295
+ createJsonGzValue(data, minSizeToGzip = 16_384) {
296
+ const { data: jsonData, isGzipped } = tsHelpers.canonicalJsonGzBytes(data, minSizeToGzip);
297
+ return this.createValue(isGzipped ? pl.JsonGzObject : pl.JsonObject, jsonData, false);
298
+ }
299
+ createError(message) {
300
+ return this.createValue(error_resource.ErrorResourceType, JSON.stringify({ message }));
301
+ }
302
+ setResourceName(name, rId) {
303
+ this.sendVoidAsync({
304
+ oneofKind: 'resourceNameSet',
305
+ resourceNameSet: { resourceId: toResourceId(rId), name },
306
+ });
307
+ }
308
+ deleteResourceName(name) {
309
+ this.sendVoidAsync({ oneofKind: 'resourceNameDelete', resourceNameDelete: { name } });
310
+ }
311
+ async getResourceByName(name) {
312
+ return await this.sendSingleAndParse({ oneofKind: 'resourceNameGet', resourceNameGet: { name } }, (r) => types.ensureResourceIdNotNull(r.resourceNameGet.resourceId));
313
+ }
314
+ async checkResourceNameExists(name) {
315
+ return await this.sendSingleAndParse({ oneofKind: 'resourceNameExists', resourceNameExists: { name } }, (r) => r.resourceNameExists.exists);
316
+ }
317
+ removeResource(rId) {
318
+ this.sendVoidAsync({ oneofKind: 'resourceRemove', resourceRemove: { id: rId } });
319
+ }
320
+ async resourceExists(rId) {
321
+ return await this.sendSingleAndParse({ oneofKind: 'resourceExists', resourceExists: { resourceId: rId } }, (r) => r.resourceExists.exists);
322
+ }
323
+ async getResourceData(rId, loadFields = true, ignoreCache = false) {
324
+ if (!ignoreCache && !isResourceRef(rId) && !types.isLocalResourceId(rId)) {
325
+ // checking if we can return result from cache
326
+ const fromCache = this.sharedResourceDataCache.get(rId);
327
+ if (fromCache && fromCache.cacheTxOpenTimestamp < this.txOpenTimestamp) {
328
+ if (!loadFields) {
329
+ this._stat.rGetDataCacheHits++;
330
+ this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;
331
+ return fromCache.basicData;
332
+ }
333
+ else if (fromCache.data) {
334
+ this._stat.rGetDataCacheHits++;
335
+ this._stat.rGetDataCacheBytes += fromCache.basicData.data?.length ?? 0;
336
+ this._stat.rGetDataCacheFields += fromCache.data.fields.length;
337
+ return fromCache.data;
338
+ }
339
+ }
340
+ }
341
+ const result = await this.sendSingleAndParse({
342
+ oneofKind: 'resourceGet',
343
+ resourceGet: { resourceId: toResourceId(rId), loadFields: loadFields },
344
+ }, (r) => type_conversion.protoToResource(tsHelpers.notEmpty(r.resourceGet.resource)));
345
+ this._stat.rGetDataNetRequests++;
346
+ this._stat.rGetDataNetBytes += result.data?.length ?? 0;
347
+ this._stat.rGetDataNetFields += result.fields.length;
348
+ // we will cache only final resource data states
349
+ // caching result even if we were ignore the cache
350
+ if (!isResourceRef(rId) && !types.isLocalResourceId(rId) && this.finalPredicate(result)) {
351
+ tsHelpers.deepFreeze(result);
352
+ const fromCache = this.sharedResourceDataCache.get(rId);
353
+ if (fromCache) {
354
+ if (loadFields && !fromCache.data) {
355
+ fromCache.data = result;
356
+ // updating timestamp becuse we updated the record
357
+ fromCache.cacheTxOpenTimestamp = this.txOpenTimestamp;
358
+ }
359
+ }
360
+ else {
361
+ const basicData = types.extractBasicResourceData(result);
362
+ tsHelpers.deepFreeze(basicData);
363
+ if (loadFields)
364
+ this.sharedResourceDataCache.set(rId, {
365
+ basicData,
366
+ data: result,
367
+ cacheTxOpenTimestamp: this.txOpenTimestamp,
368
+ });
369
+ else
370
+ this.sharedResourceDataCache.set(rId, {
371
+ basicData,
372
+ data: undefined,
373
+ cacheTxOpenTimestamp: this.txOpenTimestamp,
374
+ });
375
+ }
376
+ }
377
+ return result;
378
+ }
379
+ async getResourceDataIfExists(rId, loadFields = true) {
380
+ // calling this mehtod will ignore cache, because user intention is to detect resource absence
381
+ // which cache will prevent
382
+ const result = await notFoundToUndefined(async () => await this.getResourceData(rId, loadFields, true));
383
+ // cleaning cache record if resorce was removed from the db
384
+ if (result === undefined && !isResourceRef(rId) && !types.isLocalResourceId(rId))
385
+ this.sharedResourceDataCache.delete(rId);
386
+ return result;
387
+ }
388
+ /**
389
+ * Inform platform that resource will not get any new input fields.
390
+ * This is required, when client creates resource without schema and wants
391
+ * controller to start calculations.
392
+ * Most controllers will not start calculations even when all inputs
393
+ * have their values, if inputs list is not locked.
394
+ */
395
+ lockInputs(rId) {
396
+ this._stat.inputsLocked++;
397
+ this.sendVoidAsync({
398
+ oneofKind: 'resourceLockInputs',
399
+ resourceLockInputs: { resourceId: toResourceId(rId) },
400
+ });
401
+ }
402
+ /**
403
+ * Inform platform that resource will not get any new output fields.
404
+ * This is required for resource to pass deduplication.
405
+ */
406
+ lockOutputs(rId) {
407
+ this._stat.outputsLocked++;
408
+ this.sendVoidAsync({
409
+ oneofKind: 'resourceLockOutputs',
410
+ resourceLockOutputs: { resourceId: toResourceId(rId) },
411
+ });
412
+ }
413
+ lock(rID) {
414
+ this.lockInputs(rID);
415
+ this.lockOutputs(rID);
416
+ }
417
+ setResourceError(rId, ref) {
418
+ this.sendVoidAsync({
419
+ oneofKind: 'resourceSetError',
420
+ resourceSetError: { resourceId: toResourceId(rId), errorResourceId: toResourceId(ref) },
421
+ });
422
+ }
423
+ //
424
+ // Fields
425
+ //
426
+ createField(fId, fieldType, value) {
427
+ this._stat.fieldsCreated++;
428
+ this.sendVoidAsync({
429
+ oneofKind: 'fieldCreate',
430
+ fieldCreate: { type: type_conversion.fieldTypeToProto(fieldType), id: toFieldId(fId) },
431
+ });
432
+ if (value !== undefined)
433
+ this.setField(fId, value);
434
+ }
435
+ async fieldExists(fId) {
436
+ return await this.sendSingleAndParse({
437
+ oneofKind: 'fieldExists',
438
+ fieldExists: { field: toFieldId(fId) },
439
+ }, (r) => r.fieldExists.exists);
440
+ }
441
+ setField(fId, ref) {
442
+ this._stat.fieldsSet++;
443
+ if (isResource(ref))
444
+ this.sendVoidAsync({
445
+ oneofKind: 'fieldSet',
446
+ fieldSet: {
447
+ field: toFieldId(fId),
448
+ value: {
449
+ resourceId: toResourceId(ref),
450
+ fieldName: '', // default value, read as undefined
451
+ },
452
+ },
453
+ });
454
+ else
455
+ this.sendVoidAsync({
456
+ oneofKind: 'fieldSet',
457
+ fieldSet: {
458
+ field: toFieldId(fId),
459
+ value: toFieldId(ref),
460
+ },
461
+ });
462
+ }
463
+ setFieldError(fId, ref) {
464
+ this._stat.fieldsSet++;
465
+ this.sendVoidAsync({
466
+ oneofKind: 'fieldSetError',
467
+ fieldSetError: { field: toFieldId(fId), errResourceId: toResourceId(ref) },
468
+ });
469
+ }
470
+ async getField(fId) {
471
+ this._stat.fieldsGet++;
472
+ return await this.sendSingleAndParse({ oneofKind: 'fieldGet', fieldGet: { field: toFieldId(fId) } }, (r) => type_conversion.protoToField(tsHelpers.notEmpty(r.fieldGet.field)));
473
+ }
474
+ async getFieldIfExists(fId) {
475
+ return notFoundToUndefined(async () => await this.getField(fId));
476
+ }
477
+ resetField(fId) {
478
+ this.sendVoidAsync({ oneofKind: 'fieldReset', fieldReset: { field: toFieldId(fId) } });
479
+ }
480
+ removeField(fId) {
481
+ this.sendVoidAsync({ oneofKind: 'fieldRemove', fieldRemove: { field: toFieldId(fId) } });
482
+ }
483
+ //
484
+ // KV
485
+ //
486
+ async listKeyValues(rId) {
487
+ const result = await this.sendMultiAndParse({
488
+ oneofKind: 'resourceKeyValueList',
489
+ resourceKeyValueList: { resourceId: toResourceId(rId), startFrom: '', limit: 0 },
490
+ }, (r) => r.map((e) => e.resourceKeyValueList.record));
491
+ this._stat.kvListRequests++;
492
+ this._stat.kvListEntries += result.length;
493
+ for (const kv of result)
494
+ this._stat.kvListBytes += kv.key.length + kv.value.length;
495
+ return result;
496
+ }
497
+ async listKeyValuesString(rId) {
498
+ return (await this.listKeyValues(rId)).map(({ key, value }) => ({
499
+ key,
500
+ value: Buffer.from(value).toString(),
501
+ }));
502
+ }
503
+ async listKeyValuesIfResourceExists(rId) {
504
+ return notFoundToUndefined(async () => await this.listKeyValues(rId));
505
+ }
506
+ async listKeyValuesStringIfResourceExists(rId) {
507
+ return notFoundToUndefined(async () => await this.listKeyValuesString(rId));
508
+ }
509
+ setKValue(rId, key, value) {
510
+ this._stat.kvSetRequests++;
511
+ this._stat.kvSetBytes++;
512
+ this.sendVoidAsync({
513
+ oneofKind: 'resourceKeyValueSet',
514
+ resourceKeyValueSet: {
515
+ resourceId: toResourceId(rId),
516
+ key,
517
+ value: util.toBytes(value),
518
+ },
519
+ });
520
+ }
521
+ deleteKValue(rId, key) {
522
+ this.sendVoidAsync({
523
+ oneofKind: 'resourceKeyValueDelete',
524
+ resourceKeyValueDelete: {
525
+ resourceId: toResourceId(rId),
526
+ key,
527
+ },
528
+ });
529
+ }
530
+ async getKValue(rId, key) {
531
+ const result = await this.sendSingleAndParse({
532
+ oneofKind: 'resourceKeyValueGet',
533
+ resourceKeyValueGet: { resourceId: toResourceId(rId), key },
534
+ }, (r) => r.resourceKeyValueGet.value);
535
+ this._stat.kvGetRequests++;
536
+ this._stat.kvGetBytes += result.length;
537
+ return result;
538
+ }
539
+ async getKValueString(rId, key) {
540
+ return Buffer.from(await this.getKValue(rId, key)).toString();
541
+ }
542
+ async getKValueJson(rId, key) {
543
+ return JSON.parse(await this.getKValueString(rId, key));
544
+ }
545
+ async getKValueIfExists(rId, key) {
546
+ const result = await this.sendSingleAndParse({
547
+ oneofKind: 'resourceKeyValueGetIfExists',
548
+ resourceKeyValueGetIfExists: { resourceId: toResourceId(rId), key },
549
+ }, (r) => r.resourceKeyValueGetIfExists.exists ? r.resourceKeyValueGetIfExists.value : undefined);
550
+ this._stat.kvGetRequests++;
551
+ this._stat.kvGetBytes += result?.length ?? 0;
552
+ return result;
553
+ }
554
+ async getKValueStringIfExists(rId, key) {
555
+ const data = await this.getKValueIfExists(rId, key);
556
+ return data === undefined ? undefined : Buffer.from(data).toString();
557
+ }
558
+ async getKValueJsonIfExists(rId, key) {
559
+ const str = await this.getKValueString(rId, key);
560
+ if (str === undefined)
561
+ return undefined;
562
+ return JSON.parse(str);
563
+ }
564
+ //
565
+ // Cache
566
+ //
567
+ // TODO
568
+ //
569
+ // High level ops
570
+ //
571
+ /** Resolves existing or create first level resource from */
572
+ getFutureFieldValue(rId, fieldName, fieldType) {
573
+ const data = Buffer.from(JSON.stringify({ fieldName, fieldType }));
574
+ const getFieldResource = this.createEphemeral({ name: 'json/getField', version: '1' }, data);
575
+ this.setField({ resourceId: getFieldResource, fieldName: 'resource' }, rId);
576
+ return { resourceId: getFieldResource, fieldName: 'result' };
577
+ }
578
+ //
579
+ // Technical
580
+ //
581
+ async getGlobalTxId() {
582
+ this.globalTxIdWasAwaited = true;
583
+ return await this.globalTxId;
584
+ }
585
+ /** Closes output event stream */
586
+ async complete() {
587
+ if (this._completed)
588
+ return;
589
+ this._completed = true;
590
+ const completeResult = this.ll.complete();
591
+ await this.drainAndAwaitPendingOps();
592
+ await completeResult;
593
+ }
594
+ /** Await incoming message loop termination and throw
595
+ * any leftover errors if it was unsuccessful */
596
+ async await() {
597
+ await this.ll.await();
598
+ }
599
+ //
600
+ // Helpers
601
+ //
602
+ nextLocalResourceId(root) {
603
+ return types.createLocalResourceId(root, ++this.localResourceIdCounter, this.localTxId);
604
+ }
605
+ static localTxIdCounter = 0;
606
+ static nextLocalTxId() {
607
+ PlTransaction.localTxIdCounter++;
608
+ if (PlTransaction.localTxIdCounter === types.MaxTxId)
609
+ PlTransaction.localTxIdCounter = 1;
610
+ return PlTransaction.localTxIdCounter;
611
+ }
612
+ }
613
+
614
+ exports.PlTransaction = PlTransaction;
615
+ exports.TxCommitConflict = TxCommitConflict;
616
+ exports.field = field;
617
+ exports.isField = isField;
618
+ exports.isFieldRef = isFieldRef;
619
+ exports.isResource = isResource;
620
+ exports.isResourceId = isResourceId;
621
+ exports.isResourceRef = isResourceRef;
622
+ exports.toFieldId = toFieldId;
623
+ exports.toGlobalFieldId = toGlobalFieldId;
624
+ exports.toGlobalResourceId = toGlobalResourceId;
625
+ exports.toResourceId = toResourceId;
626
+ //# sourceMappingURL=transaction.cjs.map