@fluidframework/driver-base 2.0.0-dev.4.4.0.162574 → 2.0.0-dev.5.3.2.178189
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.
- package/.eslintrc.js +3 -0
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +20 -0
- package/dist/documentDeltaConnection.d.ts +7 -4
- package/dist/documentDeltaConnection.d.ts.map +1 -1
- package/dist/documentDeltaConnection.js +51 -59
- package/dist/documentDeltaConnection.js.map +1 -1
- package/dist/driverUtils.d.ts +3 -0
- package/dist/driverUtils.d.ts.map +1 -1
- package/dist/driverUtils.js +40 -1
- package/dist/driverUtils.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/documentDeltaConnection.d.ts +7 -4
- package/lib/documentDeltaConnection.d.ts.map +1 -1
- package/lib/documentDeltaConnection.js +51 -59
- package/lib/documentDeltaConnection.js.map +1 -1
- package/lib/driverUtils.d.ts +3 -0
- package/lib/driverUtils.d.ts.map +1 -1
- package/lib/driverUtils.js +38 -0
- package/lib/driverUtils.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +56 -16
- package/src/documentDeltaConnection.ts +83 -73
- package/src/driverUtils.ts +49 -0
- package/src/index.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/tsconfig.json +2 -1
- package/lib/test/types/validateDriverBasePrevious.generated.d.ts +0 -2
- package/lib/test/types/validateDriverBasePrevious.generated.d.ts.map +0 -1
- package/lib/test/types/validateDriverBasePrevious.generated.js +0 -6
- package/lib/test/types/validateDriverBasePrevious.generated.js.map +0 -1
package/lib/driverUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driverUtils.js","sourceRoot":"","sources":["../src/driverUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { performance } from \"@fluidframework/common-utils\";\n\n/**\n * Extract and return the w3c data.\n * @param url - request url for which w3c data needs to be reported.\n * @param initiatorType - type of the network call\n */\nexport function getW3CData(url: string, initiatorType: string) {\n\t// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming\n\t// fetchStart: immediately before the browser starts to fetch the resource.\n\t// requestStart: immediately before the browser starts requesting the resource from the server\n\t// responseStart: immediately after the browser receives the first byte of the response from the server.\n\t// responseEnd: immediately after the browser receives the last byte of the resource\n\t// or immediately before the transport connection is closed, whichever comes first.\n\t// secureConnectionStart: immediately before the browser starts the handshake process to secure the\n\t// current connection. If a secure connection is not used, this property returns zero.\n\t// startTime: Time when the resource fetch started. This value is equivalent to fetchStart.\n\t// domainLookupStart: immediately before the browser starts the domain name lookup for the resource.\n\t// domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.\n\t// redirectStart: start time of the fetch which that initiates the redirect.\n\t// redirectEnd: immediately after receiving the last byte of the response of the last redirect.\n\n\t// Interval between start and finish of the domain name lookup for the resource.\n\tlet dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart\n\t// Interval between the first fetch until the last byte of the last redirect.\n\tlet redirectTime: number | undefined; // redirectEnd - redirectStart\n\t// Time to establish the connection to the server to retrieve the resource.\n\tlet tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n\t// Time from the end of the connection until the inital handshake process to secure the connection.\n\t// If 0, then no time is spent here.\n\tlet secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart\n\t// Interval to receive all (first to last) bytes form the server.\n\tlet responseNetworkTime: number | undefined; // responsEnd - responseStart\n\t// Interval between the initial fetch until the last byte is received.\n\t// Likely same as fetchTime + receiveContentTime.\n\tlet fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart\n\t// reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>\n\t// Interval between starting the request for the resource until receiving the last byte.\n\tlet reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart\n\tlet w3cStartTime: number | undefined; // W3C Start time = fetchStart time\n\n\t// getEntriesByType is only available in browser performance object\n\tconst resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n\t// Usually the latest fetch call is to the end of resources, so we start from the end.\n\tfor (let i = resources1.length - 1; i > 0; i--) {\n\t\tconst indResTime = resources1[i] as PerformanceResourceTiming;\n\t\tconst resource_name = indResTime.name.toString();\n\t\tconst resource_initiatortype = indResTime.initiatorType;\n\t\tif (\n\t\t\tresource_initiatortype.localeCompare(initiatorType) === 0 &&\n\t\t\tresource_name.includes(url)\n\t\t) {\n\t\t\tredirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n\t\t\tw3cStartTime = indResTime.fetchStart;\n\t\t\tdnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n\t\t\ttcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n\t\t\tsecureConnectionTime =\n\t\t\t\tindResTime.secureConnectionStart > 0\n\t\t\t\t\t? indResTime.connectEnd - indResTime.secureConnectionStart\n\t\t\t\t\t: 0;\n\t\t\tresponseNetworkTime =\n\t\t\t\tindResTime.responseStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.responseStart\n\t\t\t\t\t: undefined;\n\t\t\tfetchStartToResponseEndTime =\n\t\t\t\tindResTime.fetchStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.fetchStart\n\t\t\t\t\t: undefined;\n\t\t\treqStartToResponseEndTime =\n\t\t\t\tindResTime.requestStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.requestStart\n\t\t\t\t\t: undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn {\n\t\tdnsLookupTime,\n\t\tw3cStartTime,\n\t\tredirectTime,\n\t\ttcpHandshakeTime,\n\t\tsecureConnectionTime,\n\t\tresponseNetworkTime,\n\t\tfetchStartToResponseEndTime,\n\t\treqStartToResponseEndTime,\n\t};\n}\n\n/*\n * An implementation of Promise.race that gives you the winner of the promise race.\n * If one of the promises is rejected before any other is resolved, this method will return the error/reason from that rejection.\n */\nexport async function promiseRaceWithWinner<T>(\n\tpromises: Promise<T>[],\n): Promise<{ index: number; value: T }> {\n\treturn new Promise((resolve, reject) => {\n\t\tpromises.forEach((p, index) => {\n\t\t\tp.then((v) => resolve({ index, value: v })).catch(reject);\n\t\t});\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"driverUtils.js","sourceRoot":"","sources":["../src/driverUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { performance } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\n\n/**\n * Extract and return the w3c data.\n * @param url - request url for which w3c data needs to be reported.\n * @param initiatorType - type of the network call\n */\nexport function getW3CData(url: string, initiatorType: string) {\n\t// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming\n\t// fetchStart: immediately before the browser starts to fetch the resource.\n\t// requestStart: immediately before the browser starts requesting the resource from the server\n\t// responseStart: immediately after the browser receives the first byte of the response from the server.\n\t// responseEnd: immediately after the browser receives the last byte of the resource\n\t// or immediately before the transport connection is closed, whichever comes first.\n\t// secureConnectionStart: immediately before the browser starts the handshake process to secure the\n\t// current connection. If a secure connection is not used, this property returns zero.\n\t// startTime: Time when the resource fetch started. This value is equivalent to fetchStart.\n\t// domainLookupStart: immediately before the browser starts the domain name lookup for the resource.\n\t// domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.\n\t// redirectStart: start time of the fetch which that initiates the redirect.\n\t// redirectEnd: immediately after receiving the last byte of the response of the last redirect.\n\n\t// Interval between start and finish of the domain name lookup for the resource.\n\tlet dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart\n\t// Interval between the first fetch until the last byte of the last redirect.\n\tlet redirectTime: number | undefined; // redirectEnd - redirectStart\n\t// Time to establish the connection to the server to retrieve the resource.\n\tlet tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n\t// Time from the end of the connection until the inital handshake process to secure the connection.\n\t// If 0, then no time is spent here.\n\tlet secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart\n\t// Interval to receive all (first to last) bytes form the server.\n\tlet responseNetworkTime: number | undefined; // responsEnd - responseStart\n\t// Interval between the initial fetch until the last byte is received.\n\t// Likely same as fetchTime + receiveContentTime.\n\tlet fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart\n\t// reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>\n\t// Interval between starting the request for the resource until receiving the last byte.\n\tlet reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart\n\tlet w3cStartTime: number | undefined; // W3C Start time = fetchStart time\n\n\t// getEntriesByType is only available in browser performance object\n\tconst resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n\t// Usually the latest fetch call is to the end of resources, so we start from the end.\n\tfor (let i = resources1.length - 1; i > 0; i--) {\n\t\tconst indResTime = resources1[i] as PerformanceResourceTiming;\n\t\tconst resource_name = indResTime.name.toString();\n\t\tconst resource_initiatortype = indResTime.initiatorType;\n\t\tif (\n\t\t\tresource_initiatortype.localeCompare(initiatorType) === 0 &&\n\t\t\tresource_name.includes(url)\n\t\t) {\n\t\t\tredirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n\t\t\tw3cStartTime = indResTime.fetchStart;\n\t\t\tdnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n\t\t\ttcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n\t\t\tsecureConnectionTime =\n\t\t\t\tindResTime.secureConnectionStart > 0\n\t\t\t\t\t? indResTime.connectEnd - indResTime.secureConnectionStart\n\t\t\t\t\t: 0;\n\t\t\tresponseNetworkTime =\n\t\t\t\tindResTime.responseStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.responseStart\n\t\t\t\t\t: undefined;\n\t\t\tfetchStartToResponseEndTime =\n\t\t\t\tindResTime.fetchStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.fetchStart\n\t\t\t\t\t: undefined;\n\t\t\treqStartToResponseEndTime =\n\t\t\t\tindResTime.requestStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.requestStart\n\t\t\t\t\t: undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn {\n\t\tdnsLookupTime,\n\t\tw3cStartTime,\n\t\tredirectTime,\n\t\ttcpHandshakeTime,\n\t\tsecureConnectionTime,\n\t\tresponseNetworkTime,\n\t\tfetchStartToResponseEndTime,\n\t\treqStartToResponseEndTime,\n\t};\n}\n\n/*\n * An implementation of Promise.race that gives you the winner of the promise race.\n * If one of the promises is rejected before any other is resolved, this method will return the error/reason from that rejection.\n */\nexport async function promiseRaceWithWinner<T>(\n\tpromises: Promise<T>[],\n): Promise<{ index: number; value: T }> {\n\treturn new Promise((resolve, reject) => {\n\t\tpromises.forEach((p, index) => {\n\t\t\tp.then((v) => resolve({ index, value: v })).catch(reject);\n\t\t});\n\t});\n}\n\nexport function validateMessages(\n\treason: string,\n\tmessages: ISequencedDocumentMessage[],\n\tfrom: number,\n\tlogger: ITelemetryLoggerExt,\n\tstrict: boolean = true,\n) {\n\tif (messages.length !== 0) {\n\t\tconst start = messages[0].sequenceNumber;\n\t\tconst length = messages.length;\n\t\tconst last = messages[length - 1].sequenceNumber;\n\t\tif (last + 1 !== from + length) {\n\t\t\t// If not strict, then return the first consecutive sub-block. If strict or start\n\t\t\t// seq number is not what we expected, then return no ops.\n\t\t\tif (strict || from !== start) {\n\t\t\t\tmessages.length = 0;\n\t\t\t} else {\n\t\t\t\tlet validOpsCount = 1;\n\t\t\t\twhile (\n\t\t\t\t\tvalidOpsCount < messages.length &&\n\t\t\t\t\tmessages[validOpsCount].sequenceNumber ===\n\t\t\t\t\t\tmessages[validOpsCount - 1].sequenceNumber + 1\n\t\t\t\t) {\n\t\t\t\t\tvalidOpsCount++;\n\t\t\t\t}\n\t\t\t\tmessages.length = validOpsCount;\n\t\t\t}\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"OpsFetchViolation\",\n\t\t\t\treason,\n\t\t\t\tfrom,\n\t\t\t\tstart,\n\t\t\t\tlast,\n\t\t\t\tlength,\n\t\t\t\tdetails: JSON.stringify({\n\t\t\t\t\tvalidLength: messages.length,\n\t\t\t\t\tlastValidOpSeqNumber:\n\t\t\t\t\t\tmessages.length > 0\n\t\t\t\t\t\t\t? messages[messages.length - 1].sequenceNumber\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\tstrict,\n\t\t\t\t}),\n\t\t\t});\n\t\t}\n\t}\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
export { DocumentDeltaConnection } from "./documentDeltaConnection";
|
|
6
|
-
export { getW3CData, promiseRaceWithWinner } from "./driverUtils";
|
|
6
|
+
export { getW3CData, promiseRaceWithWinner, validateMessages } from "./driverUtils";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
export { DocumentDeltaConnection } from "./documentDeltaConnection";
|
|
6
|
-
export { getW3CData, promiseRaceWithWinner } from "./driverUtils";
|
|
6
|
+
export { getW3CData, promiseRaceWithWinner, validateMessages } from "./driverUtils";
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { DocumentDeltaConnection } from \"./documentDeltaConnection\";\nexport { getW3CData, promiseRaceWithWinner } from \"./driverUtils\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { DocumentDeltaConnection } from \"./documentDeltaConnection\";\nexport { getW3CData, promiseRaceWithWinner, validateMessages } from \"./driverUtils\";\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/driver-base";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-dev.5.3.2.178189";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/driver-base";
|
|
8
|
-
export const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export const pkgVersion = "2.0.0-dev.5.3.2.178189";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-base\";\nexport const pkgVersion = \"2.0.0-dev.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-base\";\nexport const pkgVersion = \"2.0.0-dev.5.3.2.178189\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/driver-base",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.5.3.2.178189",
|
|
4
4
|
"description": "Shared driver code for Fluid driver implementations",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -14,42 +14,77 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"module": "lib/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
|
+
"nyc": {
|
|
18
|
+
"all": true,
|
|
19
|
+
"cache-dir": "nyc/.cache",
|
|
20
|
+
"exclude": [
|
|
21
|
+
"src/test/**/*.ts",
|
|
22
|
+
"dist/test/**/*.js"
|
|
23
|
+
],
|
|
24
|
+
"exclude-after-remap": false,
|
|
25
|
+
"include": [
|
|
26
|
+
"src/**/*.ts",
|
|
27
|
+
"dist/**/*.js"
|
|
28
|
+
],
|
|
29
|
+
"report-dir": "nyc/report",
|
|
30
|
+
"reporter": [
|
|
31
|
+
"cobertura",
|
|
32
|
+
"html",
|
|
33
|
+
"text"
|
|
34
|
+
],
|
|
35
|
+
"temp-directory": "nyc/.nyc_output"
|
|
36
|
+
},
|
|
17
37
|
"dependencies": {
|
|
18
|
-
"@fluidframework/common-definitions": "^0.20.1",
|
|
19
38
|
"@fluidframework/common-utils": "^1.1.1",
|
|
20
|
-
"@fluidframework/
|
|
21
|
-
"@fluidframework/driver-
|
|
39
|
+
"@fluidframework/core-interfaces": "2.0.0-dev.5.3.2.178189",
|
|
40
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.5.3.2.178189",
|
|
41
|
+
"@fluidframework/driver-utils": "2.0.0-dev.5.3.2.178189",
|
|
22
42
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
23
|
-
"@fluidframework/telemetry-utils": "2.0.0-dev.
|
|
43
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.5.3.2.178189"
|
|
24
44
|
},
|
|
25
45
|
"devDependencies": {
|
|
26
|
-
"@fluid-tools/build-cli": "^0.
|
|
27
|
-
"@fluidframework/build-common": "^1.
|
|
28
|
-
"@fluidframework/build-tools": "^0.
|
|
29
|
-
"@fluidframework/driver-base-previous": "npm:@fluidframework/driver-base@2.0.0-internal.
|
|
46
|
+
"@fluid-tools/build-cli": "^0.21.0",
|
|
47
|
+
"@fluidframework/build-common": "^1.2.0",
|
|
48
|
+
"@fluidframework/build-tools": "^0.21.0",
|
|
49
|
+
"@fluidframework/driver-base-previous": "npm:@fluidframework/driver-base@2.0.0-internal.5.2.0",
|
|
30
50
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
51
|
+
"@fluidframework/mocha-test-setup": "2.0.0-dev.5.3.2.178189",
|
|
31
52
|
"@microsoft/api-extractor": "^7.34.4",
|
|
53
|
+
"@types/mocha": "^9.1.1",
|
|
32
54
|
"@types/node": "^14.18.38",
|
|
33
55
|
"concurrently": "^7.6.0",
|
|
34
56
|
"copyfiles": "^2.4.1",
|
|
57
|
+
"cross-env": "^7.0.3",
|
|
35
58
|
"eslint": "~8.6.0",
|
|
59
|
+
"mocha": "^10.2.0",
|
|
60
|
+
"mocha-json-output-reporter": "^2.0.1",
|
|
61
|
+
"mocha-multi-reporters": "^1.5.1",
|
|
62
|
+
"moment": "^2.21.0",
|
|
63
|
+
"nyc": "^15.1.0",
|
|
36
64
|
"prettier": "~2.6.2",
|
|
37
65
|
"rimraf": "^4.4.0",
|
|
38
|
-
"socket.io-client": "^4.
|
|
66
|
+
"socket.io-client": "^4.6.1",
|
|
39
67
|
"typescript": "~4.5.5"
|
|
40
68
|
},
|
|
69
|
+
"fluidBuild": {
|
|
70
|
+
"tasks": {
|
|
71
|
+
"tsc": [
|
|
72
|
+
"...",
|
|
73
|
+
"typetests:gen"
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
41
77
|
"typeValidation": {
|
|
42
78
|
"broken": {}
|
|
43
79
|
},
|
|
44
80
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"build:commonjs": "
|
|
47
|
-
"build:compile": "
|
|
81
|
+
"build": "fluid-build . --task build",
|
|
82
|
+
"build:commonjs": "fluid-build . --task commonjs",
|
|
83
|
+
"build:compile": "fluid-build . --task compile",
|
|
48
84
|
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
49
85
|
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
50
|
-
"build:full": "npm run build",
|
|
51
|
-
"build:full:compile": "npm run build:compile",
|
|
52
86
|
"build:genver": "gen-version",
|
|
87
|
+
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
53
88
|
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
54
89
|
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
55
90
|
"eslint": "eslint --format stylish src",
|
|
@@ -59,8 +94,13 @@
|
|
|
59
94
|
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
60
95
|
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
61
96
|
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
97
|
+
"test": "npm run test:mocha",
|
|
98
|
+
"test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
|
|
99
|
+
"test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
|
|
100
|
+
"test:mocha:multireport": "cross-env FLUID_TEST_MULTIREPORT=1 npm run test:mocha",
|
|
101
|
+
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
62
102
|
"tsc": "tsc",
|
|
63
103
|
"typetests:gen": "fluid-type-test-generator",
|
|
64
|
-
"typetests:prepare": "flub
|
|
104
|
+
"typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
|
|
65
105
|
}
|
|
66
106
|
}
|
|
@@ -22,8 +22,9 @@ import {
|
|
|
22
22
|
ITokenClaims,
|
|
23
23
|
ScopeType,
|
|
24
24
|
} from "@fluidframework/protocol-definitions";
|
|
25
|
-
import { IDisposable,
|
|
25
|
+
import { IDisposable, ITelemetryProperties } from "@fluidframework/core-interfaces";
|
|
26
26
|
import {
|
|
27
|
+
ITelemetryLoggerExt,
|
|
27
28
|
ChildLogger,
|
|
28
29
|
extractLogSafeErrorProperties,
|
|
29
30
|
getCircularReplacer,
|
|
@@ -72,6 +73,8 @@ export class DocumentDeltaConnection
|
|
|
72
73
|
|
|
73
74
|
private _details: IConnected | undefined;
|
|
74
75
|
|
|
76
|
+
private trackLatencyTimeout: number | undefined;
|
|
77
|
+
|
|
75
78
|
// Listeners only needed while the connection is in progress
|
|
76
79
|
private readonly connectionListeners: Map<string, (...args: any[]) => void> = new Map();
|
|
77
80
|
// Listeners used throughout the lifetime of the DocumentDeltaConnection
|
|
@@ -82,21 +85,10 @@ export class DocumentDeltaConnection
|
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
public get disposed() {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
(Error as any).stackTraceLimit = 50;
|
|
90
|
-
assert(
|
|
91
|
-
this._disposed || this.socket.connected,
|
|
92
|
-
0x244 /* "Socket is closed, but connection is not!" */,
|
|
93
|
-
);
|
|
94
|
-
} catch (error) {
|
|
95
|
-
const normalizedError = this.addPropsToError(error);
|
|
96
|
-
throw normalizedError;
|
|
97
|
-
} finally {
|
|
98
|
-
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
|
99
|
-
}
|
|
88
|
+
assert(
|
|
89
|
+
this._disposed || this.socket.connected,
|
|
90
|
+
0x244 /* "Socket is closed, but connection is not!" */,
|
|
91
|
+
);
|
|
100
92
|
return this._disposed;
|
|
101
93
|
}
|
|
102
94
|
|
|
@@ -110,7 +102,7 @@ export class DocumentDeltaConnection
|
|
|
110
102
|
/**
|
|
111
103
|
* @deprecated Implementors should manage their own logger or monitoring context
|
|
112
104
|
*/
|
|
113
|
-
protected get logger():
|
|
105
|
+
protected get logger(): ITelemetryLoggerExt {
|
|
114
106
|
return this.mc.logger;
|
|
115
107
|
}
|
|
116
108
|
|
|
@@ -130,11 +122,12 @@ export class DocumentDeltaConnection
|
|
|
130
122
|
protected constructor(
|
|
131
123
|
protected readonly socket: Socket,
|
|
132
124
|
public documentId: string,
|
|
133
|
-
logger:
|
|
125
|
+
logger: ITelemetryLoggerExt,
|
|
134
126
|
private readonly enableLongPollingDowngrades: boolean = false,
|
|
135
127
|
protected readonly connectionId?: string,
|
|
136
128
|
) {
|
|
137
129
|
super((name, error) => {
|
|
130
|
+
this.addPropsToError(error);
|
|
138
131
|
logger.sendErrorEvent(
|
|
139
132
|
{
|
|
140
133
|
eventName: "DeltaConnection:EventException",
|
|
@@ -146,7 +139,7 @@ export class DocumentDeltaConnection
|
|
|
146
139
|
|
|
147
140
|
this.mc = loggerToMonitoringContext(ChildLogger.create(logger, "DeltaConnection"));
|
|
148
141
|
|
|
149
|
-
this.on("newListener", (event,
|
|
142
|
+
this.on("newListener", (event, _listener) => {
|
|
150
143
|
assert(!this.disposed, 0x20a /* "register for event on disposed object" */);
|
|
151
144
|
|
|
152
145
|
// Some events are already forwarded - see this.addTrackedListener() calls in initialize().
|
|
@@ -169,9 +162,29 @@ export class DocumentDeltaConnection
|
|
|
169
162
|
0x20b /* "mismatch" */,
|
|
170
163
|
);
|
|
171
164
|
if (!this.trackedListeners.has(event)) {
|
|
172
|
-
|
|
173
|
-
this
|
|
174
|
-
|
|
165
|
+
if (event === "pong") {
|
|
166
|
+
// Empty callback for tracking purposes in this class
|
|
167
|
+
this.trackedListeners.set("pong", () => {});
|
|
168
|
+
|
|
169
|
+
const sendPingLoop = () => {
|
|
170
|
+
const start = Date.now();
|
|
171
|
+
|
|
172
|
+
this.socket.volatile?.emit("ping", () => {
|
|
173
|
+
this.emit("pong", Date.now() - start);
|
|
174
|
+
|
|
175
|
+
// Schedule another ping event in 1 minute
|
|
176
|
+
this.trackLatencyTimeout = setTimeout(() => {
|
|
177
|
+
sendPingLoop();
|
|
178
|
+
}, 1000 * 60);
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
sendPingLoop();
|
|
183
|
+
} else {
|
|
184
|
+
this.addTrackedListener(event, (...args: any[]) => {
|
|
185
|
+
this.emit(event, ...args);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
175
188
|
}
|
|
176
189
|
});
|
|
177
190
|
}
|
|
@@ -236,18 +249,7 @@ export class DocumentDeltaConnection
|
|
|
236
249
|
}
|
|
237
250
|
|
|
238
251
|
private checkNotDisposed() {
|
|
239
|
-
|
|
240
|
-
// We are seeing this in telemetry and we are unable to figure out why it is happening, so this should help.
|
|
241
|
-
const originalStackTraceLimit = (Error as any).stackTraceLimit;
|
|
242
|
-
try {
|
|
243
|
-
(Error as any).stackTraceLimit = 50;
|
|
244
|
-
assert(!this.disposed, 0x20c /* "connection disposed" */);
|
|
245
|
-
} catch (error) {
|
|
246
|
-
const normalizedError = this.addPropsToError(error);
|
|
247
|
-
throw normalizedError;
|
|
248
|
-
} finally {
|
|
249
|
-
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
|
250
|
-
}
|
|
252
|
+
assert(!this.disposed, 0x20c /* "connection disposed" */);
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
/**
|
|
@@ -341,17 +343,6 @@ export class DocumentDeltaConnection
|
|
|
341
343
|
private closeSocket(error: IAnyDriverError) {
|
|
342
344
|
if (this._disposed) {
|
|
343
345
|
// This would be rare situation due to complexity around socket emitting events.
|
|
344
|
-
this.logger.sendTelemetryEvent(
|
|
345
|
-
{
|
|
346
|
-
eventName: "SocketCloseOnDisposedConnection",
|
|
347
|
-
driverVersion,
|
|
348
|
-
details: JSON.stringify({
|
|
349
|
-
...this.getConnectionDetailsProps(),
|
|
350
|
-
trackedListenerCount: this.trackedListeners.size,
|
|
351
|
-
}),
|
|
352
|
-
},
|
|
353
|
-
error,
|
|
354
|
-
);
|
|
355
346
|
return;
|
|
356
347
|
}
|
|
357
348
|
this.closeSocketCore(error);
|
|
@@ -392,6 +383,11 @@ export class DocumentDeltaConnection
|
|
|
392
383
|
return;
|
|
393
384
|
}
|
|
394
385
|
|
|
386
|
+
if (this.trackLatencyTimeout !== undefined) {
|
|
387
|
+
clearTimeout(this.trackLatencyTimeout);
|
|
388
|
+
this.trackLatencyTimeout = undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
395
391
|
// We set the disposed flag as a part of the contract for overriding the disconnect method. This is used by
|
|
396
392
|
// DocumentDeltaConnection to determine if emitting messages (ops) on the socket is allowed, which is
|
|
397
393
|
// important since OdspDocumentDeltaConnection reuses the socket rather than truly disconnecting it. Note that
|
|
@@ -409,14 +405,6 @@ export class DocumentDeltaConnection
|
|
|
409
405
|
|
|
410
406
|
// Let user of connection object know about disconnect.
|
|
411
407
|
this.emit("disconnect", err);
|
|
412
|
-
this.logger.sendTelemetryEvent({
|
|
413
|
-
eventName: "AfterDisconnectEvent",
|
|
414
|
-
driverVersion,
|
|
415
|
-
details: JSON.stringify({
|
|
416
|
-
...this.getConnectionDetailsProps(),
|
|
417
|
-
disconnectListenerCount: this.listenerCount("disconnect"),
|
|
418
|
-
}),
|
|
419
|
-
});
|
|
420
408
|
}
|
|
421
409
|
|
|
422
410
|
/**
|
|
@@ -591,9 +579,14 @@ export class DocumentDeltaConnection
|
|
|
591
579
|
// Socket can be disconnected while waiting for Fluid protocol messages
|
|
592
580
|
// (connect_document_error / connect_document_success), as well as before DeltaManager
|
|
593
581
|
// had a chance to register its handlers.
|
|
594
|
-
this.addTrackedListener("disconnect", (reason) => {
|
|
595
|
-
|
|
596
|
-
|
|
582
|
+
this.addTrackedListener("disconnect", (reason, details) => {
|
|
583
|
+
failAndCloseSocket(
|
|
584
|
+
this.createErrorObjectWithProps("disconnect", reason, {
|
|
585
|
+
socketErrorType: details?.context?.type,
|
|
586
|
+
// https://www.rfc-editor.org/rfc/rfc6455#section-7.4
|
|
587
|
+
socketCode: details?.context?.code,
|
|
588
|
+
}),
|
|
589
|
+
);
|
|
597
590
|
});
|
|
598
591
|
|
|
599
592
|
this.addTrackedListener("error", (error) => {
|
|
@@ -705,25 +698,44 @@ export class DocumentDeltaConnection
|
|
|
705
698
|
this.connectionListeners.clear();
|
|
706
699
|
}
|
|
707
700
|
|
|
701
|
+
private getErrorMessage(error?: any): string {
|
|
702
|
+
if (error?.type !== "TransportError") {
|
|
703
|
+
return extractLogSafeErrorProperties(error, true).message;
|
|
704
|
+
}
|
|
705
|
+
// JSON.stringify drops Error.message
|
|
706
|
+
const messagePrefix = error?.message !== undefined ? `${error.message}: ` : "";
|
|
707
|
+
|
|
708
|
+
// Websocket errors reported by engine.io-client.
|
|
709
|
+
// They are Error objects with description containing WS error and description = "TransportError"
|
|
710
|
+
// Please see https://github.com/socketio/engine.io-client/blob/7245b80/lib/transport.ts#L44,
|
|
711
|
+
return `${messagePrefix}${JSON.stringify(error, getCircularReplacer())}`;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private createErrorObjectWithProps(
|
|
715
|
+
handler: string,
|
|
716
|
+
error?: any,
|
|
717
|
+
props?: ITelemetryProperties,
|
|
718
|
+
canRetry = true,
|
|
719
|
+
): IAnyDriverError {
|
|
720
|
+
return createGenericNetworkError(
|
|
721
|
+
`socket.io (${handler}): ${this.getErrorMessage(error)}`,
|
|
722
|
+
{ canRetry },
|
|
723
|
+
{
|
|
724
|
+
...props,
|
|
725
|
+
driverVersion,
|
|
726
|
+
details: JSON.stringify({
|
|
727
|
+
...this.getConnectionDetailsProps(),
|
|
728
|
+
}),
|
|
729
|
+
},
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
|
|
708
733
|
/**
|
|
709
734
|
* Error raising for socket.io issues
|
|
710
735
|
*/
|
|
711
736
|
protected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
// JSON.stringify drops Error.message
|
|
715
|
-
const messagePrefix = error?.message !== undefined ? `${error.message}: ` : "";
|
|
716
|
-
|
|
717
|
-
// Websocket errors reported by engine.io-client.
|
|
718
|
-
// They are Error objects with description containing WS error and description = "TransportError"
|
|
719
|
-
// Please see https://github.com/socketio/engine.io-client/blob/7245b80/lib/transport.ts#L44,
|
|
720
|
-
message = `${messagePrefix}${JSON.stringify(error, getCircularReplacer())}`;
|
|
721
|
-
} else {
|
|
722
|
-
message = extractLogSafeErrorProperties(error, true).message;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
const errorObj = createGenericNetworkError(
|
|
726
|
-
`socket.io (${handler}): ${message}`,
|
|
737
|
+
return createGenericNetworkError(
|
|
738
|
+
`socket.io (${handler}): ${this.getErrorMessage(error)}`,
|
|
727
739
|
{ canRetry },
|
|
728
740
|
{
|
|
729
741
|
driverVersion,
|
|
@@ -732,7 +744,5 @@ export class DocumentDeltaConnection
|
|
|
732
744
|
}),
|
|
733
745
|
},
|
|
734
746
|
);
|
|
735
|
-
|
|
736
|
-
return errorObj;
|
|
737
747
|
}
|
|
738
748
|
}
|
package/src/driverUtils.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { performance } from "@fluidframework/common-utils";
|
|
7
|
+
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
+
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Extract and return the w3c data.
|
|
@@ -103,3 +105,50 @@ export async function promiseRaceWithWinner<T>(
|
|
|
103
105
|
});
|
|
104
106
|
});
|
|
105
107
|
}
|
|
108
|
+
|
|
109
|
+
export function validateMessages(
|
|
110
|
+
reason: string,
|
|
111
|
+
messages: ISequencedDocumentMessage[],
|
|
112
|
+
from: number,
|
|
113
|
+
logger: ITelemetryLoggerExt,
|
|
114
|
+
strict: boolean = true,
|
|
115
|
+
) {
|
|
116
|
+
if (messages.length !== 0) {
|
|
117
|
+
const start = messages[0].sequenceNumber;
|
|
118
|
+
const length = messages.length;
|
|
119
|
+
const last = messages[length - 1].sequenceNumber;
|
|
120
|
+
if (last + 1 !== from + length) {
|
|
121
|
+
// If not strict, then return the first consecutive sub-block. If strict or start
|
|
122
|
+
// seq number is not what we expected, then return no ops.
|
|
123
|
+
if (strict || from !== start) {
|
|
124
|
+
messages.length = 0;
|
|
125
|
+
} else {
|
|
126
|
+
let validOpsCount = 1;
|
|
127
|
+
while (
|
|
128
|
+
validOpsCount < messages.length &&
|
|
129
|
+
messages[validOpsCount].sequenceNumber ===
|
|
130
|
+
messages[validOpsCount - 1].sequenceNumber + 1
|
|
131
|
+
) {
|
|
132
|
+
validOpsCount++;
|
|
133
|
+
}
|
|
134
|
+
messages.length = validOpsCount;
|
|
135
|
+
}
|
|
136
|
+
logger.sendErrorEvent({
|
|
137
|
+
eventName: "OpsFetchViolation",
|
|
138
|
+
reason,
|
|
139
|
+
from,
|
|
140
|
+
start,
|
|
141
|
+
last,
|
|
142
|
+
length,
|
|
143
|
+
details: JSON.stringify({
|
|
144
|
+
validLength: messages.length,
|
|
145
|
+
lastValidOpSeqNumber:
|
|
146
|
+
messages.length > 0
|
|
147
|
+
? messages[messages.length - 1].sequenceNumber
|
|
148
|
+
: undefined,
|
|
149
|
+
strict,
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
package/src/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "@fluidframework/build-common/ts-common-config.json",
|
|
3
|
-
"exclude": ["
|
|
3
|
+
"exclude": ["src/test/**/*"],
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"rootDir": "./src",
|
|
6
6
|
"outDir": "./dist",
|
|
7
|
+
"composite": true,
|
|
7
8
|
},
|
|
8
9
|
"include": ["src/**/*"],
|
|
9
10
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validateDriverBasePrevious.generated.d.ts","sourceRoot":"","sources":["../../../src/test/types/validateDriverBasePrevious.generated.ts"],"names":[],"mappings":""}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
use_current_ClassDeclaration_DocumentDeltaConnection(get_old_ClassDeclaration_DocumentDeltaConnection());
|
|
2
|
-
use_old_ClassDeclaration_DocumentDeltaConnection(get_current_ClassDeclaration_DocumentDeltaConnection());
|
|
3
|
-
use_current_FunctionDeclaration_getW3CData(get_old_FunctionDeclaration_getW3CData());
|
|
4
|
-
use_old_FunctionDeclaration_getW3CData(get_current_FunctionDeclaration_getW3CData());
|
|
5
|
-
export {};
|
|
6
|
-
//# sourceMappingURL=validateDriverBasePrevious.generated.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validateDriverBasePrevious.generated.js","sourceRoot":"","sources":["../../../src/test/types/validateDriverBasePrevious.generated.ts"],"names":[],"mappings":"AAwBA,oDAAoD,CAChD,gDAAgD,EAAE,CAAC,CAAC;AAWxD,gDAAgD,CAC5C,oDAAoD,EAAE,CAAC,CAAC;AAW5D,0CAA0C,CACtC,sCAAsC,EAAE,CAAC,CAAC;AAW9C,sCAAsC,CAClC,0CAA0C,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n/*\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n * Generated by fluid-type-test-generator in @fluidframework/build-tools.\n */\nimport * as old from \"@fluidframework/driver-base-previous\";\nimport * as current from \"../../index\";\n\ntype TypeOnly<T> = {\n [P in keyof T]: TypeOnly<T[P]>;\n};\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DocumentDeltaConnection\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DocumentDeltaConnection():\n TypeOnly<old.DocumentDeltaConnection>;\ndeclare function use_current_ClassDeclaration_DocumentDeltaConnection(\n use: TypeOnly<current.DocumentDeltaConnection>);\nuse_current_ClassDeclaration_DocumentDeltaConnection(\n get_old_ClassDeclaration_DocumentDeltaConnection());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DocumentDeltaConnection\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DocumentDeltaConnection():\n TypeOnly<current.DocumentDeltaConnection>;\ndeclare function use_old_ClassDeclaration_DocumentDeltaConnection(\n use: TypeOnly<old.DocumentDeltaConnection>);\nuse_old_ClassDeclaration_DocumentDeltaConnection(\n get_current_ClassDeclaration_DocumentDeltaConnection());\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_getW3CData\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_FunctionDeclaration_getW3CData():\n TypeOnly<typeof old.getW3CData>;\ndeclare function use_current_FunctionDeclaration_getW3CData(\n use: TypeOnly<typeof current.getW3CData>);\nuse_current_FunctionDeclaration_getW3CData(\n get_old_FunctionDeclaration_getW3CData());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"FunctionDeclaration_getW3CData\": {\"backCompat\": false}\n*/\ndeclare function get_current_FunctionDeclaration_getW3CData():\n TypeOnly<typeof current.getW3CData>;\ndeclare function use_old_FunctionDeclaration_getW3CData(\n use: TypeOnly<typeof old.getW3CData>);\nuse_old_FunctionDeclaration_getW3CData(\n get_current_FunctionDeclaration_getW3CData());\n"]}
|