@seamapi/http 0.9.3 → 0.10.1

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 (68) hide show
  1. package/README.md +5 -5
  2. package/dist/connect.cjs +281 -20
  3. package/dist/connect.cjs.map +1 -1
  4. package/dist/connect.d.cts +64 -1
  5. package/lib/params-serializer.js +12 -14
  6. package/lib/params-serializer.js.map +1 -1
  7. package/lib/seam/connect/auth.js.map +1 -1
  8. package/lib/seam/connect/client.js +0 -2
  9. package/lib/seam/connect/client.js.map +1 -1
  10. package/lib/seam/connect/error-interceptor.js +11 -3
  11. package/lib/seam/connect/error-interceptor.js.map +1 -1
  12. package/lib/seam/connect/options.js.map +1 -1
  13. package/lib/seam/connect/parse-options.js.map +1 -1
  14. package/lib/seam/connect/resolve-action-attempt.js.map +1 -1
  15. package/lib/seam/connect/routes/access-codes-unmanaged.js.map +1 -1
  16. package/lib/seam/connect/routes/access-codes.js.map +1 -1
  17. package/lib/seam/connect/routes/acs-access-groups.js.map +1 -1
  18. package/lib/seam/connect/routes/acs-credential-pools.d.ts +19 -0
  19. package/lib/seam/connect/routes/acs-credential-pools.js +73 -0
  20. package/lib/seam/connect/routes/acs-credential-pools.js.map +1 -0
  21. package/lib/seam/connect/routes/acs-credential-provisioning-automations.d.ts +19 -0
  22. package/lib/seam/connect/routes/acs-credential-provisioning-automations.js +73 -0
  23. package/lib/seam/connect/routes/acs-credential-provisioning-automations.js.map +1 -0
  24. package/lib/seam/connect/routes/acs-credentials.js.map +1 -1
  25. package/lib/seam/connect/routes/acs-entrances.d.ts +27 -0
  26. package/lib/seam/connect/routes/acs-entrances.js +88 -0
  27. package/lib/seam/connect/routes/acs-entrances.js.map +1 -0
  28. package/lib/seam/connect/routes/acs-systems.js.map +1 -1
  29. package/lib/seam/connect/routes/acs-users.js.map +1 -1
  30. package/lib/seam/connect/routes/acs.d.ts +6 -0
  31. package/lib/seam/connect/routes/acs.js +12 -0
  32. package/lib/seam/connect/routes/acs.js.map +1 -1
  33. package/lib/seam/connect/routes/action-attempts.js.map +1 -1
  34. package/lib/seam/connect/routes/client-sessions.js.map +1 -1
  35. package/lib/seam/connect/routes/connect-webviews.js.map +1 -1
  36. package/lib/seam/connect/routes/connected-accounts.d.ts +4 -0
  37. package/lib/seam/connect/routes/connected-accounts.js +8 -0
  38. package/lib/seam/connect/routes/connected-accounts.js.map +1 -1
  39. package/lib/seam/connect/routes/devices-unmanaged.js.map +1 -1
  40. package/lib/seam/connect/routes/devices.js.map +1 -1
  41. package/lib/seam/connect/routes/events.js.map +1 -1
  42. package/lib/seam/connect/routes/index.d.ts +3 -0
  43. package/lib/seam/connect/routes/index.js +3 -0
  44. package/lib/seam/connect/routes/index.js.map +1 -1
  45. package/lib/seam/connect/routes/locks.js.map +1 -1
  46. package/lib/seam/connect/routes/noise-sensors-noise-thresholds.js.map +1 -1
  47. package/lib/seam/connect/routes/noise-sensors.js.map +1 -1
  48. package/lib/seam/connect/routes/thermostats-climate-setting-schedules.js.map +1 -1
  49. package/lib/seam/connect/routes/thermostats.js.map +1 -1
  50. package/lib/seam/connect/routes/user-identities.js.map +1 -1
  51. package/lib/seam/connect/routes/webhooks.js.map +1 -1
  52. package/lib/seam/connect/routes/workspaces.js.map +1 -1
  53. package/lib/seam/connect/seam-http-multi-workspace.js.map +1 -1
  54. package/lib/seam/connect/seam-http.js.map +1 -1
  55. package/lib/version.d.ts +1 -1
  56. package/lib/version.js +1 -1
  57. package/lib/version.js.map +1 -1
  58. package/package.json +10 -10
  59. package/src/lib/params-serializer.ts +8 -19
  60. package/src/lib/seam/connect/client.ts +0 -2
  61. package/src/lib/seam/connect/error-interceptor.ts +11 -3
  62. package/src/lib/seam/connect/routes/acs-credential-pools.ts +154 -0
  63. package/src/lib/seam/connect/routes/acs-credential-provisioning-automations.ts +162 -0
  64. package/src/lib/seam/connect/routes/acs-entrances.ts +190 -0
  65. package/src/lib/seam/connect/routes/acs.ts +18 -0
  66. package/src/lib/seam/connect/routes/connected-accounts.ts +23 -0
  67. package/src/lib/seam/connect/routes/index.ts +3 -0
  68. package/src/lib/version.ts +1 -1
package/README.md CHANGED
@@ -56,19 +56,19 @@ Refer to the next section for keeping the types updated.
56
56
  #### Keeping up with the latest types
57
57
 
58
58
  This package depends on [@seamapi/types] for the latest TypeScript types.
59
- New versions of this package are generally not released when new types are published.
59
+ New versions of this SDK are generally not released when new types are published.
60
60
  Unless your project frequently runs a blanket `npm update`,
61
61
  the types will become outdated with the Seam API over time.
62
- Thus, users of this package should explicitly install the types
62
+ Thus, users of this package should explicitly install the types with
63
63
 
64
64
  ```
65
- $ npm install @seamapi/types
65
+ $ npm install -D @seamapi/types
66
66
  ```
67
67
 
68
- and update them when consuming new API features:
68
+ and update them when consuming new API features with
69
69
 
70
70
  ```
71
- $ npm install @seamapi/http@latest
71
+ $ npm install -D @seamapi/http@latest
72
72
  ```
73
73
 
74
74
  ## Usage
package/dist/connect.cjs CHANGED
@@ -476,8 +476,7 @@ var errorInterceptor = async (err) => {
476
476
  throw err;
477
477
  const { response } = err;
478
478
  const status = response?.status;
479
- const headers = response?.headers;
480
- const requestId = headers?.["seam-request-id"] ?? "";
479
+ const requestId = getRequestId(err);
481
480
  if (status == null)
482
481
  throw err;
483
482
  if (status === 401) {
@@ -497,7 +496,7 @@ var isApiErrorResponse = (response) => {
497
496
  const { headers, data } = response;
498
497
  if (headers == null)
499
498
  return false;
500
- const contentType = headers["content-type"];
499
+ const contentType = headers["Content-Type"];
501
500
  if (typeof contentType === "string" && !contentType.startsWith("application/json")) {
502
501
  return false;
503
502
  }
@@ -506,6 +505,15 @@ var isApiErrorResponse = (response) => {
506
505
  }
507
506
  return false;
508
507
  };
508
+ var getRequestId = (err) => {
509
+ const headers = err.response?.headers;
510
+ if (headers == null)
511
+ return "";
512
+ const requestId = headers["seam-request-id"];
513
+ if (requestId == null)
514
+ return "";
515
+ return requestId;
516
+ };
509
517
 
510
518
  // src/lib/seam/connect/resolve-action-attempt.ts
511
519
  var resolveActionAttempt = async (actionAttempt, actionAttempts, { timeout = 5e3, pollingInterval = 500 }) => {
@@ -598,30 +606,25 @@ var paramsSerializer = (params) => {
598
606
  );
599
607
  }
600
608
  for (const v of value) {
601
- throwIfUnserializable(name, v);
602
- searchParams.append(name, v);
609
+ searchParams.append(name, serialize(name, v));
603
610
  }
604
611
  continue;
605
612
  }
606
- throwIfUnserializable(name, value);
607
- searchParams.set(name, value);
613
+ searchParams.set(name, serialize(name, value));
608
614
  }
609
615
  searchParams.sort();
610
616
  return searchParams.toString();
611
617
  };
612
- var throwIfUnserializable = (k, v) => {
613
- if (v == null) {
614
- throw new UnserializableParamError(k, `is ${v} or contains ${v}`);
615
- }
616
- if (typeof v === "function") {
617
- throw new UnserializableParamError(
618
- k,
619
- "is a function or contains a function"
620
- );
621
- }
622
- if (typeof v === "object") {
623
- throw new UnserializableParamError(k, "is an object or contains an object");
624
- }
618
+ var serialize = (k, v) => {
619
+ if (typeof v === "string")
620
+ return v.toString();
621
+ if (typeof v === "number")
622
+ return v.toString();
623
+ if (typeof v === "bigint")
624
+ return v.toString();
625
+ if (typeof v === "boolean")
626
+ return v.toString();
627
+ throw new UnserializableParamError(k, `is a ${typeof v}`);
625
628
  };
626
629
  var UnserializableParamError = class extends Error {
627
630
  constructor(name, message) {
@@ -1097,6 +1100,153 @@ var SeamHttpAcsAccessGroups = class _SeamHttpAcsAccessGroups {
1097
1100
  }
1098
1101
  };
1099
1102
 
1103
+ // src/lib/seam/connect/routes/acs-credential-pools.ts
1104
+ var SeamHttpAcsCredentialPools = class _SeamHttpAcsCredentialPools {
1105
+ constructor(apiKeyOrOptions = {}) {
1106
+ const options = parseOptions(apiKeyOrOptions);
1107
+ this.client = "client" in options ? options.client : createClient(options);
1108
+ this.defaults = limitToSeamHttpRequestOptions(options);
1109
+ }
1110
+ static fromClient(client, options = {}) {
1111
+ const constructorOptions = { ...options, client };
1112
+ if (!isSeamHttpOptionsWithClient(constructorOptions)) {
1113
+ throw new SeamHttpInvalidOptionsError("Missing client");
1114
+ }
1115
+ return new _SeamHttpAcsCredentialPools(constructorOptions);
1116
+ }
1117
+ static fromApiKey(apiKey, options = {}) {
1118
+ const constructorOptions = { ...options, apiKey };
1119
+ if (!isSeamHttpOptionsWithApiKey(constructorOptions)) {
1120
+ throw new SeamHttpInvalidOptionsError("Missing apiKey");
1121
+ }
1122
+ return new _SeamHttpAcsCredentialPools(constructorOptions);
1123
+ }
1124
+ static fromClientSessionToken(clientSessionToken, options = {}) {
1125
+ const constructorOptions = { ...options, clientSessionToken };
1126
+ if (!isSeamHttpOptionsWithClientSessionToken(constructorOptions)) {
1127
+ throw new SeamHttpInvalidOptionsError("Missing clientSessionToken");
1128
+ }
1129
+ return new _SeamHttpAcsCredentialPools(constructorOptions);
1130
+ }
1131
+ static async fromPublishableKey(publishableKey, userIdentifierKey, options = {}) {
1132
+ warnOnInsecureuserIdentifierKey(userIdentifierKey);
1133
+ const clientOptions = parseOptions({ ...options, publishableKey });
1134
+ if (isSeamHttpOptionsWithClient(clientOptions)) {
1135
+ throw new SeamHttpInvalidOptionsError(
1136
+ "The client option cannot be used with SeamHttp.fromPublishableKey"
1137
+ );
1138
+ }
1139
+ const client = createClient(clientOptions);
1140
+ const clientSessions = SeamHttpClientSessions.fromClient(client);
1141
+ const { token } = await clientSessions.getOrCreate({
1142
+ user_identifier_key: userIdentifierKey
1143
+ });
1144
+ return _SeamHttpAcsCredentialPools.fromClientSessionToken(token, options);
1145
+ }
1146
+ static fromConsoleSessionToken(consoleSessionToken, workspaceId, options = {}) {
1147
+ const constructorOptions = { ...options, consoleSessionToken, workspaceId };
1148
+ if (!isSeamHttpOptionsWithConsoleSessionToken(constructorOptions)) {
1149
+ throw new SeamHttpInvalidOptionsError(
1150
+ "Missing consoleSessionToken or workspaceId"
1151
+ );
1152
+ }
1153
+ return new _SeamHttpAcsCredentialPools(constructorOptions);
1154
+ }
1155
+ static fromPersonalAccessToken(personalAccessToken, workspaceId, options = {}) {
1156
+ const constructorOptions = { ...options, personalAccessToken, workspaceId };
1157
+ if (!isSeamHttpOptionsWithPersonalAccessToken(constructorOptions)) {
1158
+ throw new SeamHttpInvalidOptionsError(
1159
+ "Missing personalAccessToken or workspaceId"
1160
+ );
1161
+ }
1162
+ return new _SeamHttpAcsCredentialPools(constructorOptions);
1163
+ }
1164
+ async list(body) {
1165
+ const { data } = await this.client.request({
1166
+ url: "/acs/credential_pools/list",
1167
+ method: "post",
1168
+ data: body
1169
+ });
1170
+ return data.acs_credential_pools;
1171
+ }
1172
+ };
1173
+
1174
+ // src/lib/seam/connect/routes/acs-credential-provisioning-automations.ts
1175
+ var SeamHttpAcsCredentialProvisioningAutomations = class _SeamHttpAcsCredentialProvisioningAutomations {
1176
+ constructor(apiKeyOrOptions = {}) {
1177
+ const options = parseOptions(apiKeyOrOptions);
1178
+ this.client = "client" in options ? options.client : createClient(options);
1179
+ this.defaults = limitToSeamHttpRequestOptions(options);
1180
+ }
1181
+ static fromClient(client, options = {}) {
1182
+ const constructorOptions = { ...options, client };
1183
+ if (!isSeamHttpOptionsWithClient(constructorOptions)) {
1184
+ throw new SeamHttpInvalidOptionsError("Missing client");
1185
+ }
1186
+ return new _SeamHttpAcsCredentialProvisioningAutomations(constructorOptions);
1187
+ }
1188
+ static fromApiKey(apiKey, options = {}) {
1189
+ const constructorOptions = { ...options, apiKey };
1190
+ if (!isSeamHttpOptionsWithApiKey(constructorOptions)) {
1191
+ throw new SeamHttpInvalidOptionsError("Missing apiKey");
1192
+ }
1193
+ return new _SeamHttpAcsCredentialProvisioningAutomations(constructorOptions);
1194
+ }
1195
+ static fromClientSessionToken(clientSessionToken, options = {}) {
1196
+ const constructorOptions = { ...options, clientSessionToken };
1197
+ if (!isSeamHttpOptionsWithClientSessionToken(constructorOptions)) {
1198
+ throw new SeamHttpInvalidOptionsError("Missing clientSessionToken");
1199
+ }
1200
+ return new _SeamHttpAcsCredentialProvisioningAutomations(constructorOptions);
1201
+ }
1202
+ static async fromPublishableKey(publishableKey, userIdentifierKey, options = {}) {
1203
+ warnOnInsecureuserIdentifierKey(userIdentifierKey);
1204
+ const clientOptions = parseOptions({ ...options, publishableKey });
1205
+ if (isSeamHttpOptionsWithClient(clientOptions)) {
1206
+ throw new SeamHttpInvalidOptionsError(
1207
+ "The client option cannot be used with SeamHttp.fromPublishableKey"
1208
+ );
1209
+ }
1210
+ const client = createClient(clientOptions);
1211
+ const clientSessions = SeamHttpClientSessions.fromClient(client);
1212
+ const { token } = await clientSessions.getOrCreate({
1213
+ user_identifier_key: userIdentifierKey
1214
+ });
1215
+ return _SeamHttpAcsCredentialProvisioningAutomations.fromClientSessionToken(
1216
+ token,
1217
+ options
1218
+ );
1219
+ }
1220
+ static fromConsoleSessionToken(consoleSessionToken, workspaceId, options = {}) {
1221
+ const constructorOptions = { ...options, consoleSessionToken, workspaceId };
1222
+ if (!isSeamHttpOptionsWithConsoleSessionToken(constructorOptions)) {
1223
+ throw new SeamHttpInvalidOptionsError(
1224
+ "Missing consoleSessionToken or workspaceId"
1225
+ );
1226
+ }
1227
+ return new _SeamHttpAcsCredentialProvisioningAutomations(constructorOptions);
1228
+ }
1229
+ static fromPersonalAccessToken(personalAccessToken, workspaceId, options = {}) {
1230
+ const constructorOptions = { ...options, personalAccessToken, workspaceId };
1231
+ if (!isSeamHttpOptionsWithPersonalAccessToken(constructorOptions)) {
1232
+ throw new SeamHttpInvalidOptionsError(
1233
+ "Missing personalAccessToken or workspaceId"
1234
+ );
1235
+ }
1236
+ return new _SeamHttpAcsCredentialProvisioningAutomations(constructorOptions);
1237
+ }
1238
+ async launch(body) {
1239
+ const { data } = await this.client.request(
1240
+ {
1241
+ url: "/acs/credential_provisioning_automations/launch",
1242
+ method: "post",
1243
+ data: body
1244
+ }
1245
+ );
1246
+ return data.acs_credential_provisioning_automation;
1247
+ }
1248
+ };
1249
+
1100
1250
  // src/lib/seam/connect/routes/acs-credentials.ts
1101
1251
  var SeamHttpAcsCredentials = class _SeamHttpAcsCredentials {
1102
1252
  constructor(apiKeyOrOptions = {}) {
@@ -1215,6 +1365,92 @@ var SeamHttpAcsCredentials = class _SeamHttpAcsCredentials {
1215
1365
  }
1216
1366
  };
1217
1367
 
1368
+ // src/lib/seam/connect/routes/acs-entrances.ts
1369
+ var SeamHttpAcsEntrances = class _SeamHttpAcsEntrances {
1370
+ constructor(apiKeyOrOptions = {}) {
1371
+ const options = parseOptions(apiKeyOrOptions);
1372
+ this.client = "client" in options ? options.client : createClient(options);
1373
+ this.defaults = limitToSeamHttpRequestOptions(options);
1374
+ }
1375
+ static fromClient(client, options = {}) {
1376
+ const constructorOptions = { ...options, client };
1377
+ if (!isSeamHttpOptionsWithClient(constructorOptions)) {
1378
+ throw new SeamHttpInvalidOptionsError("Missing client");
1379
+ }
1380
+ return new _SeamHttpAcsEntrances(constructorOptions);
1381
+ }
1382
+ static fromApiKey(apiKey, options = {}) {
1383
+ const constructorOptions = { ...options, apiKey };
1384
+ if (!isSeamHttpOptionsWithApiKey(constructorOptions)) {
1385
+ throw new SeamHttpInvalidOptionsError("Missing apiKey");
1386
+ }
1387
+ return new _SeamHttpAcsEntrances(constructorOptions);
1388
+ }
1389
+ static fromClientSessionToken(clientSessionToken, options = {}) {
1390
+ const constructorOptions = { ...options, clientSessionToken };
1391
+ if (!isSeamHttpOptionsWithClientSessionToken(constructorOptions)) {
1392
+ throw new SeamHttpInvalidOptionsError("Missing clientSessionToken");
1393
+ }
1394
+ return new _SeamHttpAcsEntrances(constructorOptions);
1395
+ }
1396
+ static async fromPublishableKey(publishableKey, userIdentifierKey, options = {}) {
1397
+ warnOnInsecureuserIdentifierKey(userIdentifierKey);
1398
+ const clientOptions = parseOptions({ ...options, publishableKey });
1399
+ if (isSeamHttpOptionsWithClient(clientOptions)) {
1400
+ throw new SeamHttpInvalidOptionsError(
1401
+ "The client option cannot be used with SeamHttp.fromPublishableKey"
1402
+ );
1403
+ }
1404
+ const client = createClient(clientOptions);
1405
+ const clientSessions = SeamHttpClientSessions.fromClient(client);
1406
+ const { token } = await clientSessions.getOrCreate({
1407
+ user_identifier_key: userIdentifierKey
1408
+ });
1409
+ return _SeamHttpAcsEntrances.fromClientSessionToken(token, options);
1410
+ }
1411
+ static fromConsoleSessionToken(consoleSessionToken, workspaceId, options = {}) {
1412
+ const constructorOptions = { ...options, consoleSessionToken, workspaceId };
1413
+ if (!isSeamHttpOptionsWithConsoleSessionToken(constructorOptions)) {
1414
+ throw new SeamHttpInvalidOptionsError(
1415
+ "Missing consoleSessionToken or workspaceId"
1416
+ );
1417
+ }
1418
+ return new _SeamHttpAcsEntrances(constructorOptions);
1419
+ }
1420
+ static fromPersonalAccessToken(personalAccessToken, workspaceId, options = {}) {
1421
+ const constructorOptions = { ...options, personalAccessToken, workspaceId };
1422
+ if (!isSeamHttpOptionsWithPersonalAccessToken(constructorOptions)) {
1423
+ throw new SeamHttpInvalidOptionsError(
1424
+ "Missing personalAccessToken or workspaceId"
1425
+ );
1426
+ }
1427
+ return new _SeamHttpAcsEntrances(constructorOptions);
1428
+ }
1429
+ async get(body) {
1430
+ const { data } = await this.client.request({
1431
+ url: "/acs/entrances/get",
1432
+ method: "post",
1433
+ data: body
1434
+ });
1435
+ return data.acs_entrance;
1436
+ }
1437
+ async grantAccess(body) {
1438
+ await this.client.request({
1439
+ url: "/acs/entrances/grant_access",
1440
+ method: "post",
1441
+ data: body
1442
+ });
1443
+ }
1444
+ async list(body) {
1445
+ const { data } = await this.client.request({
1446
+ url: "/acs/entrances/list",
1447
+ method: "post",
1448
+ data: body
1449
+ });
1450
+ return data.acs_entrances;
1451
+ }
1452
+ };
1453
+
1218
1454
  // src/lib/seam/connect/routes/acs-systems.ts
1219
1455
  var SeamHttpAcsSystems = class _SeamHttpAcsSystems {
1220
1456
  constructor(apiKeyOrOptions = {}) {
@@ -1487,9 +1723,21 @@ var SeamHttpAcs = class _SeamHttpAcs {
1487
1723
  get accessGroups() {
1488
1724
  return SeamHttpAcsAccessGroups.fromClient(this.client, this.defaults);
1489
1725
  }
1726
+ get credentialPools() {
1727
+ return SeamHttpAcsCredentialPools.fromClient(this.client, this.defaults);
1728
+ }
1729
+ get credentialProvisioningAutomations() {
1730
+ return SeamHttpAcsCredentialProvisioningAutomations.fromClient(
1731
+ this.client,
1732
+ this.defaults
1733
+ );
1734
+ }
1490
1735
  get credentials() {
1491
1736
  return SeamHttpAcsCredentials.fromClient(this.client, this.defaults);
1492
1737
  }
1738
+ get entrances() {
1739
+ return SeamHttpAcsEntrances.fromClient(this.client, this.defaults);
1740
+ }
1493
1741
  get systems() {
1494
1742
  return SeamHttpAcsSystems.fromClient(this.client, this.defaults);
1495
1743
  }
@@ -1773,6 +2021,16 @@ var SeamHttpConnectedAccounts = class _SeamHttpConnectedAccounts {
1773
2021
  });
1774
2022
  return data.connected_accounts;
1775
2023
  }
2024
+ async update(body) {
2025
+ const { data } = await this.client.request(
2026
+ {
2027
+ url: "/connected_accounts/update",
2028
+ method: "post",
2029
+ data: body
2030
+ }
2031
+ );
2032
+ return data.connected_account;
2033
+ }
1776
2034
  };
1777
2035
 
1778
2036
  // src/lib/seam/connect/routes/devices-unmanaged.ts
@@ -3045,7 +3303,10 @@ exports.SeamHttpAccessCodes = SeamHttpAccessCodes;
3045
3303
  exports.SeamHttpAccessCodesUnmanaged = SeamHttpAccessCodesUnmanaged;
3046
3304
  exports.SeamHttpAcs = SeamHttpAcs;
3047
3305
  exports.SeamHttpAcsAccessGroups = SeamHttpAcsAccessGroups;
3306
+ exports.SeamHttpAcsCredentialPools = SeamHttpAcsCredentialPools;
3307
+ exports.SeamHttpAcsCredentialProvisioningAutomations = SeamHttpAcsCredentialProvisioningAutomations;
3048
3308
  exports.SeamHttpAcsCredentials = SeamHttpAcsCredentials;
3309
+ exports.SeamHttpAcsEntrances = SeamHttpAcsEntrances;
3049
3310
  exports.SeamHttpAcsSystems = SeamHttpAcsSystems;
3050
3311
  exports.SeamHttpAcsUsers = SeamHttpAcsUsers;
3051
3312
  exports.SeamHttpActionAttempts = SeamHttpActionAttempts;