@gitpod/gitpod-protocol 0.1.5-se-multi-repo.39 → 0.1.5-se-usage-view.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 (342) hide show
  1. package/data/gitpod-schema.json +69 -3
  2. package/lib/accounting-protocol.d.ts +18 -10
  3. package/lib/accounting-protocol.d.ts.map +1 -1
  4. package/lib/accounting-protocol.js +34 -32
  5. package/lib/accounting-protocol.js.map +1 -1
  6. package/lib/admin-protocol.d.ts +5 -0
  7. package/lib/admin-protocol.d.ts.map +1 -1
  8. package/lib/admin-protocol.js.map +1 -1
  9. package/lib/analytics.d.ts.map +1 -1
  10. package/lib/analytics.js.map +1 -1
  11. package/lib/attribution.d.ts +20 -0
  12. package/lib/attribution.d.ts.map +1 -0
  13. package/lib/attribution.js +40 -0
  14. package/lib/attribution.js.map +1 -0
  15. package/lib/auth.d.ts.map +1 -1
  16. package/lib/billing-mode.d.ts +40 -0
  17. package/lib/billing-mode.d.ts.map +1 -0
  18. package/lib/billing-mode.js +36 -0
  19. package/lib/billing-mode.js.map +1 -0
  20. package/lib/blocked-repositories-protocol.d.ts +13 -0
  21. package/lib/blocked-repositories-protocol.d.ts.map +1 -0
  22. package/lib/blocked-repositories-protocol.js +8 -0
  23. package/lib/blocked-repositories-protocol.js.map +1 -0
  24. package/lib/context-url.d.ts.map +1 -1
  25. package/lib/context-url.js +4 -4
  26. package/lib/context-url.js.map +1 -1
  27. package/lib/context-url.spec.d.ts.map +1 -1
  28. package/lib/context-url.spec.js +20 -5
  29. package/lib/context-url.spec.js.map +1 -1
  30. package/lib/email-protocol.d.ts +1 -1
  31. package/lib/email-protocol.d.ts.map +1 -1
  32. package/lib/email-protocol.js.map +1 -1
  33. package/lib/encryption/container-module.d.ts.map +1 -1
  34. package/lib/encryption/container-module.js +1 -1
  35. package/lib/encryption/container-module.js.map +1 -1
  36. package/lib/encryption/encryption-engine.d.ts.map +1 -1
  37. package/lib/encryption/encryption-engine.js +7 -7
  38. package/lib/encryption/encryption-engine.js.map +1 -1
  39. package/lib/encryption/encryption-engine.spec.d.ts.map +1 -1
  40. package/lib/encryption/encryption-engine.spec.js +2 -3
  41. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  42. package/lib/encryption/encryption-service.d.ts.map +1 -1
  43. package/lib/encryption/encryption-service.js +1 -1
  44. package/lib/encryption/encryption-service.js.map +1 -1
  45. package/lib/encryption/key-provider.d.ts.map +1 -1
  46. package/lib/encryption/key-provider.js +7 -9
  47. package/lib/encryption/key-provider.js.map +1 -1
  48. package/lib/env.d.ts +0 -5
  49. package/lib/env.d.ts.map +1 -1
  50. package/lib/env.js +1 -20
  51. package/lib/env.js.map +1 -1
  52. package/lib/experiments/always-default.d.ts +8 -0
  53. package/lib/experiments/always-default.d.ts.map +1 -0
  54. package/lib/experiments/always-default.js +20 -0
  55. package/lib/experiments/always-default.js.map +1 -0
  56. package/lib/experiments/configcat-server.d.ts +10 -0
  57. package/lib/experiments/configcat-server.d.ts.map +1 -0
  58. package/lib/experiments/configcat-server.js +36 -0
  59. package/lib/experiments/configcat-server.js.map +1 -0
  60. package/lib/experiments/configcat.d.ts +22 -0
  61. package/lib/experiments/configcat.d.ts.map +1 -0
  62. package/lib/experiments/configcat.js +53 -0
  63. package/lib/experiments/configcat.js.map +1 -0
  64. package/lib/experiments/types.d.ts +23 -0
  65. package/lib/experiments/types.d.ts.map +1 -0
  66. package/lib/experiments/types.js +10 -0
  67. package/lib/experiments/types.js.map +1 -0
  68. package/lib/gitpod-file-parser.d.ts.map +1 -1
  69. package/lib/gitpod-file-parser.js +6 -6
  70. package/lib/gitpod-file-parser.js.map +1 -1
  71. package/lib/gitpod-file-parser.spec.js +42 -39
  72. package/lib/gitpod-file-parser.spec.js.map +1 -1
  73. package/lib/gitpod-service.d.ts +57 -26
  74. package/lib/gitpod-service.d.ts.map +1 -1
  75. package/lib/gitpod-service.js +40 -33
  76. package/lib/gitpod-service.js.map +1 -1
  77. package/lib/headless-workspace-log.d.ts.map +1 -1
  78. package/lib/headless-workspace-log.js +1 -1
  79. package/lib/headless-workspace-log.js.map +1 -1
  80. package/lib/ide-frontend-service.d.ts +1 -1
  81. package/lib/ide-protocol.d.ts +14 -6
  82. package/lib/ide-protocol.d.ts.map +1 -1
  83. package/lib/index.d.ts +17 -16
  84. package/lib/index.d.ts.map +1 -1
  85. package/lib/index.js +1 -0
  86. package/lib/index.js.map +1 -1
  87. package/lib/installation-admin-protocol.d.ts +3 -0
  88. package/lib/installation-admin-protocol.d.ts.map +1 -1
  89. package/lib/installation-admin-protocol.js +3 -2
  90. package/lib/installation-admin-protocol.js.map +1 -1
  91. package/lib/license-protocol.d.ts +7 -0
  92. package/lib/license-protocol.d.ts.map +1 -1
  93. package/lib/license-protocol.js.map +1 -1
  94. package/lib/messaging/browser/connection.d.ts +1 -1
  95. package/lib/messaging/browser/connection.d.ts.map +1 -1
  96. package/lib/messaging/browser/connection.js +19 -19
  97. package/lib/messaging/browser/connection.js.map +1 -1
  98. package/lib/messaging/browser/window-connection.d.ts +4 -4
  99. package/lib/messaging/browser/window-connection.d.ts.map +1 -1
  100. package/lib/messaging/browser/window-connection.js +9 -6
  101. package/lib/messaging/browser/window-connection.js.map +1 -1
  102. package/lib/messaging/client-call-metrics.d.ts +2 -18
  103. package/lib/messaging/client-call-metrics.d.ts.map +1 -1
  104. package/lib/messaging/client-call-metrics.js +21 -22
  105. package/lib/messaging/client-call-metrics.js.map +1 -1
  106. package/lib/messaging/error.d.ts +6 -1
  107. package/lib/messaging/error.d.ts.map +1 -1
  108. package/lib/messaging/error.js +13 -3
  109. package/lib/messaging/error.js.map +1 -1
  110. package/lib/messaging/handler.d.ts.map +1 -1
  111. package/lib/messaging/handler.js +1 -1
  112. package/lib/messaging/node/connection.js +8 -8
  113. package/lib/messaging/node/connection.js.map +1 -1
  114. package/lib/messaging/proxy-factory.d.ts +1 -1
  115. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  116. package/lib/messaging/proxy-factory.js +7 -9
  117. package/lib/messaging/proxy-factory.js.map +1 -1
  118. package/lib/payment-protocol.d.ts.map +1 -1
  119. package/lib/payment-protocol.js +1 -1
  120. package/lib/payment-protocol.js.map +1 -1
  121. package/lib/permission.d.ts +2 -2
  122. package/lib/permission.d.ts.map +1 -1
  123. package/lib/permission.js +12 -23
  124. package/lib/permission.js.map +1 -1
  125. package/lib/plans.d.ts +4 -3
  126. package/lib/plans.d.ts.map +1 -1
  127. package/lib/plans.js +210 -171
  128. package/lib/plans.js.map +1 -1
  129. package/lib/protocol.d.ts +109 -35
  130. package/lib/protocol.d.ts.map +1 -1
  131. package/lib/protocol.js +248 -91
  132. package/lib/protocol.js.map +1 -1
  133. package/{src/theia-plugins.ts → lib/protocol.spec.d.ts} +2 -6
  134. package/lib/protocol.spec.d.ts.map +1 -0
  135. package/lib/protocol.spec.js +127 -0
  136. package/lib/protocol.spec.js.map +1 -0
  137. package/lib/snapshot-url.spec.js.map +1 -1
  138. package/lib/team-subscription-protocol.d.ts +20 -3
  139. package/lib/team-subscription-protocol.d.ts.map +1 -1
  140. package/lib/team-subscription-protocol.js +20 -5
  141. package/lib/team-subscription-protocol.js.map +1 -1
  142. package/lib/teams-projects-protocol.d.ts +21 -3
  143. package/lib/teams-projects-protocol.d.ts.map +1 -1
  144. package/lib/teams-projects-protocol.js +1 -1
  145. package/lib/teams-projects-protocol.js.map +1 -1
  146. package/lib/typings/globals.d.ts +2 -2
  147. package/lib/typings/globals.d.ts.map +1 -1
  148. package/lib/usage.d.ts +97 -0
  149. package/lib/usage.d.ts.map +1 -0
  150. package/lib/usage.js +14 -0
  151. package/lib/usage.js.map +1 -0
  152. package/lib/util/analytics.d.ts.map +1 -1
  153. package/lib/util/analytics.js +6 -6
  154. package/lib/util/analytics.js.map +1 -1
  155. package/lib/util/async-iterator.d.ts.map +1 -1
  156. package/lib/util/async-iterator.js +3 -3
  157. package/lib/util/async-iterator.js.map +1 -1
  158. package/lib/util/cancelable.js.map +1 -1
  159. package/lib/util/date-time.js +6 -6
  160. package/lib/util/date-time.js.map +1 -1
  161. package/lib/util/debug-app.d.ts +25 -0
  162. package/lib/util/debug-app.d.ts.map +1 -0
  163. package/lib/util/debug-app.js +100 -0
  164. package/lib/util/debug-app.js.map +1 -0
  165. package/lib/util/deferred.js.map +1 -1
  166. package/lib/util/disposable.d.ts.map +1 -1
  167. package/lib/util/disposable.js +2 -2
  168. package/lib/util/disposable.js.map +1 -1
  169. package/lib/util/event.d.ts.map +1 -1
  170. package/lib/util/event.js +5 -3
  171. package/lib/util/event.js.map +1 -1
  172. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  173. package/lib/util/garbage-collected-cache.js +6 -1
  174. package/lib/util/garbage-collected-cache.js.map +1 -1
  175. package/lib/util/generate-workspace-id.d.ts +5 -0
  176. package/lib/util/generate-workspace-id.d.ts.map +1 -1
  177. package/lib/util/generate-workspace-id.js +446 -442
  178. package/lib/util/generate-workspace-id.js.map +1 -1
  179. package/lib/util/generate-workspace-id.spec.js +18 -7
  180. package/lib/util/generate-workspace-id.spec.js.map +1 -1
  181. package/lib/util/gitpod-cookie.d.ts +1 -1
  182. package/lib/util/gitpod-cookie.d.ts.map +1 -1
  183. package/lib/util/gitpod-cookie.js +0 -3
  184. package/lib/util/gitpod-cookie.js.map +1 -1
  185. package/lib/util/gitpod-host-url.d.ts +3 -0
  186. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  187. package/lib/util/gitpod-host-url.js +49 -29
  188. package/lib/util/gitpod-host-url.js.map +1 -1
  189. package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
  190. package/lib/util/gitpod-host-url.spec.js +15 -5
  191. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  192. package/lib/util/grpc.d.ts +19 -0
  193. package/lib/util/grpc.d.ts.map +1 -1
  194. package/lib/util/grpc.js +73 -1
  195. package/lib/util/grpc.js.map +1 -1
  196. package/lib/util/jaeger-client-types.d.ts.map +1 -1
  197. package/lib/util/logging.d.ts +1 -1
  198. package/lib/util/logging.d.ts.map +1 -1
  199. package/lib/util/logging.js +31 -25
  200. package/lib/util/logging.js.map +1 -1
  201. package/lib/util/logging.spec.d.ts +7 -0
  202. package/lib/util/logging.spec.d.ts.map +1 -0
  203. package/lib/util/logging.spec.js +52 -0
  204. package/lib/util/logging.spec.js.map +1 -0
  205. package/lib/util/make-link.js +5 -5
  206. package/lib/util/make-link.js.map +1 -1
  207. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  208. package/lib/util/parse-workspace-id.js +1 -2
  209. package/lib/util/parse-workspace-id.js.map +1 -1
  210. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  211. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  212. package/lib/util/queue.spec.js +9 -6
  213. package/lib/util/queue.spec.js.map +1 -1
  214. package/lib/util/semaphore.d.ts.map +1 -1
  215. package/lib/util/semaphore.js.map +1 -1
  216. package/lib/util/skip-if.d.ts.map +1 -1
  217. package/lib/util/skip-if.js.map +1 -1
  218. package/lib/util/timeutil.d.ts +2 -0
  219. package/lib/util/timeutil.d.ts.map +1 -1
  220. package/lib/util/timeutil.js +15 -3
  221. package/lib/util/timeutil.js.map +1 -1
  222. package/lib/util/timeutil.spec.d.ts +1 -0
  223. package/lib/util/timeutil.spec.d.ts.map +1 -1
  224. package/lib/util/timeutil.spec.js +10 -0
  225. package/lib/util/timeutil.spec.js.map +1 -1
  226. package/lib/util/tracing.d.ts +6 -6
  227. package/lib/util/tracing.d.ts.map +1 -1
  228. package/lib/util/tracing.js +14 -16
  229. package/lib/util/tracing.js.map +1 -1
  230. package/lib/util/tracing.spec.js +3 -3
  231. package/lib/util/tracing.spec.js.map +1 -1
  232. package/lib/util/workspace-port-authentication.d.ts +7 -7
  233. package/lib/util/workspace-port-authentication.d.ts.map +1 -1
  234. package/lib/util/workspace-port-authentication.js +8 -11
  235. package/lib/util/workspace-port-authentication.js.map +1 -1
  236. package/lib/webhook-event.d.ts +44 -0
  237. package/lib/webhook-event.d.ts.map +1 -0
  238. package/lib/{theia-plugins.js → webhook-event.js} +2 -2
  239. package/lib/webhook-event.js.map +1 -0
  240. package/lib/workspace-class.d.ts +14 -0
  241. package/lib/workspace-class.d.ts.map +1 -0
  242. package/lib/workspace-class.js +8 -0
  243. package/lib/workspace-class.js.map +1 -0
  244. package/lib/workspace-cluster.d.ts +6 -8
  245. package/lib/workspace-cluster.d.ts.map +1 -1
  246. package/lib/workspace-cluster.js +2 -4
  247. package/lib/workspace-cluster.js.map +1 -1
  248. package/lib/workspace-instance.d.ts +20 -3
  249. package/lib/workspace-instance.d.ts.map +1 -1
  250. package/lib/wsready.d.ts +3 -3
  251. package/lib/wsready.d.ts.map +1 -1
  252. package/lib/wsready.js +0 -2
  253. package/lib/wsready.js.map +1 -1
  254. package/package.json +12 -6
  255. package/pkg-yarn.lock +8 -5
  256. package/provenance-bundle.jsonl +1 -1
  257. package/src/accounting-protocol.ts +66 -51
  258. package/src/admin-protocol.ts +30 -20
  259. package/src/analytics.ts +21 -21
  260. package/src/attribution.ts +48 -0
  261. package/src/auth.ts +2 -2
  262. package/src/billing-mode.ts +67 -0
  263. package/src/blocked-repositories-protocol.ts +13 -0
  264. package/src/context-url.spec.ts +25 -11
  265. package/src/context-url.ts +80 -78
  266. package/src/email-protocol.ts +5 -6
  267. package/src/encryption/container-module.ts +2 -3
  268. package/src/encryption/encryption-engine.spec.ts +9 -8
  269. package/src/encryption/encryption-engine.ts +14 -14
  270. package/src/encryption/encryption-service.ts +4 -5
  271. package/src/encryption/key-provider.ts +16 -19
  272. package/src/env.ts +0 -22
  273. package/src/experiments/always-default.ts +24 -0
  274. package/src/experiments/configcat-server.ts +41 -0
  275. package/src/experiments/configcat.ts +58 -0
  276. package/src/experiments/types.ts +35 -0
  277. package/src/gitpod-file-parser.spec.ts +55 -61
  278. package/src/gitpod-file-parser.ts +16 -17
  279. package/src/gitpod-service.ts +189 -111
  280. package/src/headless-workspace-log.ts +5 -4
  281. package/src/ide-frontend-service.ts +2 -2
  282. package/src/ide-protocol.ts +18 -8
  283. package/src/index.ts +17 -16
  284. package/src/installation-admin-protocol.ts +11 -8
  285. package/src/license-protocol.ts +12 -6
  286. package/src/messaging/browser/connection.ts +45 -47
  287. package/src/messaging/browser/window-connection.ts +39 -29
  288. package/src/messaging/client-call-metrics.ts +62 -82
  289. package/src/messaging/error.ts +20 -7
  290. package/src/messaging/handler.ts +6 -6
  291. package/src/messaging/node/connection.ts +8 -8
  292. package/src/messaging/proxy-factory.ts +23 -30
  293. package/src/oss-allowlist.ts +3 -3
  294. package/src/payment-protocol.ts +2 -2
  295. package/src/permission.ts +20 -31
  296. package/src/plans.ts +240 -189
  297. package/src/protocol.spec.ts +97 -0
  298. package/src/protocol.ts +456 -242
  299. package/src/snapshot-url.spec.ts +9 -7
  300. package/src/team-subscription-protocol.ts +57 -22
  301. package/src/teams-projects-protocol.ts +28 -8
  302. package/src/typings/globals.ts +4 -4
  303. package/src/usage.ts +128 -0
  304. package/src/util/analytics.ts +46 -42
  305. package/src/util/async-iterator.ts +4 -5
  306. package/src/util/cancelable.ts +3 -3
  307. package/src/util/date-time.ts +8 -8
  308. package/src/util/debug-app.ts +81 -0
  309. package/src/util/deferred.ts +6 -6
  310. package/src/util/disposable.ts +3 -6
  311. package/src/util/event.ts +9 -11
  312. package/src/util/garbage-collected-cache.ts +8 -6
  313. package/src/util/generate-workspace-id.spec.ts +26 -16
  314. package/src/util/generate-workspace-id.ts +460 -454
  315. package/src/util/gitpod-cookie.ts +8 -9
  316. package/src/util/gitpod-host-url.spec.ts +40 -13
  317. package/src/util/gitpod-host-url.ts +57 -33
  318. package/src/util/grpc.ts +90 -1
  319. package/src/util/jaeger-client-types.ts +2 -2
  320. package/src/util/logging.spec.ts +23 -0
  321. package/src/util/logging.ts +60 -42
  322. package/src/util/make-link.ts +6 -7
  323. package/src/util/parse-workspace-id.spec.ts +17 -8
  324. package/src/util/parse-workspace-id.ts +5 -6
  325. package/src/util/queue.spec.ts +27 -25
  326. package/src/util/repeat.ts +1 -1
  327. package/src/util/semaphore.ts +4 -6
  328. package/src/util/skip-if.ts +9 -6
  329. package/src/util/timeutil.spec.ts +19 -14
  330. package/src/util/timeutil.ts +27 -11
  331. package/src/util/tracing.spec.ts +28 -23
  332. package/src/util/tracing.ts +54 -51
  333. package/src/util/workspace-port-authentication.ts +10 -13
  334. package/src/webhook-event.ts +55 -0
  335. package/src/workspace-class.ts +14 -0
  336. package/src/workspace-cluster.ts +14 -13
  337. package/src/workspace-instance.ts +60 -24
  338. package/src/wsready.ts +5 -4
  339. package/data/builtin-theia-plugins.json +0 -372
  340. package/lib/theia-plugins.d.ts +0 -11
  341. package/lib/theia-plugins.d.ts.map +0 -1
  342. package/lib/theia-plugins.js.map +0 -1
package/src/protocol.ts CHANGED
@@ -10,24 +10,24 @@ import { Project } from "./teams-projects-protocol";
10
10
  import { createHash } from "crypto";
11
11
 
12
12
  export interface UserInfo {
13
- name?: string
13
+ name?: string;
14
14
  }
15
15
 
16
16
  export interface User {
17
17
  /** The user id */
18
- id: string
18
+ id: string;
19
19
 
20
20
  /** The timestamp when the user entry was created */
21
- creationDate: string
21
+ creationDate: string;
22
22
 
23
- avatarUrl?: string
23
+ avatarUrl?: string;
24
24
 
25
- name?: string
25
+ name?: string;
26
26
 
27
27
  /** Optional for backwards compatibility */
28
- fullName?: string
28
+ fullName?: string;
29
29
 
30
- identities: Identity[]
30
+ identities: Identity[];
31
31
 
32
32
  /**
33
33
  * Whether the user has been blocked to use our service, because of TOS violation for example.
@@ -45,38 +45,54 @@ export interface User {
45
45
  markedDeleted?: boolean;
46
46
 
47
47
  additionalData?: AdditionalUserData;
48
+
49
+ // Identifies an explicit team or user ID to which all the user's workspace usage should be attributed to (e.g. for billing purposes)
50
+ usageAttributionId?: string;
51
+
52
+ // The last time this user got verified somehow. The user is not verified if this is empty.
53
+ lastVerificationTime?: string;
54
+
55
+ // The phone number used for the last phone verification.
56
+ verificationPhoneNumber?: string;
48
57
  }
49
58
 
50
59
  export namespace User {
51
60
  export function is(data: any): data is User {
52
- return data
53
- && data.hasOwnProperty('id')
54
- && data.hasOwnProperty('identities')
61
+ return data && data.hasOwnProperty("id") && data.hasOwnProperty("identities");
55
62
  }
56
63
  export function getIdentity(user: User, authProviderId: string): Identity | undefined {
57
- return user.identities.find(id => id.authProviderId === authProviderId);
64
+ return user.identities.find((id) => id.authProviderId === authProviderId);
58
65
  }
59
66
  export function censor(user: User): User {
60
67
  const res = { ...user };
61
- delete (res.additionalData);
62
- res.identities = res.identities.map(i => {
63
- delete (i.tokens);
68
+ delete res.additionalData;
69
+ res.identities = res.identities.map((i) => {
70
+ delete i.tokens;
64
71
 
65
72
  // The user field is not in the Identity shape, but actually exists on DBIdentity.
66
73
  // Trying to push this object out via JSON RPC will fail because of the cyclic nature
67
74
  // of this field.
68
- delete ((i as any).user);
75
+ delete (i as any).user;
69
76
  return i;
70
77
  });
71
78
  return res;
72
79
  }
73
- export function getPrimaryEmail(user: User): string {
74
- const identities = user.identities.filter(i => !!i.primaryEmail);
80
+
81
+ /**
82
+ * Returns the stored email or if it doesn't exist returns the primaryEmail of the first identity this user signed up with.
83
+ * @param user
84
+ * @returns A primaryEmail, or undefined if there is none.
85
+ */
86
+ export function getPrimaryEmail(user: User): string | undefined {
87
+ if (user.additionalData?.profile?.emailAddress) {
88
+ return user.additionalData?.profile?.emailAddress;
89
+ }
90
+ const identities = user.identities.filter((i) => !!i.primaryEmail);
75
91
  if (identities.length <= 0) {
76
- throw new Error(`No identity with primary email for user: ${user.id}!`);
92
+ return undefined;
77
93
  }
78
94
 
79
- return identities[0].primaryEmail!;
95
+ return identities[0].primaryEmail || undefined;
80
96
  }
81
97
  export function getName(user: User): string | undefined {
82
98
  const name = user.fullName || user.name;
@@ -91,6 +107,91 @@ export namespace User {
91
107
  }
92
108
  return undefined;
93
109
  }
110
+
111
+ export function hasPreferredIde(user: User) {
112
+ return (
113
+ typeof user?.additionalData?.ideSettings?.defaultIde !== "undefined" ||
114
+ typeof user?.additionalData?.ideSettings?.useLatestVersion !== "undefined"
115
+ );
116
+ }
117
+
118
+ export function isOnboardingUser(user: User) {
119
+ return !hasPreferredIde(user);
120
+ }
121
+
122
+ export function migrationIDESettings(user: User) {
123
+ if (
124
+ !user?.additionalData?.ideSettings ||
125
+ Object.keys(user.additionalData.ideSettings).length === 0 ||
126
+ user.additionalData.ideSettings.settingVersion === "2.0"
127
+ ) {
128
+ return;
129
+ }
130
+ const newIDESettings: IDESettings = {
131
+ settingVersion: "2.0",
132
+ };
133
+ const ideSettings = user.additionalData.ideSettings;
134
+ if (ideSettings.useDesktopIde) {
135
+ if (ideSettings.defaultDesktopIde === "code-desktop") {
136
+ newIDESettings.defaultIde = "code-desktop";
137
+ } else if (ideSettings.defaultDesktopIde === "code-desktop-insiders") {
138
+ newIDESettings.defaultIde = "code-desktop";
139
+ newIDESettings.useLatestVersion = true;
140
+ } else {
141
+ newIDESettings.defaultIde = ideSettings.defaultDesktopIde;
142
+ newIDESettings.useLatestVersion = ideSettings.useLatestVersion;
143
+ }
144
+ } else {
145
+ const useLatest = ideSettings.defaultIde === "code-latest";
146
+ newIDESettings.defaultIde = "code";
147
+ newIDESettings.useLatestVersion = useLatest;
148
+ }
149
+ user.additionalData.ideSettings = newIDESettings;
150
+ }
151
+
152
+ export function getProfile(user: User): Profile {
153
+ return {
154
+ name: User.getName(user!) || "",
155
+ email: User.getPrimaryEmail(user!) || "",
156
+ company: user?.additionalData?.profile?.companyName,
157
+ avatarURL: user?.avatarUrl,
158
+ };
159
+ }
160
+
161
+ export function setProfile(user: User, profile: Profile): User {
162
+ user.fullName = profile.name;
163
+ user.avatarUrl = profile.avatarURL;
164
+
165
+ if (!user.additionalData) {
166
+ user.additionalData = {};
167
+ }
168
+ if (!user.additionalData.profile) {
169
+ user.additionalData.profile = {};
170
+ }
171
+ user.additionalData.profile.emailAddress = profile.email;
172
+ user.additionalData.profile.companyName = profile.company;
173
+ user.additionalData.profile.lastUpdatedDetailsNudge = new Date().toISOString();
174
+
175
+ return user;
176
+ }
177
+
178
+ // The actual Profile of a User
179
+ export interface Profile {
180
+ name: string;
181
+ email: string;
182
+ company?: string;
183
+ avatarURL?: string;
184
+ }
185
+ export namespace Profile {
186
+ export function hasChanges(before: Profile, after: Profile) {
187
+ return (
188
+ before.name !== after.name ||
189
+ before.email !== after.email ||
190
+ before.company !== after.company ||
191
+ before.avatarURL !== after.avatarURL
192
+ );
193
+ }
194
+ }
94
195
  }
95
196
 
96
197
  export interface AdditionalUserData {
@@ -99,15 +200,42 @@ export interface AdditionalUserData {
99
200
  featurePreview?: boolean;
100
201
  ideSettings?: IDESettings;
101
202
  // key is the name of the news, string the iso date when it was seen
102
- whatsNewSeen?: { [key: string]: string }
203
+ whatsNewSeen?: { [key: string]: string };
103
204
  // key is the name of the OAuth client i.e. local app, string the iso date when it was approved
104
205
  // TODO(rl): provide a management UX to allow rescinding of approval
105
- oauthClientsApproved?: { [key: string]: string }
206
+ oauthClientsApproved?: { [key: string]: string };
106
207
  // to remember GH Orgs the user installed/updated the GH App for
107
208
  knownGitHubOrgs?: string[];
108
-
109
209
  // Git clone URL pointing to the user's dotfile repo
110
210
  dotfileRepo?: string;
211
+ // preferred workspace classes
212
+ workspaceClasses?: WorkspaceClasses;
213
+ // additional user profile data
214
+ profile?: ProfileDetails;
215
+ }
216
+ export namespace AdditionalUserData {
217
+ export function set(user: User, partialData: Partial<AdditionalUserData>): User {
218
+ if (!user.additionalData) {
219
+ user.additionalData = {
220
+ ...partialData,
221
+ };
222
+ } else {
223
+ user.additionalData = {
224
+ ...user.additionalData,
225
+ ...partialData,
226
+ };
227
+ }
228
+ return user;
229
+ }
230
+ }
231
+ // The format in which we store User Profiles in
232
+ export interface ProfileDetails {
233
+ // when was the last time the user updated their profile information or has been nudged to do so.
234
+ lastUpdatedDetailsNudge?: string;
235
+ // the user's company name
236
+ companyName?: string;
237
+ // the user's email
238
+ emailAddress?: string;
111
239
  }
112
240
 
113
241
  export interface EmailNotificationSettings {
@@ -117,10 +245,18 @@ export interface EmailNotificationSettings {
117
245
  }
118
246
 
119
247
  export type IDESettings = {
120
- defaultIde?: string
121
- useDesktopIde?: boolean
122
- defaultDesktopIde?: string
123
- useLatestVersion?: boolean
248
+ settingVersion?: string;
249
+ defaultIde?: string;
250
+ // DEPRECATED: Use defaultIde after `settingVersion: 2.0`, no more specialify desktop or browser.
251
+ useDesktopIde?: boolean;
252
+ // DEPRECATED: Same with useDesktopIde.
253
+ defaultDesktopIde?: string;
254
+ useLatestVersion?: boolean;
255
+ };
256
+
257
+ export interface WorkspaceClasses {
258
+ regular: string;
259
+ prebuild: string;
124
260
  }
125
261
 
126
262
  export interface UserPlatform {
@@ -153,8 +289,13 @@ export interface UserFeatureSettings {
153
289
  * The values of this type MUST MATCH enum values in WorkspaceFeatureFlag from ws-manager/client/core_pb.d.ts
154
290
  * If they don't we'll break things during workspace startup.
155
291
  */
156
- export const WorkspaceFeatureFlags = { "full_workspace_backup": undefined, "fixed_resources": undefined };
157
- export type NamedWorkspaceFeatureFlag = keyof (typeof WorkspaceFeatureFlags);
292
+ export const WorkspaceFeatureFlags = {
293
+ full_workspace_backup: undefined,
294
+ persistent_volume_claim: undefined,
295
+ protected_secrets: undefined,
296
+ workspace_class_limiting: undefined,
297
+ };
298
+ export type NamedWorkspaceFeatureFlag = keyof typeof WorkspaceFeatureFlags;
158
299
 
159
300
  export interface EnvVarWithValue {
160
301
  name: string;
@@ -167,7 +308,7 @@ export interface ProjectEnvVarWithValue extends EnvVarWithValue {
167
308
  censored: boolean;
168
309
  }
169
310
 
170
- export type ProjectEnvVar = Omit<ProjectEnvVarWithValue, 'value'>;
311
+ export type ProjectEnvVar = Omit<ProjectEnvVarWithValue, "value">;
171
312
 
172
313
  export interface UserEnvVarValue extends EnvVarWithValue {
173
314
  id?: string;
@@ -180,6 +321,44 @@ export interface UserEnvVar extends UserEnvVarValue {
180
321
  }
181
322
 
182
323
  export namespace UserEnvVar {
324
+ /**
325
+ * @param variable
326
+ * @returns Either a string containing an error message or undefined.
327
+ */
328
+ export function validate(variable: UserEnvVarValue): string | undefined {
329
+ const name = variable.name;
330
+ const pattern = variable.repositoryPattern;
331
+ if (name.trim() === "") {
332
+ return "Name must not be empty.";
333
+ }
334
+ if (name.length > 255) {
335
+ return "Name too long. Maximum name length is 255 characters.";
336
+ }
337
+ if (!/^[a-zA-Z_]+[a-zA-Z0-9_]*$/.test(name)) {
338
+ return "Name must match /^[a-zA-Z_]+[a-zA-Z0-9_]*$/.";
339
+ }
340
+ if (variable.value.trim() === "") {
341
+ return "Value must not be empty.";
342
+ }
343
+ if (variable.value.length > 32767) {
344
+ return "Value too long. Maximum value length is 32767 characters.";
345
+ }
346
+ if (pattern.trim() === "") {
347
+ return "Scope must not be empty.";
348
+ }
349
+ const split = pattern.split("/");
350
+ if (split.length < 2) {
351
+ return "A scope must use the form 'organization/repo'.";
352
+ }
353
+ for (const name of split) {
354
+ if (name !== "*") {
355
+ if (!/^[a-zA-Z0-9_\-.\*]+$/.test(name)) {
356
+ return "Invalid scope segment. Only ASCII characters, numbers, -, _, . or * are allowed.";
357
+ }
358
+ }
359
+ }
360
+ return undefined;
361
+ }
183
362
 
184
363
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
185
364
  export function normalizeRepoPattern(pattern: string) {
@@ -200,7 +379,7 @@ export namespace UserEnvVar {
200
379
  if (repoPattern == "*") {
201
380
  score += 1;
202
381
  }
203
- if (ownerPattern == '*') {
382
+ if (ownerPattern == "*") {
204
383
  score += 2;
205
384
  }
206
385
  if (ownerPattern == "#" || repoPattern == "#") {
@@ -211,20 +390,20 @@ export namespace UserEnvVar {
211
390
 
212
391
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
213
392
  export function filter<T extends UserEnvVarValue>(vars: T[], owner: string, repo: string): T[] {
214
- let result = vars.filter(e => {
393
+ let result = vars.filter((e) => {
215
394
  const [ownerPattern, repoPattern] = splitRepositoryPattern(e.repositoryPattern);
216
- if (ownerPattern !== '*' && ownerPattern !== '#' && (!!owner && ownerPattern !== owner.toLocaleLowerCase())) {
395
+ if (ownerPattern !== "*" && ownerPattern !== "#" && !!owner && ownerPattern !== owner.toLocaleLowerCase()) {
217
396
  return false;
218
397
  }
219
- if (repoPattern !== '*' && repoPattern !== '#' && (!!repo && repoPattern !== repo.toLocaleLowerCase())) {
398
+ if (repoPattern !== "*" && repoPattern !== "#" && !!repo && repoPattern !== repo.toLocaleLowerCase()) {
220
399
  return false;
221
400
  }
222
401
  return true;
223
402
  });
224
403
 
225
404
  const resmap = new Map<string, T[]>();
226
- result.forEach(e => {
227
- const l = (resmap.get(e.name) || []);
405
+ result.forEach((e) => {
406
+ const l = resmap.get(e.name) || [];
228
407
  l.push(e);
229
408
  resmap.set(e.name, l);
230
409
  });
@@ -259,46 +438,107 @@ export namespace UserEnvVar {
259
438
 
260
439
  // DEPRECATED: Use ProjectEnvVar instead of repositoryPattern - https://github.com/gitpod-com/gitpod/issues/5322
261
440
  export function splitRepositoryPattern(repositoryPattern: string): string[] {
262
- const patterns = repositoryPattern.split('/');
263
- const repoPattern = patterns.slice(1).join('/')
441
+ const patterns = repositoryPattern.split("/");
442
+ const repoPattern = patterns.slice(1).join("/");
264
443
  const ownerPattern = patterns[0];
265
444
  return [ownerPattern, repoPattern];
266
445
  }
267
446
  }
268
447
 
269
- export interface GitpodToken {
448
+ export interface SSHPublicKeyValue {
449
+ name: string;
450
+ key: string;
451
+ }
452
+ export interface UserSSHPublicKey extends SSHPublicKeyValue {
453
+ id: string;
454
+ key: string;
455
+ userId: string;
456
+ fingerprint: string;
457
+ creationTime: string;
458
+ lastUsedTime?: string;
459
+ }
460
+
461
+ export type UserSSHPublicKeyValue = Omit<UserSSHPublicKey, "key" | "userId">;
462
+
463
+ export namespace SSHPublicKeyValue {
464
+ export function validate(value: SSHPublicKeyValue): string | undefined {
465
+ if (value.name.length === 0) {
466
+ return "Title must not be empty.";
467
+ }
468
+ if (value.name.length > 255) {
469
+ return "Title too long. Maximum value length is 255 characters.";
470
+ }
471
+ if (value.key.length === 0) {
472
+ return "Key must not be empty.";
473
+ }
474
+ try {
475
+ getData(value);
476
+ } catch (e) {
477
+ return "Key is invalid. You must supply a key in OpenSSH public key format.";
478
+ }
479
+ return;
480
+ }
481
+
482
+ export function getData(value: SSHPublicKeyValue) {
483
+ // Begins with 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', or 'sk-ssh-ed25519@openssh.com'.
484
+ const regex =
485
+ /^(?<type>ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519|sk-ecdsa-sha2-nistp256@openssh\.com|sk-ssh-ed25519@openssh\.com) (?<key>.*?)( (?<email>.*?))?$/;
486
+ const resultGroup = regex.exec(value.key.trim());
487
+ if (!resultGroup) {
488
+ throw new Error("Key is invalid.");
489
+ }
490
+ return {
491
+ type: resultGroup.groups?.["type"] as string,
492
+ key: resultGroup.groups?.["key"] as string,
493
+ email: resultGroup.groups?.["email"] || undefined,
494
+ };
495
+ }
496
+
497
+ export function getFingerprint(value: SSHPublicKeyValue) {
498
+ const data = getData(value);
499
+ let buf = Buffer.from(data.key, "base64");
500
+ // gitlab style
501
+ // const hash = createHash("md5").update(buf).digest("hex");
502
+ // github style
503
+ const hash = createHash("sha256").update(buf).digest("base64");
504
+ return hash;
505
+ }
270
506
 
507
+ export const MAXIMUM_KEY_LENGTH = 5;
508
+ }
509
+
510
+ export interface GitpodToken {
271
511
  /** Hash value (SHA256) of the token (primary key). */
272
- tokenHash: string
512
+ tokenHash: string;
273
513
 
274
514
  /** Human readable name of the token */
275
- name?: string
515
+ name?: string;
276
516
 
277
517
  /** Token kind */
278
- type: GitpodTokenType
518
+ type: GitpodTokenType;
279
519
 
280
520
  /** The user the token belongs to. */
281
- user: User
521
+ user: User;
282
522
 
283
523
  /** Scopes (e.g. limition to read-only) */
284
- scopes: string[]
524
+ scopes: string[];
285
525
 
286
526
  /** Created timestamp */
287
- created: string
527
+ created: string;
288
528
 
289
529
  // token is deleted on the database and about to be collected by db-sync
290
- deleted?: boolean
530
+ deleted?: boolean;
291
531
  }
292
532
 
293
533
  export enum GitpodTokenType {
294
534
  API_AUTH_TOKEN = 0,
295
- MACHINE_AUTH_TOKEN = 1
535
+ MACHINE_AUTH_TOKEN = 1,
296
536
  }
297
537
 
298
538
  export interface OneTimeSecret {
299
- id: string
539
+ id: string;
300
540
 
301
- value: string
541
+ value: string;
302
542
 
303
543
  expirationTime: string;
304
544
 
@@ -330,13 +570,12 @@ export type IdentityLookup = Pick<Identity, "authProviderId" | "authId">;
330
570
 
331
571
  export namespace Identity {
332
572
  export function is(data: any): data is Identity {
333
- return data.hasOwnProperty('authProviderId')
334
- && data.hasOwnProperty('authId')
335
- && data.hasOwnProperty('authName')
573
+ return (
574
+ data.hasOwnProperty("authProviderId") && data.hasOwnProperty("authId") && data.hasOwnProperty("authName")
575
+ );
336
576
  }
337
577
  export function equals(id1: IdentityLookup, id2: IdentityLookup) {
338
- return id1.authProviderId === id2.authProviderId
339
- && id1.authId === id2.authId
578
+ return id1.authProviderId === id2.authProviderId && id1.authId === id2.authId;
340
579
  }
341
580
  }
342
581
 
@@ -400,7 +639,14 @@ export interface Snapshot {
400
639
  message?: string;
401
640
  }
402
641
 
403
- export type SnapshotState = 'pending' | 'available' | 'error';
642
+ export interface VolumeSnapshot {
643
+ id: string;
644
+ workspaceId: string;
645
+ creationTime: string;
646
+ volumeHandle: string;
647
+ }
648
+
649
+ export type SnapshotState = "pending" | "available" | "error";
404
650
 
405
651
  export interface LayoutData {
406
652
  workspaceId: string;
@@ -429,13 +675,13 @@ export interface Workspace {
429
675
  * The resolved, fix name of the workspace image. We only use this
430
676
  * to access the logs during an image build.
431
677
  */
432
- imageNameResolved?: string
678
+ imageNameResolved?: string;
433
679
 
434
680
  /**
435
681
  * The resolved/built fixed named of the base image. This field is only set if the workspace
436
682
  * already has its base image built.
437
683
  */
438
- baseImageNameResolved?: string
684
+ baseImageNameResolved?: string;
439
685
 
440
686
  shareable?: boolean;
441
687
  pinned?: boolean;
@@ -469,20 +715,19 @@ export interface Workspace {
469
715
 
470
716
  export type WorkspaceSoftDeletion = "user" | "gc";
471
717
 
472
- export type WorkspaceType = "regular" | "prebuild" | "probe";
718
+ export type WorkspaceType = "regular" | "prebuild" | "probe"; // TODO(gpl) Removed prove here
473
719
 
474
720
  export namespace Workspace {
475
-
476
721
  export function getFullRepositoryName(ws: Workspace): string | undefined {
477
722
  if (CommitContext.is(ws.context)) {
478
- return ws.context.repository.owner + '/' + ws.context.repository.name
723
+ return ws.context.repository.owner + "/" + ws.context.repository.name;
479
724
  }
480
725
  return undefined;
481
726
  }
482
727
 
483
728
  export function getFullRepositoryUrl(ws: Workspace): string | undefined {
484
729
  if (CommitContext.is(ws.context)) {
485
- return `https://${ws.context.repository.host}/${getFullRepositoryName(ws)}`
730
+ return `https://${ws.context.repository.host}/${getFullRepositoryName(ws)}`;
486
731
  }
487
732
  return undefined;
488
733
  }
@@ -516,56 +761,40 @@ export namespace Workspace {
516
761
  }
517
762
  }
518
763
 
519
- export interface PreparePluginUploadParams {
520
- fullPluginName: string;
521
- }
522
-
523
- export interface ResolvePluginsParams {
524
- config?: WorkspaceConfig
525
- builtins?: ResolvedPlugins
526
- vsxRegistryUrl?: string
527
- }
528
-
529
- export interface InstallPluginsParams {
530
- pluginIds: string[]
531
- }
532
-
533
- export interface UninstallPluginParams {
534
- pluginId: string;
535
- }
536
-
537
764
  export interface GuessGitTokenScopesParams {
538
- host: string
539
- repoUrl: string
540
- gitCommand: string
541
- currentToken: GitToken
765
+ host: string;
766
+ repoUrl: string;
767
+ gitCommand: string;
768
+ currentToken: GitToken;
542
769
  }
543
770
 
544
771
  export interface GitToken {
545
- token: string
546
- user: string
547
- scopes: string[]
772
+ token: string;
773
+ user: string;
774
+ scopes: string[];
548
775
  }
549
776
 
550
777
  export interface GuessedGitTokenScopes {
551
- message?: string
552
- scopes?: string[]
778
+ message?: string;
779
+ scopes?: string[];
553
780
  }
554
781
 
555
- export type ResolvedPluginKind = 'user' | 'workspace' | 'builtin';
556
-
557
- export interface ResolvedPlugins {
558
- [pluginId: string]: ResolvedPlugin | undefined
782
+ export interface VSCodeConfig {
783
+ extensions?: string[];
559
784
  }
560
785
 
561
- export interface ResolvedPlugin {
562
- fullPluginName: string;
563
- url: string;
564
- kind: ResolvedPluginKind;
786
+ export interface JetBrainsConfig {
787
+ intellij?: JetBrainsProductConfig;
788
+ goland?: JetBrainsProductConfig;
789
+ pycharm?: JetBrainsProductConfig;
790
+ phpstorm?: JetBrainsProductConfig;
565
791
  }
566
-
567
- export interface VSCodeConfig {
568
- extensions?: string[];
792
+ export interface JetBrainsProductConfig {
793
+ prebuilds?: JetBrainsPrebuilds;
794
+ vmoptions?: string;
795
+ }
796
+ export interface JetBrainsPrebuilds {
797
+ version?: "stable" | "latest" | "both";
569
798
  }
570
799
 
571
800
  export interface RepositoryCloneInformation {
@@ -584,6 +813,7 @@ export interface WorkspaceConfig {
584
813
  gitConfig?: { [config: string]: string };
585
814
  github?: GithubAppConfig;
586
815
  vscode?: VSCodeConfig;
816
+ jetbrains?: JetBrainsConfig;
587
817
 
588
818
  /** deprecated. Enabled by default **/
589
819
  experimentalNetwork?: boolean;
@@ -598,7 +828,7 @@ export interface WorkspaceConfig {
598
828
  * additional-content - config comes from additional content, usually provided through the project's configuration
599
829
  * default - our static catch-all default config
600
830
  */
601
- _origin?: 'repo' | 'project-db' | 'definitely-gp' | 'derived' | 'additional-content' | 'default';
831
+ _origin?: "repo" | "project-db" | "definitely-gp" | "derived" | "additional-content" | "default";
602
832
 
603
833
  /**
604
834
  * Set of automatically infered feature flags. That's not something the user can set, but
@@ -608,34 +838,33 @@ export interface WorkspaceConfig {
608
838
  }
609
839
 
610
840
  export interface GithubAppConfig {
611
- prebuilds?: GithubAppPrebuildConfig
841
+ prebuilds?: GithubAppPrebuildConfig;
612
842
  }
613
843
  export interface GithubAppPrebuildConfig {
614
- master?: boolean
615
- branches?: boolean
616
- pullRequests?: boolean
617
- pullRequestsFromForks?: boolean
618
- addCheck?: boolean | 'prevent-merge-on-error'
619
- addBadge?: boolean
620
- addLabel?: boolean | string
621
- addComment?: boolean
844
+ master?: boolean;
845
+ branches?: boolean;
846
+ pullRequests?: boolean;
847
+ pullRequestsFromForks?: boolean;
848
+ addCheck?: boolean | "prevent-merge-on-error";
849
+ addBadge?: boolean;
850
+ addLabel?: boolean | string;
851
+ addComment?: boolean;
622
852
  }
623
853
  export namespace GithubAppPrebuildConfig {
624
854
  export function is(obj: boolean | GithubAppPrebuildConfig): obj is GithubAppPrebuildConfig {
625
- return !(typeof obj === 'boolean');
855
+ return !(typeof obj === "boolean");
626
856
  }
627
857
  }
628
858
 
629
859
  export type WorkspaceImageSource = WorkspaceImageSourceDocker | WorkspaceImageSourceReference;
630
860
  export interface WorkspaceImageSourceDocker {
631
- dockerFilePath: string
632
- dockerFileHash: string
633
- dockerFileSource?: Commit
861
+ dockerFilePath: string;
862
+ dockerFileHash: string;
863
+ dockerFileSource?: Commit;
634
864
  }
635
865
  export namespace WorkspaceImageSourceDocker {
636
866
  export function is(obj: object): obj is WorkspaceImageSourceDocker {
637
- return 'dockerFileHash' in obj
638
- && 'dockerFilePath' in obj;
867
+ return "dockerFileHash" in obj && "dockerFilePath" in obj;
639
868
  }
640
869
  }
641
870
  export interface WorkspaceImageSourceReference {
@@ -644,13 +873,13 @@ export interface WorkspaceImageSourceReference {
644
873
  }
645
874
  export namespace WorkspaceImageSourceReference {
646
875
  export function is(obj: object): obj is WorkspaceImageSourceReference {
647
- return 'baseImageResolved' in obj;
876
+ return "baseImageResolved" in obj;
648
877
  }
649
878
  }
650
879
 
651
- export type PrebuiltWorkspaceState
880
+ export type PrebuiltWorkspaceState =
652
881
  // the prebuild is queued and may start at anytime
653
- = "queued"
882
+ | "queued"
654
883
  // the workspace prebuild is currently running (i.e. there's a workspace pod deployed)
655
884
  | "building"
656
885
  // the prebuild was aborted
@@ -671,13 +900,16 @@ export interface PrebuiltWorkspace {
671
900
  buildWorkspaceId: string;
672
901
  creationTime: string;
673
902
  state: PrebuiltWorkspaceState;
903
+ statusVersion: number;
674
904
  error?: string;
675
905
  snapshot?: string;
676
906
  }
677
907
 
678
908
  export namespace PrebuiltWorkspace {
679
909
  export function isDone(pws: PrebuiltWorkspace) {
680
- return pws.state === "available" || pws.state === "timeout" || pws.state === 'aborted';
910
+ return (
911
+ pws.state === "available" || pws.state === "timeout" || pws.state === "aborted" || pws.state === "failed"
912
+ );
681
913
  }
682
914
 
683
915
  export function isAvailable(pws: PrebuiltWorkspace) {
@@ -705,13 +937,13 @@ export interface PrebuiltWorkspaceUpdatable {
705
937
  }
706
938
 
707
939
  export interface WhitelistedRepository {
708
- url: string
709
- name: string
710
- description?: string
711
- avatar?: string
940
+ url: string;
941
+ name: string;
942
+ description?: string;
943
+ avatar?: string;
712
944
  }
713
945
 
714
- export type PortOnOpen = 'open-browser' | 'open-preview' | 'notify' | 'ignore';
946
+ export type PortOnOpen = "open-browser" | "open-preview" | "notify" | "ignore";
715
947
 
716
948
  export interface PortConfig {
717
949
  port: number;
@@ -722,7 +954,7 @@ export interface PortConfig {
722
954
  }
723
955
  export namespace PortConfig {
724
956
  export function is(config: any): config is PortConfig {
725
- return config && ('port' in config) && (typeof config.port === 'number');
957
+ return config && "port" in config && typeof config.port === "number";
726
958
  }
727
959
  }
728
960
 
@@ -732,7 +964,7 @@ export interface PortRangeConfig {
732
964
  }
733
965
  export namespace PortRangeConfig {
734
966
  export function is(config: any): config is PortRangeConfig {
735
- return config && ('port' in config) && (typeof config.port === 'string' || config.port instanceof String);
967
+ return config && "port" in config && (typeof config.port === "string" || config.port instanceof String);
736
968
  }
737
969
  }
738
970
 
@@ -743,32 +975,31 @@ export interface TaskConfig {
743
975
  prebuild?: string;
744
976
  command?: string;
745
977
  env?: { [env: string]: any };
746
- openIn?: 'bottom' | 'main' | 'left' | 'right';
747
- openMode?: 'split-top' | 'split-left' | 'split-right' | 'split-bottom' | 'tab-before' | 'tab-after';
978
+ openIn?: "bottom" | "main" | "left" | "right";
979
+ openMode?: "split-top" | "split-left" | "split-right" | "split-bottom" | "tab-before" | "tab-after";
748
980
  }
749
981
 
750
982
  export namespace TaskConfig {
751
983
  export function is(config: any): config is TaskConfig {
752
- return config
753
- && ('command' in config || 'init' in config || 'before' in config);
984
+ return config && ("command" in config || "init" in config || "before" in config);
754
985
  }
755
986
  }
756
987
 
757
988
  export namespace WorkspaceImageBuild {
758
- export type Phase = 'BaseImage' | 'GitpodLayer' | 'Error' | 'Done';
989
+ export type Phase = "BaseImage" | "GitpodLayer" | "Error" | "Done";
759
990
  export interface StateInfo {
760
- phase: Phase
761
- currentStep?: number
762
- maxSteps?: number
991
+ phase: Phase;
992
+ currentStep?: number;
993
+ maxSteps?: number;
763
994
  }
764
995
  export interface LogContent {
765
- text: string
766
- upToLine?: number
767
- isDiff?: boolean
996
+ text: string;
997
+ upToLine?: number;
998
+ isDiff?: boolean;
768
999
  }
769
1000
  export type LogCallback = (info: StateInfo, content: LogContent | undefined) => void;
770
1001
  export namespace LogLine {
771
- export const DELIMITER = '\r\n';
1002
+ export const DELIMITER = "\r\n";
772
1003
  export const DELIMITER_REGEX = /\r?\n/;
773
1004
  }
774
1005
  }
@@ -777,20 +1008,18 @@ export type ImageConfig = ImageConfigString | ImageConfigFile;
777
1008
  export type ImageConfigString = string;
778
1009
  export namespace ImageConfigString {
779
1010
  export function is(config: ImageConfig | undefined): config is ImageConfigString {
780
- return typeof config === 'string';
1011
+ return typeof config === "string";
781
1012
  }
782
-
783
1013
  }
784
1014
  export interface ImageConfigFile {
785
1015
  // Path to the Dockerfile relative to repository root
786
- file: string,
1016
+ file: string;
787
1017
  // Path to the docker build context relative to repository root
788
- context?: string
1018
+ context?: string;
789
1019
  }
790
1020
  export namespace ImageConfigFile {
791
1021
  export function is(config: ImageConfig | undefined): config is ImageConfigFile {
792
- return typeof config === 'object'
793
- && 'file' in config;
1022
+ return typeof config === "object" && "file" in config;
794
1023
  }
795
1024
  }
796
1025
  export interface ExternalImageConfigFile extends ImageConfigFile {
@@ -798,14 +1027,13 @@ export interface ExternalImageConfigFile extends ImageConfigFile {
798
1027
  }
799
1028
  export namespace ExternalImageConfigFile {
800
1029
  export function is(config: any | undefined): config is ExternalImageConfigFile {
801
- return typeof config === 'object'
802
- && 'file' in config
803
- && 'externalSource' in config;
1030
+ return typeof config === "object" && "file" in config && "externalSource" in config;
804
1031
  }
805
1032
  }
806
1033
 
807
1034
  export interface WorkspaceContext {
808
1035
  title: string;
1036
+ ref?: string;
809
1037
  /** This contains the URL portion of the contextURL (which might contain other modifiers as well). It's optional because it's not set for older workspaces. */
810
1038
  normalizedContextURL?: string;
811
1039
  forceCreateNewWorkspace?: boolean;
@@ -814,8 +1042,7 @@ export interface WorkspaceContext {
814
1042
 
815
1043
  export namespace WorkspaceContext {
816
1044
  export function is(context: any): context is WorkspaceContext {
817
- return context
818
- && 'title' in context;
1045
+ return context && "title" in context;
819
1046
  }
820
1047
  }
821
1048
 
@@ -824,8 +1051,7 @@ export interface WithSnapshot {
824
1051
  }
825
1052
  export namespace WithSnapshot {
826
1053
  export function is(context: any): context is WithSnapshot {
827
- return context
828
- && 'snapshotBucketId' in context;
1054
+ return context && "snapshotBucketId" in context;
829
1055
  }
830
1056
  }
831
1057
 
@@ -835,10 +1061,7 @@ export interface WithPrebuild extends WithSnapshot {
835
1061
  }
836
1062
  export namespace WithPrebuild {
837
1063
  export function is(context: any): context is WithPrebuild {
838
- return context
839
- && WithSnapshot.is(context)
840
- && 'prebuildWorkspaceId' in context
841
- && 'wasPrebuilt' in context;
1064
+ return context && WithSnapshot.is(context) && "prebuildWorkspaceId" in context && "wasPrebuilt" in context;
842
1065
  }
843
1066
  }
844
1067
 
@@ -852,16 +1075,14 @@ export interface WithDefaultConfig {
852
1075
 
853
1076
  export namespace WithDefaultConfig {
854
1077
  export function is(context: any): context is WithDefaultConfig {
855
- return context
856
- && 'withDefaultConfig' in context
857
- && context.withDefaultConfig;
1078
+ return context && "withDefaultConfig" in context && context.withDefaultConfig;
858
1079
  }
859
1080
 
860
1081
  export function mark(ctx: WorkspaceContext): WorkspaceContext & WithDefaultConfig {
861
1082
  return {
862
1083
  ...ctx,
863
- withDefaultConfig: true
864
- }
1084
+ withDefaultConfig: true,
1085
+ };
865
1086
  }
866
1087
  }
867
1088
 
@@ -871,9 +1092,7 @@ export interface SnapshotContext extends WorkspaceContext, WithSnapshot {
871
1092
 
872
1093
  export namespace SnapshotContext {
873
1094
  export function is(context: any): context is SnapshotContext {
874
- return context
875
- && WithSnapshot.is(context)
876
- && 'snapshotId' in context;
1095
+ return context && WithSnapshot.is(context) && "snapshotId" in context;
877
1096
  }
878
1097
  }
879
1098
 
@@ -890,8 +1109,7 @@ export interface StartPrebuildContext extends WorkspaceContext {
890
1109
 
891
1110
  export namespace StartPrebuildContext {
892
1111
  export function is(context: any): context is StartPrebuildContext {
893
- return context
894
- && 'actual' in context;
1112
+ return context && "actual" in context;
895
1113
  }
896
1114
  }
897
1115
 
@@ -903,21 +1121,18 @@ export interface PrebuiltWorkspaceContext extends WorkspaceContext {
903
1121
 
904
1122
  export namespace PrebuiltWorkspaceContext {
905
1123
  export function is(context: any): context is PrebuiltWorkspaceContext {
906
- return context
907
- && 'originalContext' in context
908
- && 'prebuiltWorkspace' in context;
1124
+ return context && "originalContext" in context && "prebuiltWorkspace" in context;
909
1125
  }
910
1126
  }
911
1127
 
912
1128
  export interface WithReferrerContext extends WorkspaceContext {
913
- referrer: string
914
- referrerIde?: string
1129
+ referrer: string;
1130
+ referrerIde?: string;
915
1131
  }
916
1132
 
917
1133
  export namespace WithReferrerContext {
918
1134
  export function is(context: any): context is WithReferrerContext {
919
- return context
920
- && 'referrer' in context;
1135
+ return context && "referrer" in context;
921
1136
  }
922
1137
  }
923
1138
 
@@ -927,21 +1142,18 @@ export interface WithEnvvarsContext extends WorkspaceContext {
927
1142
 
928
1143
  export namespace WithEnvvarsContext {
929
1144
  export function is(context: any): context is WithEnvvarsContext {
930
- return context
931
- && 'envvars' in context
1145
+ return context && "envvars" in context;
932
1146
  }
933
1147
  }
934
1148
 
935
1149
  export interface WorkspaceProbeContext extends WorkspaceContext {
936
- responseURL: string
937
- responseToken: string
1150
+ responseURL: string;
1151
+ responseToken: string;
938
1152
  }
939
1153
 
940
1154
  export namespace WorkspaceProbeContext {
941
1155
  export function is(context: any): context is WorkspaceProbeContext {
942
- return context
943
- && 'responseURL' in context
944
- && 'responseToken' in context;
1156
+ return context && "responseURL" in context && "responseToken" in context;
945
1157
  }
946
1158
  }
947
1159
 
@@ -953,32 +1165,30 @@ export namespace RefType {
953
1165
  }
954
1166
  // This fallback is meant to handle the cases where (for historic reasons) ref is present but refType is missing
955
1167
  return commit.refType || "branch";
956
- }
1168
+ };
957
1169
  }
958
1170
 
959
1171
  export interface Commit {
960
- repository: Repository
961
- revision: string
1172
+ repository: Repository;
1173
+ revision: string;
962
1174
 
963
1175
  // Might contain either a branch or a tag (determined by refType)
964
- ref?: string
1176
+ ref?: string;
965
1177
 
966
1178
  // refType is only set if ref is present (and not for old workspaces, before this feature was added)
967
- refType?: RefType
1179
+ refType?: RefType;
968
1180
  }
969
1181
 
970
1182
  export interface AdditionalContentContext extends WorkspaceContext {
971
-
972
1183
  /**
973
1184
  * utf-8 encoded contents that will be copied on top of the workspace's filesystem
974
1185
  */
975
- additionalFiles: {[filePath: string]: string};
976
-
1186
+ additionalFiles: { [filePath: string]: string };
977
1187
  }
978
1188
 
979
1189
  export namespace AdditionalContentContext {
980
1190
  export function is(ctx: any): ctx is AdditionalContentContext {
981
- return 'additionalFiles' in ctx;
1191
+ return "additionalFiles" in ctx;
982
1192
  }
983
1193
 
984
1194
  export function hasDockerConfig(ctx: any, config: WorkspaceConfig): boolean {
@@ -988,7 +1198,7 @@ export namespace AdditionalContentContext {
988
1198
 
989
1199
  export interface CommitContext extends WorkspaceContext, GitCheckoutInfo {
990
1200
  /** @deprecated Moved to .repository.cloneUrl, left here for backwards-compatibility for old workspace contextes in the DB */
991
- cloneUrl?: string
1201
+ cloneUrl?: string;
992
1202
 
993
1203
  /**
994
1204
  * The clone and checkout information for additional repositories in case of multi-repo projects.
@@ -997,7 +1207,6 @@ export interface CommitContext extends WorkspaceContext, GitCheckoutInfo {
997
1207
  }
998
1208
 
999
1209
  export namespace CommitContext {
1000
-
1001
1210
  /**
1002
1211
  * Creates a hash for all the commits of the CommitContext and all sub-repo commit infos.
1003
1212
  * The hash is max 255 chars long.
@@ -1006,17 +1215,19 @@ export namespace CommitContext {
1006
1215
  */
1007
1216
  export function computeHash(commitContext: CommitContext): string {
1008
1217
  // for single commits we use the revision to be backward compatible.
1009
- if (!commitContext.additionalRepositoryCheckoutInfo || commitContext.additionalRepositoryCheckoutInfo.length === 0) {
1218
+ if (
1219
+ !commitContext.additionalRepositoryCheckoutInfo ||
1220
+ commitContext.additionalRepositoryCheckoutInfo.length === 0
1221
+ ) {
1010
1222
  return commitContext.revision;
1011
1223
  }
1012
- const hasher = createHash('sha256');
1224
+ const hasher = createHash("sha256");
1013
1225
  hasher.update(commitContext.revision);
1014
1226
  for (const info of commitContext.additionalRepositoryCheckoutInfo) {
1015
1227
  hasher.update(info.revision);
1016
1228
  }
1017
- return hasher.digest('hex');
1229
+ return hasher.digest("hex");
1018
1230
  }
1019
-
1020
1231
  }
1021
1232
 
1022
1233
  export interface GitCheckoutInfo extends Commit {
@@ -1027,9 +1238,7 @@ export interface GitCheckoutInfo extends Commit {
1027
1238
 
1028
1239
  export namespace CommitContext {
1029
1240
  export function is(commit: any): commit is CommitContext {
1030
- return WorkspaceContext.is(commit)
1031
- && 'repository' in commit
1032
- && 'revision' in commit
1241
+ return WorkspaceContext.is(commit) && "repository" in commit && "revision" in commit;
1033
1242
  }
1034
1243
  }
1035
1244
 
@@ -1037,17 +1246,14 @@ export interface PullRequestContext extends CommitContext {
1037
1246
  nr: number;
1038
1247
  ref: string;
1039
1248
  base: {
1040
- repository: Repository
1041
- ref: string
1042
- }
1249
+ repository: Repository;
1250
+ ref: string;
1251
+ };
1043
1252
  }
1044
1253
 
1045
1254
  export namespace PullRequestContext {
1046
1255
  export function is(ctx: any): ctx is PullRequestContext {
1047
- return CommitContext.is(ctx)
1048
- && 'nr' in ctx
1049
- && 'ref' in ctx
1050
- && 'base' in ctx
1256
+ return CommitContext.is(ctx) && "nr" in ctx && "ref" in ctx && "base" in ctx;
1051
1257
  }
1052
1258
  }
1053
1259
 
@@ -1059,10 +1265,7 @@ export interface IssueContext extends CommitContext {
1059
1265
 
1060
1266
  export namespace IssueContext {
1061
1267
  export function is(ctx: any): ctx is IssueContext {
1062
- return CommitContext.is(ctx)
1063
- && 'nr' in ctx
1064
- && 'ref' in ctx
1065
- && 'localBranch' in ctx
1268
+ return CommitContext.is(ctx) && "nr" in ctx && "ref" in ctx && "localBranch" in ctx;
1066
1269
  }
1067
1270
  }
1068
1271
 
@@ -1073,9 +1276,7 @@ export interface NavigatorContext extends CommitContext {
1073
1276
 
1074
1277
  export namespace NavigatorContext {
1075
1278
  export function is(ctx: any): ctx is NavigatorContext {
1076
- return CommitContext.is(ctx)
1077
- && 'path' in ctx
1078
- && 'isFile' in ctx
1279
+ return CommitContext.is(ctx) && "path" in ctx && "isFile" in ctx;
1079
1280
  }
1080
1281
  }
1081
1282
 
@@ -1084,6 +1285,8 @@ export interface Repository {
1084
1285
  owner: string;
1085
1286
  name: string;
1086
1287
  cloneUrl: string;
1288
+ /* Optional kind to differentiate between repositories of orgs/groups/projects and personal repos. */
1289
+ repoKind?: string;
1087
1290
  description?: string;
1088
1291
  avatarUrl?: string;
1089
1292
  webUrl?: string;
@@ -1092,8 +1295,8 @@ export interface Repository {
1092
1295
  private?: boolean;
1093
1296
  fork?: {
1094
1297
  // The direct parent of this fork
1095
- parent: Repository
1096
- }
1298
+ parent: Repository;
1299
+ };
1097
1300
  }
1098
1301
  export interface Branch {
1099
1302
  name: string;
@@ -1118,21 +1321,19 @@ export namespace Repository {
1118
1321
  export interface WorkspaceInstancePortsChangedEvent {
1119
1322
  type: "PortsChanged";
1120
1323
  instanceID: string;
1121
- portsOpened: number[]
1122
- portsClosed: number[]
1324
+ portsOpened: number[];
1325
+ portsClosed: number[];
1123
1326
  }
1124
1327
 
1125
1328
  export namespace WorkspaceInstancePortsChangedEvent {
1126
-
1127
1329
  export function is(data: any): data is WorkspaceInstancePortsChangedEvent {
1128
1330
  return data && data.type == "PortsChanged";
1129
1331
  }
1130
-
1131
1332
  }
1132
1333
 
1133
1334
  export interface WorkspaceInfo {
1134
- workspace: Workspace
1135
- latestInstance?: WorkspaceInstance
1335
+ workspace: Workspace;
1336
+ latestInstance?: WorkspaceInstance;
1136
1337
  }
1137
1338
 
1138
1339
  export namespace WorkspaceInfo {
@@ -1148,35 +1349,36 @@ export interface WorkspaceCreationResult {
1148
1349
  workspaceURL?: string;
1149
1350
  existingWorkspaces?: WorkspaceInfo[];
1150
1351
  runningWorkspacePrebuild?: {
1151
- prebuildID: string
1152
- workspaceID: string
1153
- instanceID: string
1154
- starting: RunningWorkspacePrebuildStarting
1155
- sameCluster: boolean
1156
- }
1352
+ prebuildID: string;
1353
+ workspaceID: string;
1354
+ instanceID: string;
1355
+ starting: RunningWorkspacePrebuildStarting;
1356
+ sameCluster: boolean;
1357
+ };
1157
1358
  runningPrebuildWorkspaceID?: string;
1158
1359
  }
1159
- export type RunningWorkspacePrebuildStarting = 'queued' | 'starting' | 'running';
1360
+ export type RunningWorkspacePrebuildStarting = "queued" | "starting" | "running";
1160
1361
 
1161
1362
  export enum CreateWorkspaceMode {
1162
1363
  // Default returns a running prebuild if there is any, otherwise creates a new workspace (using a prebuild if one is available)
1163
- Default = 'default',
1364
+ Default = "default",
1164
1365
  // ForceNew creates a new workspace irrespective of any running prebuilds. This mode is guaranteed to actually create a workspace - but may degrade user experience as currently runnig prebuilds are ignored.
1165
- ForceNew = 'force-new',
1366
+ ForceNew = "force-new",
1166
1367
  // UsePrebuild polls the database waiting for a currently running prebuild to become available. This mode exists to handle the db-sync delay.
1167
- UsePrebuild = 'use-prebuild',
1368
+ UsePrebuild = "use-prebuild",
1168
1369
  // SelectIfRunning returns a list of currently running workspaces for the context URL if there are any, otherwise falls back to Default mode
1169
- SelectIfRunning = 'select-if-running',
1370
+ SelectIfRunning = "select-if-running",
1170
1371
  }
1171
1372
 
1172
1373
  export namespace WorkspaceCreationResult {
1173
1374
  export function is(data: any): data is WorkspaceCreationResult {
1174
- return data && (
1175
- 'createdWorkspaceId' in data
1176
- || 'existingWorkspaces' in data
1177
- || 'runningWorkspacePrebuild' in data
1178
- || 'runningPrebuildWorkspaceID' in data
1179
- )
1375
+ return (
1376
+ data &&
1377
+ ("createdWorkspaceId" in data ||
1378
+ "existingWorkspaces" in data ||
1379
+ "runningWorkspacePrebuild" in data ||
1380
+ "runningPrebuildWorkspaceID" in data)
1381
+ );
1180
1382
  }
1181
1383
  }
1182
1384
 
@@ -1210,7 +1412,7 @@ export interface AuthProviderInfo {
1210
1412
  readonly default: string[];
1211
1413
  readonly publicRepo: string[];
1212
1414
  readonly privateRepo: string[];
1213
- }
1415
+ };
1214
1416
  }
1215
1417
 
1216
1418
  export interface AuthProviderEntry {
@@ -1236,23 +1438,27 @@ export interface OAuth2Config {
1236
1438
  readonly scopeSeparator?: string;
1237
1439
 
1238
1440
  readonly settingsUrl?: string;
1239
- readonly authorizationParams?: { [key: string]: string }
1441
+ readonly authorizationParams?: { [key: string]: string };
1240
1442
  readonly configURL?: string;
1241
1443
  }
1242
1444
 
1243
1445
  export namespace AuthProviderEntry {
1244
1446
  export type Type = "GitHub" | "GitLab" | string;
1245
1447
  export type Status = "pending" | "verified";
1246
- export type NewEntry = Pick<AuthProviderEntry, "ownerId" | "host" | "type"> & { clientId?: string, clientSecret?: string };
1247
- export type UpdateEntry = Pick<AuthProviderEntry, "id" | "ownerId"> & Pick<OAuth2Config, "clientId" | "clientSecret">;
1448
+ export type NewEntry = Pick<AuthProviderEntry, "ownerId" | "host" | "type"> & {
1449
+ clientId?: string;
1450
+ clientSecret?: string;
1451
+ };
1452
+ export type UpdateEntry = Pick<AuthProviderEntry, "id" | "ownerId"> &
1453
+ Pick<OAuth2Config, "clientId" | "clientSecret">;
1248
1454
  export function redact(entry: AuthProviderEntry): AuthProviderEntry {
1249
1455
  return {
1250
1456
  ...entry,
1251
1457
  oauth: {
1252
1458
  ...entry.oauth,
1253
- clientSecret: "redacted"
1254
- }
1255
- }
1459
+ clientSecret: "redacted",
1460
+ },
1461
+ };
1256
1462
  }
1257
1463
  }
1258
1464
 
@@ -1296,3 +1502,11 @@ export interface Terms {
1296
1502
  readonly content: string;
1297
1503
  readonly formElements?: object;
1298
1504
  }
1505
+
1506
+ export interface CostCenter {
1507
+ readonly id: string;
1508
+ /**
1509
+ * Unit: credits
1510
+ */
1511
+ spendingLimit: number;
1512
+ }