@dxos/client-services 0.3.3-main.f2ca85a → 0.3.3-main.f990aad
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/dist/lib/browser/{chunk-CIMVJJPI.mjs → chunk-UUQTHQF5.mjs} +74 -45
- package/dist/lib/browser/chunk-UUQTHQF5.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +1 -1
- package/dist/lib/node/index.cjs +78 -49
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +132 -56
- package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +2 -0
- package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/package.json +35 -35
- package/src/packlets/services/client-rpc-server.ts +18 -1
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-CIMVJJPI.mjs.map +0 -7
|
@@ -69,6 +69,82 @@ var import_services15 = require("@dxos/protocols/proto/dxos/client/services");
|
|
|
69
69
|
var import_codec_protobuf = require("@dxos/codec-protobuf");
|
|
70
70
|
var import_debug = require("@dxos/debug");
|
|
71
71
|
var import_rpc = require("@dxos/rpc");
|
|
72
|
+
var import_tracing = require("@dxos/tracing");
|
|
73
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
74
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
75
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
76
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
77
|
+
else
|
|
78
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
79
|
+
if (d = decorators[i])
|
|
80
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
81
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
82
|
+
}
|
|
83
|
+
var ClientRpcServer = class ClientRpcServer2 {
|
|
84
|
+
constructor(params) {
|
|
85
|
+
this._handlerCache = /* @__PURE__ */ new Map();
|
|
86
|
+
this._callMetrics = new import_tracing.MapCounter();
|
|
87
|
+
const { serviceRegistry, handleCall, handleStream, ...rpcOptions } = params;
|
|
88
|
+
this._handleCall = handleCall;
|
|
89
|
+
this._handleStream = handleStream;
|
|
90
|
+
this._serviceRegistry = serviceRegistry;
|
|
91
|
+
this._rpcPeer = new import_rpc.RpcPeer({
|
|
92
|
+
...rpcOptions,
|
|
93
|
+
callHandler: (method, params2) => {
|
|
94
|
+
const [serviceName, methodName] = (0, import_rpc.parseMethodName)(method);
|
|
95
|
+
const handler = (method2, params3) => this._getServiceHandler(serviceName).call(method2, params3);
|
|
96
|
+
this._callMetrics.inc(`${serviceName}.${methodName} request`);
|
|
97
|
+
if (this._handleCall) {
|
|
98
|
+
return this._handleCall(methodName, params2, handler);
|
|
99
|
+
} else {
|
|
100
|
+
return handler(methodName, params2);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
streamHandler: (method, params2) => {
|
|
104
|
+
const [serviceName, methodName] = (0, import_rpc.parseMethodName)(method);
|
|
105
|
+
const handler = (method2, params3) => this._getServiceHandler(serviceName).callStream(method2, params3);
|
|
106
|
+
this._callMetrics.inc(`${serviceName}.${methodName} request stream`);
|
|
107
|
+
if (this._handleStream) {
|
|
108
|
+
return import_codec_protobuf.Stream.map(import_codec_protobuf.Stream.unwrapPromise(this._handleStream(methodName, params2, handler)), (data) => {
|
|
109
|
+
this._callMetrics.inc(`${serviceName}.${methodName} response stream`);
|
|
110
|
+
return data;
|
|
111
|
+
});
|
|
112
|
+
} else {
|
|
113
|
+
return handler(methodName, params2);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
get _services() {
|
|
119
|
+
return Object.keys(this._serviceRegistry.services);
|
|
120
|
+
}
|
|
121
|
+
async open() {
|
|
122
|
+
await this._rpcPeer.open();
|
|
123
|
+
}
|
|
124
|
+
async close() {
|
|
125
|
+
await this._rpcPeer.close();
|
|
126
|
+
}
|
|
127
|
+
_getServiceHandler(serviceName) {
|
|
128
|
+
if (!this._handlerCache.has(serviceName)) {
|
|
129
|
+
const [key, descriptor] = Object.entries(this._serviceRegistry.descriptors).find(([key2, descriptor2]) => descriptor2.name === serviceName) ?? (0, import_debug.raise)(new Error(`Service not available: ${serviceName}`));
|
|
130
|
+
const service = this._serviceRegistry.services[key];
|
|
131
|
+
if (!service) {
|
|
132
|
+
throw new Error(`Service not available: ${serviceName}`);
|
|
133
|
+
}
|
|
134
|
+
this._handlerCache.set(serviceName, descriptor.createServer(service));
|
|
135
|
+
}
|
|
136
|
+
return this._handlerCache.get(serviceName);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
_ts_decorate([
|
|
140
|
+
import_tracing.trace.metricsCounter()
|
|
141
|
+
], ClientRpcServer.prototype, "_callMetrics", void 0);
|
|
142
|
+
_ts_decorate([
|
|
143
|
+
import_tracing.trace.info()
|
|
144
|
+
], ClientRpcServer.prototype, "_services", null);
|
|
145
|
+
ClientRpcServer = _ts_decorate([
|
|
146
|
+
import_tracing.trace.resource()
|
|
147
|
+
], ClientRpcServer);
|
|
72
148
|
|
|
73
149
|
// packages/sdk/client-services/src/packlets/services/diagnostics.ts
|
|
74
150
|
var import_async = require("@dxos/async");
|
|
@@ -110,7 +186,7 @@ var getPlatform = () => {
|
|
|
110
186
|
};
|
|
111
187
|
|
|
112
188
|
// packages/sdk/client-services/src/version.ts
|
|
113
|
-
var DXOS_VERSION = "0.3.3-main.
|
|
189
|
+
var DXOS_VERSION = "0.3.3-main.f990aad";
|
|
114
190
|
|
|
115
191
|
// packages/sdk/client-services/src/packlets/services/diagnostics.ts
|
|
116
192
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/sdk/client-services/src/packlets/services/diagnostics.ts";
|
|
@@ -257,7 +333,7 @@ var import_log13 = require("@dxos/log");
|
|
|
257
333
|
var import_protocols10 = require("@dxos/protocols");
|
|
258
334
|
var import_services10 = require("@dxos/protocols/proto/dxos/client/services");
|
|
259
335
|
var import_teleport_extension_object_sync = require("@dxos/teleport-extension-object-sync");
|
|
260
|
-
var
|
|
336
|
+
var import_tracing5 = require("@dxos/tracing");
|
|
261
337
|
var import_util6 = require("@dxos/util");
|
|
262
338
|
|
|
263
339
|
// packages/sdk/client-services/src/packlets/identity/authenticator.ts
|
|
@@ -385,9 +461,9 @@ var import_invariant2 = require("@dxos/invariant");
|
|
|
385
461
|
var import_keys2 = require("@dxos/keys");
|
|
386
462
|
var import_log3 = require("@dxos/log");
|
|
387
463
|
var import_credentials5 = require("@dxos/protocols/proto/dxos/halo/credentials");
|
|
388
|
-
var
|
|
464
|
+
var import_tracing2 = require("@dxos/tracing");
|
|
389
465
|
var import_util = require("@dxos/util");
|
|
390
|
-
function
|
|
466
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
391
467
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
392
468
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
393
469
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -546,14 +622,14 @@ var Identity = class Identity2 {
|
|
|
546
622
|
})));
|
|
547
623
|
}
|
|
548
624
|
};
|
|
549
|
-
|
|
550
|
-
|
|
625
|
+
_ts_decorate2([
|
|
626
|
+
import_tracing2.trace.span()
|
|
551
627
|
], Identity.prototype, "open", null);
|
|
552
|
-
|
|
553
|
-
|
|
628
|
+
_ts_decorate2([
|
|
629
|
+
import_tracing2.trace.span()
|
|
554
630
|
], Identity.prototype, "close", null);
|
|
555
|
-
Identity =
|
|
556
|
-
|
|
631
|
+
Identity = _ts_decorate2([
|
|
632
|
+
import_tracing2.trace.resource()
|
|
557
633
|
], Identity);
|
|
558
634
|
|
|
559
635
|
// packages/sdk/client-services/src/packlets/identity/identity-manager.ts
|
|
@@ -567,9 +643,9 @@ var import_log4 = require("@dxos/log");
|
|
|
567
643
|
var import_protocols3 = require("@dxos/protocols");
|
|
568
644
|
var import_credentials7 = require("@dxos/protocols/proto/dxos/halo/credentials");
|
|
569
645
|
var import_timeframe = require("@dxos/timeframe");
|
|
570
|
-
var
|
|
646
|
+
var import_tracing3 = require("@dxos/tracing");
|
|
571
647
|
var import_util2 = require("@dxos/util");
|
|
572
|
-
function
|
|
648
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
573
649
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
574
650
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
575
651
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -925,13 +1001,13 @@ var IdentityManager = class IdentityManager2 {
|
|
|
925
1001
|
});
|
|
926
1002
|
}
|
|
927
1003
|
};
|
|
928
|
-
|
|
929
|
-
|
|
1004
|
+
_ts_decorate3([
|
|
1005
|
+
import_tracing3.trace.span({
|
|
930
1006
|
showInBrowserTimeline: true
|
|
931
1007
|
})
|
|
932
1008
|
], IdentityManager.prototype, "open", null);
|
|
933
|
-
IdentityManager =
|
|
934
|
-
|
|
1009
|
+
IdentityManager = _ts_decorate3([
|
|
1010
|
+
import_tracing3.trace.resource()
|
|
935
1011
|
], IdentityManager);
|
|
936
1012
|
|
|
937
1013
|
// packages/sdk/client-services/src/packlets/identity/identity-service.ts
|
|
@@ -2362,7 +2438,7 @@ var import_protocols7 = require("@dxos/protocols");
|
|
|
2362
2438
|
var import_services7 = require("@dxos/protocols/proto/dxos/client/services");
|
|
2363
2439
|
var import_credentials11 = require("@dxos/protocols/proto/dxos/halo/credentials");
|
|
2364
2440
|
var import_timeframe2 = require("@dxos/timeframe");
|
|
2365
|
-
var
|
|
2441
|
+
var import_tracing4 = require("@dxos/tracing");
|
|
2366
2442
|
var import_util4 = require("@dxos/util");
|
|
2367
2443
|
|
|
2368
2444
|
// packages/sdk/client-services/src/packlets/spaces/notarization-plugin.ts
|
|
@@ -2634,7 +2710,7 @@ var NotarizationTeleportExtension = class extends import_teleport2.RpcExtension
|
|
|
2634
2710
|
};
|
|
2635
2711
|
|
|
2636
2712
|
// packages/sdk/client-services/src/packlets/spaces/data-space.ts
|
|
2637
|
-
function
|
|
2713
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
2638
2714
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2639
2715
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
2640
2716
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -2966,32 +3042,32 @@ var DataSpace = class DataSpace2 {
|
|
|
2966
3042
|
this.stateUpdate.emit();
|
|
2967
3043
|
}
|
|
2968
3044
|
};
|
|
2969
|
-
|
|
3045
|
+
_ts_decorate4([
|
|
2970
3046
|
import_async9.synchronized
|
|
2971
3047
|
], DataSpace.prototype, "open", null);
|
|
2972
|
-
|
|
3048
|
+
_ts_decorate4([
|
|
2973
3049
|
import_async9.synchronized
|
|
2974
3050
|
], DataSpace.prototype, "close", null);
|
|
2975
|
-
|
|
2976
|
-
|
|
3051
|
+
_ts_decorate4([
|
|
3052
|
+
import_tracing4.trace.span({
|
|
2977
3053
|
showInBrowserTimeline: true
|
|
2978
3054
|
})
|
|
2979
3055
|
], DataSpace.prototype, "initializeDataPipeline", null);
|
|
2980
|
-
|
|
2981
|
-
|
|
3056
|
+
_ts_decorate4([
|
|
3057
|
+
import_tracing4.trace.span({
|
|
2982
3058
|
showInBrowserTimeline: true
|
|
2983
3059
|
})
|
|
2984
3060
|
], DataSpace.prototype, "_initializeAndReadControlPipeline", null);
|
|
2985
|
-
|
|
3061
|
+
_ts_decorate4([
|
|
2986
3062
|
(0, import_debug4.timed)(1e4)
|
|
2987
3063
|
], DataSpace.prototype, "_createWritableFeeds", null);
|
|
2988
|
-
|
|
3064
|
+
_ts_decorate4([
|
|
2989
3065
|
import_async9.synchronized
|
|
2990
3066
|
], DataSpace.prototype, "activate", null);
|
|
2991
|
-
|
|
3067
|
+
_ts_decorate4([
|
|
2992
3068
|
import_async9.synchronized
|
|
2993
3069
|
], DataSpace.prototype, "deactivate", null);
|
|
2994
|
-
DataSpace =
|
|
3070
|
+
DataSpace = _ts_decorate4([
|
|
2995
3071
|
(0, import_async9.trackLeaks)("open", "close")
|
|
2996
3072
|
], DataSpace);
|
|
2997
3073
|
|
|
@@ -3065,7 +3141,7 @@ var spaceGenesis = async (keyring, signingContext, space) => {
|
|
|
3065
3141
|
};
|
|
3066
3142
|
|
|
3067
3143
|
// packages/sdk/client-services/src/packlets/spaces/data-space-manager.ts
|
|
3068
|
-
function
|
|
3144
|
+
function _ts_decorate5(decorators, target, key, desc) {
|
|
3069
3145
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3070
3146
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
3071
3147
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -3381,19 +3457,19 @@ var DataSpaceManager = class DataSpaceManager2 {
|
|
|
3381
3457
|
return dataSpace;
|
|
3382
3458
|
}
|
|
3383
3459
|
};
|
|
3384
|
-
|
|
3460
|
+
_ts_decorate5([
|
|
3385
3461
|
import_async10.synchronized
|
|
3386
3462
|
], DataSpaceManager.prototype, "open", null);
|
|
3387
|
-
|
|
3463
|
+
_ts_decorate5([
|
|
3388
3464
|
import_async10.synchronized
|
|
3389
3465
|
], DataSpaceManager.prototype, "close", null);
|
|
3390
|
-
|
|
3466
|
+
_ts_decorate5([
|
|
3391
3467
|
import_async10.synchronized
|
|
3392
3468
|
], DataSpaceManager.prototype, "createSpace", null);
|
|
3393
|
-
|
|
3469
|
+
_ts_decorate5([
|
|
3394
3470
|
import_async10.synchronized
|
|
3395
3471
|
], DataSpaceManager.prototype, "acceptSpace", null);
|
|
3396
|
-
DataSpaceManager =
|
|
3472
|
+
DataSpaceManager = _ts_decorate5([
|
|
3397
3473
|
(0, import_async10.trackLeaks)("open", "close")
|
|
3398
3474
|
], DataSpaceManager);
|
|
3399
3475
|
|
|
@@ -3619,7 +3695,7 @@ var SpacesServiceImpl = class {
|
|
|
3619
3695
|
var getChannelId = (channel) => `user-channel/${channel}`;
|
|
3620
3696
|
|
|
3621
3697
|
// packages/sdk/client-services/src/packlets/services/service-context.ts
|
|
3622
|
-
function
|
|
3698
|
+
function _ts_decorate6(decorators, target, key, desc) {
|
|
3623
3699
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3624
3700
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
3625
3701
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -3853,15 +3929,15 @@ var ServiceContext = class ServiceContext2 {
|
|
|
3853
3929
|
await identity.space.spaceState.addCredentialProcessor(this._deviceSpaceSync);
|
|
3854
3930
|
}
|
|
3855
3931
|
};
|
|
3856
|
-
|
|
3857
|
-
|
|
3932
|
+
_ts_decorate6([
|
|
3933
|
+
import_tracing5.trace.span()
|
|
3858
3934
|
], ServiceContext.prototype, "open", null);
|
|
3859
|
-
|
|
3860
|
-
|
|
3935
|
+
_ts_decorate6([
|
|
3936
|
+
import_tracing5.trace.span()
|
|
3861
3937
|
], ServiceContext.prototype, "_initialize", null);
|
|
3862
|
-
ServiceContext =
|
|
3938
|
+
ServiceContext = _ts_decorate6([
|
|
3863
3939
|
(0, import_util6.safeInstanceof)("dxos.client-services.ServiceContext"),
|
|
3864
|
-
|
|
3940
|
+
import_tracing5.trace.resource()
|
|
3865
3941
|
], ServiceContext);
|
|
3866
3942
|
|
|
3867
3943
|
// packages/sdk/client-services/src/packlets/services/service-host.ts
|
|
@@ -3880,7 +3956,7 @@ var import_network_manager2 = require("@dxos/network-manager");
|
|
|
3880
3956
|
var import_protocols12 = require("@dxos/protocols");
|
|
3881
3957
|
var import_services14 = require("@dxos/protocols/proto/dxos/client/services");
|
|
3882
3958
|
var import_text_model = require("@dxos/text-model");
|
|
3883
|
-
var
|
|
3959
|
+
var import_tracing6 = require("@dxos/tracing");
|
|
3884
3960
|
var import_websocket_rpc = require("@dxos/websocket-rpc");
|
|
3885
3961
|
|
|
3886
3962
|
// packages/sdk/client-services/src/packlets/services/service-registry.ts
|
|
@@ -4263,7 +4339,7 @@ var DevtoolsServiceImpl = class {
|
|
|
4263
4339
|
var import_invariant14 = require("@dxos/invariant");
|
|
4264
4340
|
var import_lock_file = require("@dxos/lock-file");
|
|
4265
4341
|
var import_log14 = require("@dxos/log");
|
|
4266
|
-
function
|
|
4342
|
+
function _ts_decorate7(decorators, target, key, desc) {
|
|
4267
4343
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4268
4344
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
4269
4345
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -4313,7 +4389,7 @@ var Lock = class {
|
|
|
4313
4389
|
await import_lock_file.LockFile.release(this._fileHandle);
|
|
4314
4390
|
}
|
|
4315
4391
|
};
|
|
4316
|
-
|
|
4392
|
+
_ts_decorate7([
|
|
4317
4393
|
import_log14.logInfo
|
|
4318
4394
|
], Lock.prototype, "lockKey", null);
|
|
4319
4395
|
|
|
@@ -4570,7 +4646,7 @@ var SystemServiceImpl = class {
|
|
|
4570
4646
|
};
|
|
4571
4647
|
|
|
4572
4648
|
// packages/sdk/client-services/src/packlets/services/service-host.ts
|
|
4573
|
-
function
|
|
4649
|
+
function _ts_decorate8(decorators, target, key, desc) {
|
|
4574
4650
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4575
4651
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
4576
4652
|
r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -4607,7 +4683,7 @@ var ClientServicesHost = class ClientServicesHost2 {
|
|
|
4607
4683
|
lockKey,
|
|
4608
4684
|
callbacks
|
|
4609
4685
|
} = {}) {
|
|
4610
|
-
this._tracingService =
|
|
4686
|
+
this._tracingService = import_tracing6.TRACE_PROCESSOR.createTraceSender();
|
|
4611
4687
|
this._statusUpdate = new import_async18.Event();
|
|
4612
4688
|
this._opening = false;
|
|
4613
4689
|
this._open = false;
|
|
@@ -4932,22 +5008,22 @@ var ClientServicesHost = class ClientServicesHost2 {
|
|
|
4932
5008
|
return identity;
|
|
4933
5009
|
}
|
|
4934
5010
|
};
|
|
4935
|
-
|
|
4936
|
-
|
|
5011
|
+
_ts_decorate8([
|
|
5012
|
+
import_tracing6.trace.info()
|
|
4937
5013
|
], ClientServicesHost.prototype, "_opening", void 0);
|
|
4938
|
-
|
|
4939
|
-
|
|
5014
|
+
_ts_decorate8([
|
|
5015
|
+
import_tracing6.trace.info()
|
|
4940
5016
|
], ClientServicesHost.prototype, "_open", void 0);
|
|
4941
|
-
|
|
5017
|
+
_ts_decorate8([
|
|
4942
5018
|
import_async18.synchronized,
|
|
4943
|
-
|
|
5019
|
+
import_tracing6.trace.span()
|
|
4944
5020
|
], ClientServicesHost.prototype, "open", null);
|
|
4945
|
-
|
|
5021
|
+
_ts_decorate8([
|
|
4946
5022
|
import_async18.synchronized,
|
|
4947
|
-
|
|
5023
|
+
import_tracing6.trace.span()
|
|
4948
5024
|
], ClientServicesHost.prototype, "close", null);
|
|
4949
|
-
ClientServicesHost =
|
|
4950
|
-
|
|
5025
|
+
ClientServicesHost = _ts_decorate8([
|
|
5026
|
+
import_tracing6.trace.resource()
|
|
4951
5027
|
], ClientServicesHost);
|
|
4952
5028
|
|
|
4953
5029
|
// packages/sdk/client-services/src/packlets/testing/invitation-utils.ts
|