@gitpod/gitpod-protocol 0.1.5-svenefftinge-patch-1.0 → 0.1.5-tar-telemetry-settings-data.2

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 (300) hide show
  1. package/data/gitpod-schema.json +25 -24
  2. package/lib/accounting-protocol.d.ts +155 -0
  3. package/lib/accounting-protocol.d.ts.map +1 -0
  4. package/lib/accounting-protocol.js +109 -0
  5. package/lib/accounting-protocol.js.map +1 -0
  6. package/lib/admin-protocol.d.ts +30 -4
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js +15 -0
  9. package/lib/admin-protocol.js.map +1 -1
  10. package/lib/analytics.d.ts +45 -0
  11. package/lib/analytics.d.ts.map +1 -0
  12. package/lib/analytics.js +10 -0
  13. package/lib/analytics.js.map +1 -0
  14. package/lib/context-url.d.ts +31 -0
  15. package/lib/context-url.d.ts.map +1 -0
  16. package/lib/context-url.js +102 -0
  17. package/lib/context-url.js.map +1 -0
  18. package/lib/context-url.spec.d.ts +14 -0
  19. package/lib/context-url.spec.d.ts.map +1 -0
  20. package/lib/context-url.spec.js +94 -0
  21. package/lib/context-url.spec.js.map +1 -0
  22. package/lib/email-protocol.d.ts +1 -2
  23. package/lib/email-protocol.d.ts.map +1 -1
  24. package/lib/email-protocol.js +4 -4
  25. package/lib/email-protocol.js.map +1 -1
  26. package/lib/encryption/container-module.js +5 -4
  27. package/lib/encryption/container-module.js.map +1 -1
  28. package/lib/encryption/encryption-engine.js +19 -20
  29. package/lib/encryption/encryption-engine.js.map +1 -1
  30. package/lib/encryption/encryption-engine.spec.js +29 -36
  31. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  32. package/lib/encryption/encryption-service.js +29 -43
  33. package/lib/encryption/encryption-service.js.map +1 -1
  34. package/lib/encryption/key-provider.js +25 -30
  35. package/lib/encryption/key-provider.js.map +1 -1
  36. package/lib/env.d.ts +1 -2
  37. package/lib/env.d.ts.map +1 -1
  38. package/lib/env.js +20 -21
  39. package/lib/env.js.map +1 -1
  40. package/lib/gitpod-file-parser.js +25 -41
  41. package/lib/gitpod-file-parser.js.map +1 -1
  42. package/lib/gitpod-file-parser.spec.js +116 -116
  43. package/lib/gitpod-file-parser.spec.js.map +1 -1
  44. package/lib/gitpod-service.d.ts +161 -20
  45. package/lib/gitpod-service.d.ts.map +1 -1
  46. package/lib/gitpod-service.js +170 -256
  47. package/lib/gitpod-service.js.map +1 -1
  48. package/lib/headless-workspace-log.d.ts +8 -11
  49. package/lib/headless-workspace-log.d.ts.map +1 -1
  50. package/lib/headless-workspace-log.js +4 -7
  51. package/lib/headless-workspace-log.js.map +1 -1
  52. package/lib/ide-protocol.d.ts +105 -0
  53. package/lib/ide-protocol.d.ts.map +1 -0
  54. package/lib/ide-protocol.js +8 -0
  55. package/lib/ide-protocol.js.map +1 -0
  56. package/lib/index.d.ts +6 -0
  57. package/lib/index.d.ts.map +1 -1
  58. package/lib/index.js +7 -1
  59. package/lib/index.js.map +1 -1
  60. package/lib/installation-admin-protocol.d.ts +27 -0
  61. package/lib/installation-admin-protocol.d.ts.map +1 -0
  62. package/lib/installation-admin-protocol.js +30 -0
  63. package/lib/installation-admin-protocol.js.map +1 -0
  64. package/lib/messaging/browser/connection.d.ts +5 -3
  65. package/lib/messaging/browser/connection.d.ts.map +1 -1
  66. package/lib/messaging/browser/connection.js +183 -33
  67. package/lib/messaging/browser/connection.js.map +1 -1
  68. package/lib/messaging/browser/window-connection.js +35 -55
  69. package/lib/messaging/browser/window-connection.js.map +1 -1
  70. package/lib/messaging/client-call-metrics.d.ts +35 -0
  71. package/lib/messaging/client-call-metrics.d.ts.map +1 -0
  72. package/lib/messaging/client-call-metrics.js +83 -0
  73. package/lib/messaging/client-call-metrics.js.map +1 -0
  74. package/lib/messaging/error.d.ts +4 -1
  75. package/lib/messaging/error.d.ts.map +1 -1
  76. package/lib/messaging/error.js +8 -2
  77. package/lib/messaging/error.js.map +1 -1
  78. package/lib/messaging/handler.d.ts +10 -0
  79. package/lib/messaging/handler.d.ts.map +1 -1
  80. package/lib/messaging/node/connection.d.ts +1 -17
  81. package/lib/messaging/node/connection.d.ts.map +1 -1
  82. package/lib/messaging/node/connection.js +23 -59
  83. package/lib/messaging/node/connection.js.map +1 -1
  84. package/lib/messaging/proxy-factory.d.ts +2 -0
  85. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  86. package/lib/messaging/proxy-factory.js +74 -159
  87. package/lib/messaging/proxy-factory.js.map +1 -1
  88. package/lib/oss-allowlist.d.ts +14 -0
  89. package/lib/oss-allowlist.d.ts.map +1 -0
  90. package/lib/oss-allowlist.js +8 -0
  91. package/lib/oss-allowlist.js.map +1 -0
  92. package/lib/payment-protocol.d.ts +18 -0
  93. package/lib/payment-protocol.d.ts.map +1 -0
  94. package/lib/payment-protocol.js +13 -0
  95. package/lib/payment-protocol.js.map +1 -0
  96. package/lib/permission.d.ts +8 -1
  97. package/lib/permission.d.ts.map +1 -1
  98. package/lib/permission.js +36 -15
  99. package/lib/permission.js.map +1 -1
  100. package/lib/plans.d.ts +210 -0
  101. package/lib/plans.d.ts.map +1 -0
  102. package/lib/plans.js +570 -0
  103. package/lib/plans.js.map +1 -0
  104. package/lib/protocol.d.ts +118 -52
  105. package/lib/protocol.d.ts.map +1 -1
  106. package/lib/protocol.js +116 -130
  107. package/lib/protocol.js.map +1 -1
  108. package/lib/snapshot-url.d.ts +14 -0
  109. package/lib/snapshot-url.d.ts.map +1 -0
  110. package/lib/snapshot-url.js +26 -0
  111. package/lib/snapshot-url.js.map +1 -0
  112. package/{src/util/without.ts → lib/snapshot-url.spec.d.ts} +2 -3
  113. package/lib/snapshot-url.spec.d.ts.map +1 -0
  114. package/lib/snapshot-url.spec.js +41 -0
  115. package/lib/snapshot-url.spec.js.map +1 -0
  116. package/lib/team-subscription-protocol.d.ts +73 -0
  117. package/lib/team-subscription-protocol.d.ts.map +1 -0
  118. package/lib/team-subscription-protocol.js +63 -0
  119. package/lib/team-subscription-protocol.js.map +1 -0
  120. package/lib/teams-projects-protocol.d.ts +113 -0
  121. package/lib/teams-projects-protocol.d.ts.map +1 -0
  122. package/lib/teams-projects-protocol.js +30 -0
  123. package/lib/teams-projects-protocol.js.map +1 -0
  124. package/lib/util/analytics.d.ts +8 -0
  125. package/lib/util/analytics.d.ts.map +1 -0
  126. package/lib/util/analytics.js +79 -0
  127. package/lib/util/analytics.js.map +1 -0
  128. package/lib/util/async-iterator.js +55 -133
  129. package/lib/util/async-iterator.js.map +1 -1
  130. package/lib/util/cancelable.js +17 -59
  131. package/lib/util/cancelable.js.map +1 -1
  132. package/lib/util/date-time.js +8 -8
  133. package/lib/util/date-time.js.map +1 -1
  134. package/lib/util/deferred.js +10 -12
  135. package/lib/util/deferred.js.map +1 -1
  136. package/lib/util/disposable.js +26 -39
  137. package/lib/util/disposable.js.map +1 -1
  138. package/lib/util/event.js +58 -74
  139. package/lib/util/event.js.map +1 -1
  140. package/lib/util/garbage-collected-cache.d.ts +1 -0
  141. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  142. package/lib/util/garbage-collected-cache.js +26 -46
  143. package/lib/util/garbage-collected-cache.js.map +1 -1
  144. package/lib/util/generate-workspace-id.d.ts +1 -1
  145. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  146. package/lib/util/generate-workspace-id.js +31 -68
  147. package/lib/util/generate-workspace-id.js.map +1 -1
  148. package/lib/util/generate-workspace-id.spec.js +57 -78
  149. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  150. package/lib/util/gitpod-cookie.d.ts +20 -0
  151. package/lib/util/gitpod-cookie.d.ts.map +1 -0
  152. package/lib/util/gitpod-cookie.js +44 -0
  153. package/lib/util/gitpod-cookie.js.map +1 -0
  154. package/lib/util/gitpod-host-url.d.ts +1 -2
  155. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  156. package/lib/util/gitpod-host-url.js +95 -98
  157. package/lib/util/gitpod-host-url.js.map +1 -1
  158. package/lib/util/gitpod-host-url.spec.d.ts +7 -1
  159. package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
  160. package/lib/util/gitpod-host-url.spec.js +103 -31
  161. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  162. package/lib/util/grpc.d.ts +15 -0
  163. package/lib/util/grpc.d.ts.map +1 -0
  164. package/lib/util/grpc.js +18 -0
  165. package/lib/util/grpc.js.map +1 -0
  166. package/lib/util/jaeger-client-types.d.ts +68 -0
  167. package/lib/util/jaeger-client-types.d.ts.map +1 -0
  168. package/lib/util/{without.js → jaeger-client-types.js} +1 -1
  169. package/lib/util/jaeger-client-types.js.map +1 -0
  170. package/lib/util/logging.d.ts +49 -33
  171. package/lib/util/logging.d.ts.map +1 -1
  172. package/lib/util/logging.js +107 -110
  173. package/lib/util/logging.js.map +1 -1
  174. package/lib/util/make-link.js +2 -2
  175. package/lib/util/make-link.js.map +1 -1
  176. package/lib/util/parse-workspace-id.d.ts +10 -0
  177. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  178. package/lib/util/parse-workspace-id.js +32 -7
  179. package/lib/util/parse-workspace-id.js.map +1 -1
  180. package/lib/util/parse-workspace-id.spec.d.ts +4 -0
  181. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  182. package/lib/util/parse-workspace-id.spec.js +123 -84
  183. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  184. package/lib/util/queue.js +16 -55
  185. package/lib/util/queue.js.map +1 -1
  186. package/lib/util/queue.spec.js +144 -288
  187. package/lib/util/queue.spec.js.map +1 -1
  188. package/lib/util/repeat.d.ts +15 -0
  189. package/lib/util/repeat.d.ts.map +1 -0
  190. package/lib/util/repeat.js +55 -0
  191. package/lib/util/repeat.js.map +1 -0
  192. package/lib/util/semaphore.js +15 -46
  193. package/lib/util/semaphore.js.map +1 -1
  194. package/lib/util/skip-if.js +6 -6
  195. package/lib/util/skip-if.js.map +1 -1
  196. package/lib/util/timeutil.js +28 -16
  197. package/lib/util/timeutil.js.map +1 -1
  198. package/lib/util/timeutil.spec.js +21 -24
  199. package/lib/util/timeutil.spec.js.map +1 -1
  200. package/lib/util/tracing.d.ts +51 -5
  201. package/lib/util/tracing.d.ts.map +1 -1
  202. package/lib/util/tracing.js +197 -62
  203. package/lib/util/tracing.js.map +1 -1
  204. package/lib/util/tracing.spec.d.ts +7 -0
  205. package/lib/util/tracing.spec.d.ts.map +1 -0
  206. package/lib/util/tracing.spec.js +121 -0
  207. package/lib/util/tracing.spec.js.map +1 -0
  208. package/lib/util/workspace-port-authentication.js +3 -2
  209. package/lib/util/workspace-port-authentication.js.map +1 -1
  210. package/lib/workspace-cluster.d.ts +76 -0
  211. package/lib/workspace-cluster.d.ts.map +1 -0
  212. package/lib/workspace-cluster.js +33 -0
  213. package/lib/workspace-cluster.js.map +1 -0
  214. package/lib/workspace-instance.d.ts +24 -2
  215. package/lib/workspace-instance.d.ts.map +1 -1
  216. package/lib/wsready.d.ts +1 -1
  217. package/lib/wsready.js +2 -2
  218. package/package.json +31 -17
  219. package/pkg-yarn.lock +17 -9
  220. package/provenance-bundle.jsonl +2 -0
  221. package/src/accounting-protocol.ts +229 -0
  222. package/src/admin-protocol.ts +52 -5
  223. package/src/analytics.ts +54 -0
  224. package/src/context-url.spec.ts +53 -0
  225. package/src/context-url.ts +107 -0
  226. package/src/email-protocol.ts +2 -3
  227. package/src/env.ts +10 -10
  228. package/src/gitpod-service.ts +234 -38
  229. package/src/headless-workspace-log.ts +7 -11
  230. package/src/ide-frontend-service.ts +1 -1
  231. package/src/ide-protocol.ts +119 -0
  232. package/src/index.ts +7 -1
  233. package/src/installation-admin-protocol.ts +42 -0
  234. package/src/messaging/browser/connection.ts +195 -14
  235. package/src/messaging/client-call-metrics.ts +97 -0
  236. package/src/messaging/error.ts +11 -2
  237. package/src/messaging/handler.ts +12 -0
  238. package/src/messaging/node/connection.ts +21 -68
  239. package/src/messaging/proxy-factory.ts +14 -6
  240. package/src/oss-allowlist.ts +15 -0
  241. package/src/payment-protocol.ts +20 -0
  242. package/src/permission.ts +24 -4
  243. package/src/plans.ts +632 -0
  244. package/src/protocol.ts +192 -82
  245. package/src/snapshot-url.spec.ts +25 -0
  246. package/src/snapshot-url.ts +27 -0
  247. package/src/team-subscription-protocol.ts +113 -0
  248. package/src/teams-projects-protocol.ts +147 -0
  249. package/src/util/analytics.ts +87 -0
  250. package/src/util/deferred.ts +1 -1
  251. package/src/util/garbage-collected-cache.ts +9 -3
  252. package/src/util/generate-workspace-id.spec.ts +20 -3
  253. package/src/util/generate-workspace-id.ts +22 -2
  254. package/src/util/gitpod-cookie.ts +39 -0
  255. package/src/util/gitpod-host-url.spec.ts +25 -1
  256. package/src/util/gitpod-host-url.ts +22 -13
  257. package/src/util/grpc.ts +15 -0
  258. package/src/util/jaeger-client-types.ts +102 -0
  259. package/src/util/logging.ts +102 -38
  260. package/src/util/parse-workspace-id.spec.ts +21 -1
  261. package/src/util/parse-workspace-id.ts +32 -6
  262. package/src/util/queue.spec.ts +1 -1
  263. package/src/util/repeat.ts +45 -0
  264. package/src/util/semaphore.ts +2 -2
  265. package/src/util/skip-if.ts +1 -1
  266. package/src/util/timeutil.ts +4 -4
  267. package/src/util/tracing.spec.ts +83 -0
  268. package/src/util/tracing.ts +183 -17
  269. package/src/workspace-cluster.ts +104 -0
  270. package/src/workspace-instance.ts +45 -13
  271. package/src/wsready.ts +2 -2
  272. package/lib/messaging/connection-error-handler.d.ts +0 -27
  273. package/lib/messaging/connection-error-handler.d.ts.map +0 -1
  274. package/lib/messaging/connection-error-handler.js +0 -46
  275. package/lib/messaging/connection-error-handler.js.map +0 -1
  276. package/lib/util/context-url.d.ts +0 -13
  277. package/lib/util/context-url.d.ts.map +0 -1
  278. package/lib/util/context-url.js +0 -26
  279. package/lib/util/context-url.js.map +0 -1
  280. package/lib/util/context-url.spec.d.ts +0 -10
  281. package/lib/util/context-url.spec.d.ts.map +0 -1
  282. package/lib/util/context-url.spec.js +0 -52
  283. package/lib/util/context-url.spec.js.map +0 -1
  284. package/lib/util/repeater.d.ts +0 -22
  285. package/lib/util/repeater.d.ts.map +0 -1
  286. package/lib/util/repeater.js +0 -118
  287. package/lib/util/repeater.js.map +0 -1
  288. package/lib/util/safe-promise.d.ts +0 -11
  289. package/lib/util/safe-promise.d.ts.map +0 -1
  290. package/lib/util/safe-promise.js +0 -34
  291. package/lib/util/safe-promise.js.map +0 -1
  292. package/lib/util/without.d.ts +0 -7
  293. package/lib/util/without.d.ts.map +0 -1
  294. package/lib/util/without.js.map +0 -1
  295. package/src/messaging/connection-error-handler.ts +0 -62
  296. package/src/util/context-url.spec.ts +0 -25
  297. package/src/util/context-url.ts +0 -23
  298. package/src/util/jaeger-client.d.ts +0 -105
  299. package/src/util/repeater.ts +0 -49
  300. package/src/util/safe-promise.ts +0 -26
@@ -5,14 +5,19 @@
5
5
  */
6
6
 
7
7
  import {
8
- User, WorkspaceInfo, WorkspaceCreationResult, UserMessage, WorkspaceInstanceUser,
9
- WhitelistedRepository, WorkspaceImageBuild, AuthProviderInfo, Branding, CreateWorkspaceMode,
8
+ User, WorkspaceInfo, WorkspaceCreationResult, WorkspaceInstanceUser,
9
+ WhitelistedRepository, WorkspaceImageBuild, AuthProviderInfo, CreateWorkspaceMode,
10
10
  Token, UserEnvVarValue, ResolvePluginsParams, PreparePluginUploadParams, Terms,
11
- ResolvedPlugins, Configuration, InstallPluginsParams, UninstallPluginParams, UserInfo, GitpodTokenType, GitpodToken, AuthProviderEntry
11
+ ResolvedPlugins, Configuration, InstallPluginsParams, UninstallPluginParams, UserInfo, GitpodTokenType,
12
+ GitpodToken, AuthProviderEntry, GuessGitTokenScopesParams, GuessedGitTokenScopes, ProjectEnvVar
12
13
  } from './protocol';
14
+ import {
15
+ Team, TeamMemberInfo,
16
+ TeamMembershipInvite, Project, TeamMemberRole, PrebuildWithStatus, StartPrebuildResult, PartialProject
17
+ } from './teams-projects-protocol';
13
18
  import { JsonRpcProxy, JsonRpcServer } from './messaging/proxy-factory';
14
19
  import { Disposable, CancellationTokenSource } from 'vscode-jsonrpc';
15
- import { HeadlessLogEvent } from './headless-workspace-log';
20
+ import { HeadlessLogUrls } from './headless-workspace-log';
16
21
  import { WorkspaceInstance, WorkspaceInstancePort, WorkspaceInstancePhase } from './workspace-instance';
17
22
  import { AdminServer } from './admin-protocol';
18
23
  import { GitpodHostUrl } from './util/gitpod-host-url';
@@ -20,11 +25,20 @@ import { WebSocketConnectionProvider } from './messaging/browser/connection';
20
25
  import { PermissionName } from './permission';
21
26
  import { LicenseService } from './license-protocol';
22
27
  import { Emitter } from './util/event';
28
+ import { AccountStatement, CreditAlert } from './accounting-protocol';
29
+ import { GithubUpgradeURL, PlanCoupon } from './payment-protocol';
30
+ import { TeamSubscription, TeamSubscriptionSlot, TeamSubscriptionSlotResolved } from './team-subscription-protocol';
31
+ import { RemotePageMessage, RemoteTrackMessage, RemoteIdentifyMessage } from './analytics';
32
+ import { IDEServer } from './ide-protocol';
33
+ import { InstallationAdminSettings, TelemetryData } from './installation-admin-protocol';
23
34
 
24
35
  export interface GitpodClient {
25
36
  onInstanceUpdate(instance: WorkspaceInstance): void;
26
37
  onWorkspaceImageBuildLogs: WorkspaceImageBuild.LogCallback;
27
- onHeadlessWorkspaceLogs(evt: HeadlessLogEvent): void;
38
+
39
+ onPrebuildUpdate(update: PrebuildWithStatus): void;
40
+
41
+ onCreditAlert(creditAlert: CreditAlert): void;
28
42
 
29
43
  //#region propagating reconnection to iframe
30
44
  notifyDidOpenConnection(): void;
@@ -33,18 +47,18 @@ export interface GitpodClient {
33
47
  }
34
48
 
35
49
  export const GitpodServer = Symbol('GitpodServer');
36
- export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer, LicenseService {
50
+ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer, LicenseService, IDEServer {
37
51
  // User related API
38
52
  getLoggedInUser(): Promise<User>;
39
53
  getTerms(): Promise<Terms>;
40
54
  updateLoggedInUser(user: Partial<User>): Promise<User>;
41
55
  getAuthProviders(): Promise<AuthProviderInfo[]>;
42
56
  getOwnAuthProviders(): Promise<AuthProviderEntry[]>;
43
- updateOwnAuthProvider(params: GitpodServer.UpdateOwnAuthProviderParams): Promise<void>;
57
+ updateOwnAuthProvider(params: GitpodServer.UpdateOwnAuthProviderParams): Promise<AuthProviderEntry>;
44
58
  deleteOwnAuthProvider(params: GitpodServer.DeleteOwnAuthProviderParams): Promise<void>;
45
- getBranding(): Promise<Branding>;
46
59
  getConfiguration(): Promise<Configuration>;
47
60
  getToken(query: GitpodServer.GetTokenSearchOptions): Promise<Token | undefined>;
61
+ getGitpodTokenScopes(tokenHash: string): Promise<string[]>;
48
62
  /**
49
63
  * @deprecated
50
64
  */
@@ -58,8 +72,15 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
58
72
  getWorkspaceOwner(workspaceId: string): Promise<UserInfo | undefined>;
59
73
  getWorkspaceUsers(workspaceId: string): Promise<WorkspaceInstanceUser[]>;
60
74
  getFeaturedRepositories(): Promise<WhitelistedRepository[]>;
75
+ getSuggestedContextURLs(): Promise<string[]>;
76
+ /**
77
+ * **Security:**
78
+ * Sensitive information like an owner token is erased, since it allows access for all team members.
79
+ * If you need to access an owner token use `getOwnerToken` instead.
80
+ */
61
81
  getWorkspace(id: string): Promise<WorkspaceInfo>;
62
82
  isWorkspaceOwner(workspaceId: string): Promise<boolean>;
83
+ getOwnerToken(workspaceId: string): Promise<string>;
63
84
 
64
85
  /**
65
86
  * Creates and starts a workspace for the given context URL.
@@ -76,8 +97,8 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
76
97
  updateWorkspaceUserPin(id: string, action: GitpodServer.PinAction): Promise<void>;
77
98
  sendHeartBeat(options: GitpodServer.SendHeartBeatOptions): Promise<void>;
78
99
  watchWorkspaceImageBuildLogs(workspaceId: string): Promise<void>;
79
- watchHeadlessWorkspaceLogs(workspaceId: string): Promise<void>;
80
100
  isPrebuildDone(pwsid: string): Promise<boolean>;
101
+ getHeadlessLog(instanceId: string): Promise<HeadlessLogUrls>;
81
102
 
82
103
  // Workspace timeout
83
104
  setWorkspaceTimeout(workspaceId: string, duration: WorkspaceTimeoutDuration): Promise<SetWorkspaceTimeoutResult>;
@@ -91,19 +112,52 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
91
112
  openPort(workspaceId: string, port: WorkspaceInstancePort): Promise<WorkspaceInstancePort | undefined>;
92
113
  closePort(workspaceId: string, port: number): Promise<void>;
93
114
 
94
- // User messages
95
- getUserMessages(options: GitpodServer.GetUserMessagesOptions): Promise<UserMessage[]>;
96
- updateUserMessages(options: GitpodServer.UpdateUserMessagesOptions): Promise<void>;
97
-
98
115
  // User storage
99
116
  getUserStorageResource(options: GitpodServer.GetUserStorageResourceOptions): Promise<string>;
100
117
  updateUserStorageResource(options: GitpodServer.UpdateUserStorageResourceOptions): Promise<void>;
101
118
 
102
- // user env vars
119
+ // User env vars
103
120
  getEnvVars(): Promise<UserEnvVarValue[]>;
121
+ getAllEnvVars(): Promise<UserEnvVarValue[]>;
104
122
  setEnvVar(variable: UserEnvVarValue): Promise<void>;
105
123
  deleteEnvVar(variable: UserEnvVarValue): Promise<void>;
106
124
 
125
+ // Teams
126
+ getTeams(): Promise<Team[]>;
127
+ getTeamMembers(teamId: string): Promise<TeamMemberInfo[]>;
128
+ createTeam(name: string): Promise<Team>;
129
+ joinTeam(inviteId: string): Promise<Team>;
130
+ setTeamMemberRole(teamId: string, userId: string, role: TeamMemberRole): Promise<void>;
131
+ removeTeamMember(teamId: string, userId: string): Promise<void>;
132
+ getGenericInvite(teamId: string): Promise<TeamMembershipInvite>;
133
+ resetGenericInvite(inviteId: string): Promise<TeamMembershipInvite>;
134
+ deleteTeam(teamId: string, userId: string): Promise<void>;
135
+
136
+ // Admin Settings
137
+ adminGetSettings(): Promise<InstallationAdminSettings>;
138
+ adminUpdateSettings(settings: InstallationAdminSettings): Promise<void>;
139
+ adminGetTelemetryData(): Promise<TelemetryData>;
140
+
141
+ // Projects
142
+ getProviderRepositoriesForUser(params: GetProviderRepositoriesParams): Promise<ProviderRepository[]>;
143
+ createProject(params: CreateProjectParams): Promise<Project>;
144
+ deleteProject(projectId: string): Promise<void>;
145
+ getTeamProjects(teamId: string): Promise<Project[]>;
146
+ getUserProjects(): Promise<Project[]>;
147
+ getProjectOverview(projectId: string): Promise<Project.Overview | undefined>;
148
+ findPrebuilds(params: FindPrebuildsParams): Promise<PrebuildWithStatus[]>;
149
+ triggerPrebuild(projectId: string, branchName: string | null): Promise<StartPrebuildResult>;
150
+ cancelPrebuild(projectId: string, prebuildId: string): Promise<void>;
151
+ fetchProjectRepositoryConfiguration(projectId: string): Promise<string | undefined>;
152
+ guessProjectConfiguration(projectId: string): Promise<string | undefined>;
153
+ fetchRepositoryConfiguration(cloneUrl: string): Promise<string | undefined>;
154
+ guessRepositoryConfiguration(cloneUrl: string): Promise<string | undefined>;
155
+ setProjectConfiguration(projectId: string, configString: string): Promise<void>;
156
+ updateProjectPartial(partialProject: PartialProject): Promise<void>;
157
+ setProjectEnvironmentVariable(projectId: string, name: string, value: string, censored: boolean): Promise<void>;
158
+ getProjectEnvironmentVariables(projectId: string): Promise<ProjectEnvVar[]>;
159
+ deleteProjectEnvironmentVariable(variableId: string): Promise<void>;
160
+
107
161
  // content service
108
162
  getContentBlobUploadUrl(name: string): Promise<string>
109
163
  getContentBlobDownloadUrl(name: string): Promise<string>
@@ -118,10 +172,15 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
118
172
  registerGithubApp(installationId: string): Promise<void>;
119
173
 
120
174
  /**
121
- * Stores a new snapshot for the given workspace and bucketId
175
+ * Stores a new snapshot for the given workspace and bucketId. Returns _before_ the actual snapshot is done. To wait for that, use `waitForSnapshot`.
122
176
  * @return the snapshot id
123
177
  */
124
178
  takeSnapshot(options: GitpodServer.TakeSnapshotOptions): Promise<string>;
179
+ /**
180
+ *
181
+ * @param snapshotId
182
+ */
183
+ waitForSnapshot(snapshotId: string): Promise<void>;
125
184
 
126
185
  /**
127
186
  * Returns the list of snapshots that exist for a workspace.
@@ -146,6 +205,105 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
146
205
  resolvePlugins(workspaceId: string, params: ResolvePluginsParams): Promise<ResolvedPlugins>;
147
206
  installUserPlugins(params: InstallPluginsParams): Promise<boolean>;
148
207
  uninstallUserPlugin(params: UninstallPluginParams): Promise<boolean>;
208
+
209
+ guessGitTokenScopes(params: GuessGitTokenScopesParams): Promise<GuessedGitTokenScopes>;
210
+
211
+ /**
212
+ * gitpod.io concerns
213
+ */
214
+ isStudent(): Promise<boolean>;
215
+ /**
216
+ *
217
+ */
218
+ getAccountStatement(options: GitpodServer.GetAccountStatementOptions): Promise<AccountStatement | undefined>;
219
+ getRemainingUsageHours(): Promise<number>;
220
+
221
+ /**
222
+ *
223
+ */
224
+ getChargebeeSiteId(): Promise<string>;
225
+ createPortalSession(): Promise<{}>;
226
+ checkout(planId: string, planQuantity?: number): Promise<{}>;
227
+ getAvailableCoupons(): Promise<PlanCoupon[]>;
228
+ getAppliedCoupons(): Promise<PlanCoupon[]>;
229
+
230
+ getShowPaymentUI(): Promise<boolean>;
231
+ isChargebeeCustomer(): Promise<boolean>;
232
+
233
+ subscriptionUpgradeTo(subscriptionId: string, chargebeePlanId: string): Promise<void>;
234
+ subscriptionDowngradeTo(subscriptionId: string, chargebeePlanId: string): Promise<void>;
235
+ subscriptionCancel(subscriptionId: string): Promise<void>;
236
+ subscriptionCancelDowngrade(subscriptionId: string): Promise<void>;
237
+
238
+ tsGet(): Promise<TeamSubscription[]>;
239
+ tsGetSlots(): Promise<TeamSubscriptionSlotResolved[]>;
240
+ tsGetUnassignedSlot(teamSubscriptionId: string): Promise<TeamSubscriptionSlot | undefined>
241
+ tsAddSlots(teamSubscriptionId: string, quantity: number): Promise<void>;
242
+ tsAssignSlot(teamSubscriptionId: string, teamSubscriptionSlotId: string, identityStr: string | undefined): Promise<void>
243
+ tsReassignSlot(teamSubscriptionId: string, teamSubscriptionSlotId: string, newIdentityStr: string): Promise<void>;
244
+ tsDeactivateSlot(teamSubscriptionId: string, teamSubscriptionSlotId: string): Promise<void>;
245
+ tsReactivateSlot(teamSubscriptionId: string, teamSubscriptionSlotId: string): Promise<void>;
246
+
247
+ getGithubUpgradeUrls(): Promise<GithubUpgradeURL[]>;
248
+
249
+ /**
250
+ * Analytics
251
+ */
252
+ trackEvent(event: RemoteTrackMessage): Promise<void>;
253
+ trackLocation(event: RemotePageMessage): Promise<void>;
254
+ identifyUser(event: RemoteIdentifyMessage): Promise<void>;
255
+ }
256
+
257
+ export interface RateLimiterError {
258
+ method?: string,
259
+
260
+ /**
261
+ * Retry after this many seconds, earliest.
262
+ * cmp.: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
263
+ */
264
+ retryAfter: number,
265
+ }
266
+
267
+ export interface CreateProjectParams {
268
+ name: string;
269
+ slug?: string;
270
+ account: string;
271
+ provider: string;
272
+ cloneUrl: string;
273
+ teamId?: string;
274
+ userId?: string;
275
+ appInstallationId: string;
276
+ }
277
+ export interface FindPrebuildsParams {
278
+ projectId: string;
279
+ branch?: string;
280
+ latest?: boolean;
281
+ prebuildId?: string;
282
+ // default: 30
283
+ limit?: number;
284
+ }
285
+ export interface GetProviderRepositoriesParams {
286
+ provider: string;
287
+ hints?: { installationId: string } | object;
288
+ }
289
+ export interface ProviderRepository {
290
+ name: string;
291
+ path?: string;
292
+ account: string;
293
+ accountAvatarUrl: string;
294
+ cloneUrl: string;
295
+ updatedAt: string;
296
+ installationId?: number;
297
+ installationUpdatedAt?: string;
298
+
299
+ inUse?: { userName: string };
300
+ }
301
+
302
+ export interface ClientHeaderFields {
303
+ ip?: string;
304
+ userAgent?: string;
305
+ dnt?: string;
306
+ clientRegion?: string;
149
307
  }
150
308
 
151
309
  export const WorkspaceTimeoutValues = ["30m", "60m", "180m"] as const;
@@ -158,6 +316,7 @@ export const createServerMock = function <C extends GitpodClient, S extends Gitp
158
316
  methods.setClient = methods.setClient || (() => { });
159
317
  methods.dispose = methods.dispose || (() => { });
160
318
  return new Proxy<JsonRpcProxy<S>>(methods as any as JsonRpcProxy<S>, {
319
+ // @ts-ignore
161
320
  get: (target: S, property: keyof S) => {
162
321
  const result = target[property];
163
322
  if (!result) {
@@ -190,6 +349,8 @@ export namespace GitpodServer {
190
349
  limit?: number;
191
350
  searchString?: string;
192
351
  pinnedOnly?: boolean;
352
+ projectId?: string | string[];
353
+ includeWithoutProject?: boolean;
193
354
  }
194
355
  export interface GetAccountStatementOptions {
195
356
  date?: string;
@@ -197,6 +358,7 @@ export namespace GitpodServer {
197
358
  export interface CreateWorkspaceOptions {
198
359
  contextUrl: string;
199
360
  mode?: CreateWorkspaceMode;
361
+ forceDefaultConfig?: boolean;
200
362
  }
201
363
  export interface StartWorkspaceOptions {
202
364
  forceDefaultImage: boolean;
@@ -204,13 +366,8 @@ export namespace GitpodServer {
204
366
  export interface TakeSnapshotOptions {
205
367
  workspaceId: string;
206
368
  layoutData?: string;
207
- }
208
- export interface GetUserMessagesOptions {
209
- readonly releaseNotes?: boolean;
210
- readonly workspaceInstanceId: string;
211
- }
212
- export interface UpdateUserMessagesOptions {
213
- readonly messageIds: string[];
369
+ /* this is here to enable backwards-compatibility and untangling rollout between workspace, IDE and meta */
370
+ dontWait?: boolean;
214
371
  }
215
372
  export interface GetUserStorageResourceOptions {
216
373
  readonly uri: string;
@@ -252,10 +409,12 @@ export class GitpodCompositeClient<Client extends GitpodClient> implements Gitpo
252
409
 
253
410
  public registerClient(client: Partial<Client>): Disposable {
254
411
  this.clients.push(client);
255
- const index = this.clients.length;
256
412
  return {
257
413
  dispose: () => {
258
- this.clients.slice(index, 1);
414
+ const index = this.clients.indexOf(client);
415
+ if (index > -1) {
416
+ this.clients.splice(index, 1);
417
+ }
259
418
  }
260
419
  }
261
420
  }
@@ -272,11 +431,11 @@ export class GitpodCompositeClient<Client extends GitpodClient> implements Gitpo
272
431
  }
273
432
  }
274
433
 
275
- onWorkspaceImageBuildLogs(info: WorkspaceImageBuild.StateInfo, content: WorkspaceImageBuild.LogContent | undefined): void {
434
+ onPrebuildUpdate(update: PrebuildWithStatus): void {
276
435
  for (const client of this.clients) {
277
- if (client.onWorkspaceImageBuildLogs) {
436
+ if (client.onPrebuildUpdate) {
278
437
  try {
279
- client.onWorkspaceImageBuildLogs(info, content);
438
+ client.onPrebuildUpdate(update);
280
439
  } catch (error) {
281
440
  console.error(error)
282
441
  }
@@ -284,11 +443,11 @@ export class GitpodCompositeClient<Client extends GitpodClient> implements Gitpo
284
443
  }
285
444
  }
286
445
 
287
- onHeadlessWorkspaceLogs(evt: HeadlessLogEvent): void {
446
+ onWorkspaceImageBuildLogs(info: WorkspaceImageBuild.StateInfo, content: WorkspaceImageBuild.LogContent | undefined): void {
288
447
  for (const client of this.clients) {
289
- if (client.onHeadlessWorkspaceLogs) {
448
+ if (client.onWorkspaceImageBuildLogs) {
290
449
  try {
291
- client.onHeadlessWorkspaceLogs(evt);
450
+ client.onWorkspaceImageBuildLogs(info, content);
292
451
  } catch (error) {
293
452
  console.error(error)
294
453
  }
@@ -320,6 +479,18 @@ export class GitpodCompositeClient<Client extends GitpodClient> implements Gitpo
320
479
  }
321
480
  }
322
481
 
482
+ onCreditAlert(creditAlert: CreditAlert): void {
483
+ for (const client of this.clients) {
484
+ if (client.onCreditAlert) {
485
+ try {
486
+ client.onCreditAlert(creditAlert);
487
+ } catch (error) {
488
+ console.error(error)
489
+ }
490
+ }
491
+ }
492
+ }
493
+
323
494
  }
324
495
 
325
496
  export type GitpodService = GitpodServiceImpl<GitpodClient, GitpodServer>;
@@ -340,7 +511,7 @@ export class WorkspaceInstanceUpdateListener {
340
511
  private readonly onDidChangeEmitter = new Emitter<void>();
341
512
  readonly onDidChange = this.onDidChangeEmitter.event;
342
513
 
343
- private source: 'sync' | 'update' = 'sync';
514
+ private source: 'sync' | 'update' = 'sync';
344
515
 
345
516
  get info(): WorkspaceInfo {
346
517
  return this._info;
@@ -432,11 +603,15 @@ export class WorkspaceInstanceUpdateListener {
432
603
 
433
604
  }
434
605
 
606
+ export interface GitpodServiceOptions {
607
+ onReconnect?: () => (void | Promise<void>)
608
+ }
609
+
435
610
  export class GitpodServiceImpl<Client extends GitpodClient, Server extends GitpodServer> {
436
611
 
437
612
  private readonly compositeClient = new GitpodCompositeClient<Client>();
438
613
 
439
- constructor(public readonly server: JsonRpcProxy<Server>) {
614
+ constructor(public readonly server: JsonRpcProxy<Server>, private options?: GitpodServiceOptions) {
440
615
  server.setClient(this.compositeClient);
441
616
  server.onDidOpenConnection(() => this.compositeClient.notifyDidOpenConnection());
442
617
  server.onDidCloseConnection(() => this.compositeClient.notifyDidCloseConnection());
@@ -456,13 +631,34 @@ export class GitpodServiceImpl<Client extends GitpodClient, Server extends Gitpo
456
631
  this.instanceListeners.set(workspaceId, listener);
457
632
  return listener;
458
633
  }
634
+
635
+ async reconnect(): Promise<void> {
636
+ if (this.options?.onReconnect) {
637
+ await this.options.onReconnect();
638
+ }
639
+ }
459
640
  }
460
641
 
461
- export function createGitpodService<C extends GitpodClient, S extends GitpodServer>(serverUrl: string) {
462
- const url = new GitpodHostUrl(serverUrl)
463
- .asWebsocket()
464
- .withApi({ pathname: GitpodServerPath });
642
+ export function createGitpodService<C extends GitpodClient, S extends GitpodServer>(serverUrl: string | Promise<string>) {
643
+ const toWsUrl = (serverUrl: string) => {
644
+ return new GitpodHostUrl(serverUrl)
645
+ .asWebsocket()
646
+ .withApi({ pathname: GitpodServerPath })
647
+ .toString();
648
+ };
649
+ let url: string | Promise<string>;
650
+ if (typeof serverUrl === "string") {
651
+ url = toWsUrl(serverUrl);
652
+ } else {
653
+ url = serverUrl.then(url => toWsUrl(url));
654
+ }
655
+
465
656
  const connectionProvider = new WebSocketConnectionProvider();
466
- const gitpodServer = connectionProvider.createProxy<S>(url.toString());
467
- return new GitpodServiceImpl<C, S>(gitpodServer);
657
+ let onReconnect = () => { };
658
+ const gitpodServer = connectionProvider.createProxy<S>(url, undefined, {
659
+ onListening: socket => {
660
+ onReconnect = () => socket.reconnect();
661
+ }
662
+ });
663
+ return new GitpodServiceImpl<C, S>(gitpodServer, { onReconnect });
468
664
  }
@@ -22,21 +22,17 @@ export namespace HeadlessWorkspaceEventType {
22
22
  }
23
23
  }
24
24
 
25
- export interface HeadlessLogEvent {
25
+ export interface HeadlessWorkspaceEvent {
26
26
  workspaceID: string;
27
27
  text: string;
28
28
  type: HeadlessWorkspaceEventType;
29
29
  }
30
30
 
31
- export enum TheiaHeadlessLogType {
32
- TaskLogLabel = "workspaceTaskOutput",
33
- TaskFailedLabel = "workspaceTaskFailed",
34
- TaskSuccessfulLabel = "workspaceTaskDone"
31
+ export interface HeadlessLogUrls {
32
+ // A map of id to URL
33
+ streams: { [streamID: string]: string };
35
34
  }
36
35
 
37
- export interface TheiaHeadlessLogMessage {
38
- type: TheiaHeadlessLogType;
39
- data?: string;
40
- error?: string;
41
- snapshotURL?: string;
42
- }
36
+ /** cmp. @const HEADLESS_LOG_STREAM_STATUS_CODE_REGEX */
37
+ export const HEADLESS_LOG_STREAM_STATUS_CODE = "X-LogStream-StatusCode";
38
+ export const HEADLESS_LOG_STREAM_STATUS_CODE_REGEX = /X-LogStream-StatusCode: ([0-9]{3})/;
@@ -7,7 +7,7 @@
7
7
  import { Event } from "./util/event";
8
8
  import { Disposable } from "./util/disposable";
9
9
 
10
- export type IDEFrontendState = 'init' | 'ready' | 'terminated';
10
+ export type IDEFrontendState = 'init' | 'ready' | 'terminated';
11
11
 
12
12
  export interface IDEFrontendService {
13
13
  readonly state: IDEFrontendState;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2021 Gitpod GmbH. All rights reserved.
3
+ * Licensed under the GNU Affero General Public License (AGPL).
4
+ * See License-AGPL.txt in the project root for license information.
5
+ */
6
+
7
+ /**
8
+ * `IDEServer` provides a list of available IDEs.
9
+ */
10
+ export interface IDEServer {
11
+ /**
12
+ * Returns the IDE preferences.
13
+ */
14
+ getIDEOptions(): Promise<IDEOptions>;
15
+ }
16
+
17
+ export interface IDEOptions {
18
+ /**
19
+ * A list of available IDEs.
20
+ */
21
+ options: { [key: string]: IDEOption };
22
+
23
+ /**
24
+ * The default (browser) IDE when the user has not specified one.
25
+ */
26
+ defaultIde: string;
27
+
28
+ /**
29
+ * The default desktop IDE when the user has not specified one.
30
+ */
31
+ defaultDesktopIde: string;
32
+
33
+ /**
34
+ * Client specific IDE options.
35
+ */
36
+ clients?: { [id: string]: IDEClient };
37
+ }
38
+
39
+ export interface IDEClient {
40
+ /**
41
+ * The default desktop IDE when the user has not specified one.
42
+ */
43
+ defaultDesktopIDE?: string;
44
+
45
+ /**
46
+ * Desktop IDEs supported by the client.
47
+ */
48
+ desktopIDEs?: string[]
49
+
50
+ /**
51
+ * Steps to install the client on user machine.
52
+ */
53
+ installationSteps?: string[]
54
+ }
55
+
56
+ export interface IDEOption {
57
+ /**
58
+ * To ensure a stable order one can set an `orderKey`.
59
+ */
60
+ orderKey?: string;
61
+
62
+ /**
63
+ * Human readable title text of the IDE (plain text only).
64
+ */
65
+ title: string;
66
+
67
+ /**
68
+ * The type of the IDE, currently 'browser' or 'desktop'.
69
+ */
70
+ type: 'browser' | 'desktop';
71
+
72
+ /**
73
+ * The logo for the IDE. That could be a key in (see
74
+ * components/dashboard/src/images/ideLogos.ts) or a URL.
75
+ */
76
+ logo: string;
77
+
78
+ /**
79
+ * Text of an optional tooltip (plain text only).
80
+ */
81
+ tooltip?: string;
82
+
83
+ /**
84
+ * Text of an optional label next to the IDE option like “Insiders” (plain
85
+ * text only).
86
+ */
87
+ label?: string;
88
+
89
+ /**
90
+ * Notes to the IDE option that are renderd in the preferences when a user
91
+ * chooses this IDE.
92
+ */
93
+ notes?: string[];
94
+
95
+ /**
96
+ * If `true` this IDE option is not visible in the IDE preferences.
97
+ */
98
+ hidden?: boolean;
99
+
100
+ /**
101
+ * The image ref to the IDE image.
102
+ */
103
+ image: string;
104
+
105
+ /**
106
+ * The latest image ref to the IDE image, this image ref always resolve to digest.
107
+ */
108
+ latestImage?: string;
109
+
110
+ /**
111
+ * When this is `true`, the tag of this image is resolved to the latest
112
+ * image digest regularly.
113
+ *
114
+ * This is useful if this image points to a tag like `nightly` that will be
115
+ * updated regularly. When `resolveImageDigest` is `true`, we make sure that
116
+ * we resolve the tag regularly to the most recent image version.
117
+ */
118
+ resolveImageDigest?: boolean;
119
+ }
package/src/index.ts CHANGED
@@ -13,4 +13,10 @@ export * from './license-protocol';
13
13
  export * from './workspace-instance';
14
14
  export * from './permission';
15
15
  export * from './admin-protocol';
16
- export * from './email-protocol';
16
+ export * from './email-protocol';
17
+ export * from './headless-workspace-log';
18
+ export * from './context-url';
19
+ export * from './teams-projects-protocol';
20
+ export * from './snapshot-url';
21
+ export * from './oss-allowlist';
22
+ export * from './installation-admin-protocol';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3
+ * Licensed under the GNU Affero General Public License (AGPL).
4
+ * See License-AGPL.txt in the project root for license information.
5
+ */
6
+
7
+ import { v4 as uuidv4 } from 'uuid';
8
+
9
+ const InstallationAdminSettingsPrototype = {
10
+ sendTelemetry: true
11
+ }
12
+
13
+ export type InstallationAdminSettings = typeof InstallationAdminSettingsPrototype;
14
+
15
+ export namespace InstallationAdminSettings {
16
+ export function fields(): (keyof InstallationAdminSettings)[] {
17
+ return Object.keys(InstallationAdminSettingsPrototype) as (keyof InstallationAdminSettings)[];
18
+ }
19
+ }
20
+
21
+ export interface InstallationAdmin {
22
+ id: string;
23
+ settings: InstallationAdminSettings;
24
+ }
25
+
26
+ export interface TelemetryData {
27
+ installationAdmin: InstallationAdmin
28
+ totalUsers: number
29
+ totalWorkspaces: number
30
+ totalInstances: number
31
+ }
32
+
33
+ export namespace InstallationAdmin {
34
+ export function createDefault(): InstallationAdmin {
35
+ return {
36
+ id: uuidv4(),
37
+ settings: {
38
+ ...InstallationAdminSettingsPrototype,
39
+ }
40
+ };
41
+ }
42
+ }