@fluid-experimental/dds-interceptions 2.0.0-dev-rc.2.0.0.245554

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 (83) hide show
  1. package/.eslintrc.cjs +14 -0
  2. package/.mocharc.cjs +12 -0
  3. package/CHANGELOG.md +93 -0
  4. package/LICENSE +21 -0
  5. package/README.md +95 -0
  6. package/api-extractor-cjs.json +8 -0
  7. package/api-extractor-lint.json +4 -0
  8. package/api-extractor.json +4 -0
  9. package/api-report/dds-interceptions.api.md +24 -0
  10. package/dist/dds-interceptions-alpha.d.ts +13 -0
  11. package/dist/dds-interceptions-beta.d.ts +19 -0
  12. package/dist/dds-interceptions-public.d.ts +19 -0
  13. package/dist/dds-interceptions-untrimmed.d.ts +67 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +13 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/map/index.d.ts +7 -0
  19. package/dist/map/index.d.ts.map +1 -0
  20. package/dist/map/index.js +12 -0
  21. package/dist/map/index.js.map +1 -0
  22. package/dist/map/sharedDirectoryWithInterception.d.ts +29 -0
  23. package/dist/map/sharedDirectoryWithInterception.d.ts.map +1 -0
  24. package/dist/map/sharedDirectoryWithInterception.js +117 -0
  25. package/dist/map/sharedDirectoryWithInterception.js.map +1 -0
  26. package/dist/map/sharedMapWithInterception.d.ts +23 -0
  27. package/dist/map/sharedMapWithInterception.d.ts.map +1 -0
  28. package/dist/map/sharedMapWithInterception.js +49 -0
  29. package/dist/map/sharedMapWithInterception.js.map +1 -0
  30. package/dist/package.json +3 -0
  31. package/dist/sequence/index.d.ts +6 -0
  32. package/dist/sequence/index.d.ts.map +1 -0
  33. package/dist/sequence/index.js +10 -0
  34. package/dist/sequence/index.js.map +1 -0
  35. package/dist/sequence/sharedStringWithInterception.d.ts +27 -0
  36. package/dist/sequence/sharedStringWithInterception.d.ts.map +1 -0
  37. package/dist/sequence/sharedStringWithInterception.js +207 -0
  38. package/dist/sequence/sharedStringWithInterception.js.map +1 -0
  39. package/dist/tsdoc-metadata.json +11 -0
  40. package/lib/dds-interceptions-alpha.d.ts +13 -0
  41. package/lib/dds-interceptions-beta.d.ts +19 -0
  42. package/lib/dds-interceptions-public.d.ts +19 -0
  43. package/lib/dds-interceptions-untrimmed.d.ts +67 -0
  44. package/lib/index.d.ts +7 -0
  45. package/lib/index.d.ts.map +1 -0
  46. package/lib/index.js +7 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib/map/index.d.ts +7 -0
  49. package/lib/map/index.d.ts.map +1 -0
  50. package/lib/map/index.js +7 -0
  51. package/lib/map/index.js.map +1 -0
  52. package/lib/map/sharedDirectoryWithInterception.d.ts +29 -0
  53. package/lib/map/sharedDirectoryWithInterception.d.ts.map +1 -0
  54. package/lib/map/sharedDirectoryWithInterception.js +113 -0
  55. package/lib/map/sharedDirectoryWithInterception.js.map +1 -0
  56. package/lib/map/sharedMapWithInterception.d.ts +23 -0
  57. package/lib/map/sharedMapWithInterception.d.ts.map +1 -0
  58. package/lib/map/sharedMapWithInterception.js +45 -0
  59. package/lib/map/sharedMapWithInterception.js.map +1 -0
  60. package/lib/sequence/index.d.ts +6 -0
  61. package/lib/sequence/index.d.ts.map +1 -0
  62. package/lib/sequence/index.js +6 -0
  63. package/lib/sequence/index.js.map +1 -0
  64. package/lib/sequence/sharedStringWithInterception.d.ts +27 -0
  65. package/lib/sequence/sharedStringWithInterception.d.ts.map +1 -0
  66. package/lib/sequence/sharedStringWithInterception.js +203 -0
  67. package/lib/sequence/sharedStringWithInterception.js.map +1 -0
  68. package/lib/test/sharedDirectoryWithInterception.spec.js +282 -0
  69. package/lib/test/sharedDirectoryWithInterception.spec.js.map +1 -0
  70. package/lib/test/sharedMapWithInterception.spec.js +105 -0
  71. package/lib/test/sharedMapWithInterception.spec.js.map +1 -0
  72. package/lib/test/sharedStringWithInterception.spec.js +147 -0
  73. package/lib/test/sharedStringWithInterception.spec.js.map +1 -0
  74. package/package.json +151 -0
  75. package/prettier.config.cjs +8 -0
  76. package/src/index.ts +7 -0
  77. package/src/map/index.ts +7 -0
  78. package/src/map/sharedDirectoryWithInterception.ts +172 -0
  79. package/src/map/sharedMapWithInterception.ts +58 -0
  80. package/src/sequence/index.ts +6 -0
  81. package/src/sequence/sharedStringWithInterception.ts +288 -0
  82. package/tsconfig.cjs.json +7 -0
  83. package/tsconfig.json +9 -0
@@ -0,0 +1,288 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { assert } from "@fluidframework/core-utils";
7
+ import * as MergeTree from "@fluidframework/merge-tree";
8
+ import { SharedString } from "@fluidframework/sequence";
9
+ import { IFluidDataStoreContext } from "@fluidframework/runtime-definitions";
10
+
11
+ /**
12
+ * - Create a new object from the passed SharedString.
13
+ *
14
+ * - Modify the methods that insert / remove / annotate the properties of the SharedString to call
15
+ * the propertyInterceptionCallback to get new properties.
16
+ *
17
+ * - Use these new properties to call the underlying SharedString.
18
+ *
19
+ * - The propertyInterceptionCallback and the call to the underlying SharedString are wrapped around an
20
+ * orderSequentially call to batch any operations that might happen in the callback.
21
+ *
22
+ * @param sharedString - The underlying SharedString
23
+ * @param context - The IFluidDataStoreContext that will be used to call orderSequentially
24
+ * @param propertyInterceptionCallback - The interception callback to be called
25
+ *
26
+ * @returns A new SharedString that intercepts the methods modifying the SharedString properties.
27
+ * @internal
28
+ */
29
+ export function createSharedStringWithInterception(
30
+ sharedString: SharedString,
31
+ context: IFluidDataStoreContext,
32
+ propertyInterceptionCallback: (props?: MergeTree.PropertySet) => MergeTree.PropertySet,
33
+ ): SharedString {
34
+ const sharedStringWithInterception = Object.create(sharedString);
35
+
36
+ // executingCallback keeps track of whether a method on this wrapper object is called recursively
37
+ // from the propertyInterceptionCallback.
38
+ let executingCallback: boolean = false;
39
+
40
+ /**
41
+ * Inserts a marker at a relative position.
42
+ *
43
+ * @param relativePos1 - The relative position to insert the marker at
44
+ * @param refType - The reference type of the marker
45
+ * @param props - The properties of the marker
46
+ */
47
+ sharedStringWithInterception.insertMarkerRelative = (
48
+ relativePos1: MergeTree.IRelativePosition,
49
+ refType: MergeTree.ReferenceType,
50
+ props?: MergeTree.PropertySet,
51
+ ) => {
52
+ // Wrapper methods should not be called from the interception callback as this will lead to
53
+ // infinite recursion.
54
+ assert(
55
+ executingCallback === false,
56
+ 0x0c1 /* "Interception wrapper methods called recursively from the interception callback" */,
57
+ );
58
+
59
+ context.containerRuntime.orderSequentially(() => {
60
+ executingCallback = true;
61
+ try {
62
+ sharedString.insertMarkerRelative(
63
+ relativePos1,
64
+ refType,
65
+ propertyInterceptionCallback(props),
66
+ );
67
+ } finally {
68
+ executingCallback = false;
69
+ }
70
+ });
71
+ };
72
+
73
+ /**
74
+ * Inserts a marker at the position.
75
+ *
76
+ * @param pos - The position to insert the marker at
77
+ * @param refType - The reference type of the marker
78
+ * @param props - The properties of the marker
79
+ */
80
+ sharedStringWithInterception.insertMarker = (
81
+ pos: number,
82
+ refType: MergeTree.ReferenceType,
83
+ props?: MergeTree.PropertySet,
84
+ ) => {
85
+ let insertOp;
86
+ // Wrapper methods should not be called from the interception callback as this will lead to
87
+ // infinite recursion.
88
+ assert(
89
+ executingCallback === false,
90
+ 0x0c2 /* "Interception wrapper methods called recursively from the interception callback" */,
91
+ );
92
+
93
+ context.containerRuntime.orderSequentially(() => {
94
+ executingCallback = true;
95
+ try {
96
+ insertOp = sharedString.insertMarker(
97
+ pos,
98
+ refType,
99
+ propertyInterceptionCallback(props),
100
+ );
101
+ } finally {
102
+ executingCallback = false;
103
+ }
104
+ });
105
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
106
+ return insertOp;
107
+ };
108
+
109
+ /**
110
+ * Inserts the text at a relative position.
111
+ *
112
+ * @param relativePos1 - The relative position to insert the text at
113
+ * @param text - The text to insert
114
+ * @param props - The properties of text
115
+ */
116
+ sharedStringWithInterception.insertTextRelative = (
117
+ relativePos1: MergeTree.IRelativePosition,
118
+ text: string,
119
+ props?: MergeTree.PropertySet,
120
+ ) => {
121
+ // Wrapper methods should not be called from the interception callback as this will lead to
122
+ // infinite recursion.
123
+ assert(
124
+ executingCallback === false,
125
+ 0x0c3 /* "Interception wrapper methods called recursively from the interception callback" */,
126
+ );
127
+
128
+ context.containerRuntime.orderSequentially(() => {
129
+ executingCallback = true;
130
+ try {
131
+ sharedString.insertTextRelative(
132
+ relativePos1,
133
+ text,
134
+ propertyInterceptionCallback(props),
135
+ );
136
+ } finally {
137
+ executingCallback = false;
138
+ }
139
+ });
140
+ };
141
+
142
+ /**
143
+ * Inserts the text at the position.
144
+ *
145
+ * @param pos - The position to insert the text at
146
+ * @param text - The text to insert
147
+ * @param props - The properties of text
148
+ */
149
+ sharedStringWithInterception.insertText = (
150
+ pos: number,
151
+ text: string,
152
+ props?: MergeTree.PropertySet,
153
+ ) => {
154
+ // Wrapper methods should not be called from the interception callback as this will lead to
155
+ // infinite recursion.
156
+ assert(
157
+ executingCallback === false,
158
+ 0x0c4 /* "Interception wrapper methods called recursively from the interception callback" */,
159
+ );
160
+
161
+ context.containerRuntime.orderSequentially(() => {
162
+ executingCallback = true;
163
+ try {
164
+ sharedString.insertText(pos, text, propertyInterceptionCallback(props));
165
+ } finally {
166
+ executingCallback = false;
167
+ }
168
+ });
169
+ };
170
+
171
+ /**
172
+ * Replaces a range with the provided text.
173
+ *
174
+ * @param start - The inclusive start of the range to replace
175
+ * @param end - The exclusive end of the range to replace
176
+ * @param text - The text to replace the range with
177
+ * @param props - Optional. The properties of the replacement text
178
+ */
179
+ sharedStringWithInterception.replaceText = (
180
+ start: number,
181
+ end: number,
182
+ text: string,
183
+ props?: MergeTree.PropertySet,
184
+ ) => {
185
+ // Wrapper methods should not be called from the interception callback as this will lead to
186
+ // infinite recursion.
187
+ assert(
188
+ executingCallback === false,
189
+ 0x0c5 /* "Interception wrapper methods called recursively from the interception callback" */,
190
+ );
191
+
192
+ context.containerRuntime.orderSequentially(() => {
193
+ executingCallback = true;
194
+ try {
195
+ sharedString.replaceText(start, end, text, propertyInterceptionCallback(props));
196
+ } finally {
197
+ executingCallback = false;
198
+ }
199
+ });
200
+ };
201
+
202
+ /**
203
+ * Annotates the marker with the provided properties.
204
+ *
205
+ * @param marker - The marker to annotate
206
+ * @param props - The properties to annotate the marker with
207
+ */
208
+ sharedStringWithInterception.annotateMarker = (
209
+ marker: MergeTree.Marker,
210
+ props: MergeTree.PropertySet,
211
+ ) => {
212
+ // Wrapper methods should not be called from the interception callback as this will lead to
213
+ // infinite recursion.
214
+ assert(
215
+ executingCallback === false,
216
+ 0x0c7 /* "Interception wrapper methods called recursively from the interception callback" */,
217
+ );
218
+
219
+ context.containerRuntime.orderSequentially(() => {
220
+ executingCallback = true;
221
+ try {
222
+ sharedString.annotateMarker(marker, propertyInterceptionCallback(props));
223
+ } finally {
224
+ executingCallback = false;
225
+ }
226
+ });
227
+ };
228
+
229
+ /**
230
+ * Annotates the range with the provided properties.
231
+ *
232
+ * @param start - The inclusive start position of the range to annotate
233
+ * @param end - The exclusive end position of the range to annotate
234
+ * @param props - The properties to annotate the range with
235
+ *
236
+ */
237
+ sharedStringWithInterception.annotateRange = (
238
+ start: number,
239
+ end: number,
240
+ props: MergeTree.PropertySet,
241
+ ) => {
242
+ // Wrapper methods should not be called from the interception callback as this will lead to
243
+ // infinite recursion.
244
+ assert(
245
+ executingCallback === false,
246
+ 0x0c8 /* "Interception wrapper methods called recursively from the interception callback" */,
247
+ );
248
+
249
+ context.containerRuntime.orderSequentially(() => {
250
+ executingCallback = true;
251
+ try {
252
+ sharedString.annotateRange(start, end, propertyInterceptionCallback(props));
253
+ } finally {
254
+ executingCallback = false;
255
+ }
256
+ });
257
+ };
258
+
259
+ /**
260
+ * Inserts the segment at the given position
261
+ *
262
+ * @param pos - The position to insert the segment at
263
+ * @param segment - The segment to insert
264
+ */
265
+ sharedStringWithInterception.insertAtReferencePosition = (
266
+ pos: MergeTree.ReferencePosition,
267
+ segment: MergeTree.TextSegment,
268
+ ) => {
269
+ // Wrapper methods should not be called from the interception callback as this will lead to
270
+ // infinite recursion.
271
+ assert(
272
+ executingCallback === false,
273
+ 0x0c9 /* "Interception wrapper methods called recursively from the interception callback" */,
274
+ );
275
+
276
+ context.containerRuntime.orderSequentially(() => {
277
+ executingCallback = true;
278
+ try {
279
+ segment.properties = propertyInterceptionCallback(segment.properties);
280
+ sharedString.insertAtReferencePosition(pos, segment);
281
+ } finally {
282
+ executingCallback = false;
283
+ }
284
+ });
285
+ };
286
+
287
+ return sharedStringWithInterception as SharedString;
288
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ // This config must be used in a "type": "commonjs" environment. (Use fluid-tsc commonjs.)
3
+ "extends": "./tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "./dist",
6
+ },
7
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../../common/build/build-common/tsconfig.node16.json",
3
+ "include": ["src/**/*"],
4
+ "exclude": ["src/test/**/*"],
5
+ "compilerOptions": {
6
+ "rootDir": "./src",
7
+ "outDir": "./lib",
8
+ },
9
+ }