@gitpod/gitpod-protocol 0.1.5-v0.6.0-beta2 → 0.1.5-vn-integrate-gitpod-yml-tasks-into-jetbrainsa.5

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 (299) hide show
  1. package/data/builtin-theia-plugins.json +9 -9
  2. package/data/gitpod-schema.json +25 -24
  3. package/lib/accounting-protocol.d.ts +155 -0
  4. package/lib/accounting-protocol.d.ts.map +1 -0
  5. package/lib/accounting-protocol.js +109 -0
  6. package/lib/accounting-protocol.js.map +1 -0
  7. package/lib/admin-protocol.d.ts +31 -4
  8. package/lib/admin-protocol.d.ts.map +1 -1
  9. package/lib/admin-protocol.js +15 -0
  10. package/lib/admin-protocol.js.map +1 -1
  11. package/lib/analytics.d.ts +45 -0
  12. package/lib/analytics.d.ts.map +1 -0
  13. package/lib/analytics.js +10 -0
  14. package/lib/analytics.js.map +1 -0
  15. package/lib/auth.d.ts +25 -0
  16. package/lib/auth.d.ts.map +1 -0
  17. package/lib/auth.js +16 -0
  18. package/lib/auth.js.map +1 -0
  19. package/lib/context-url.d.ts +31 -0
  20. package/lib/context-url.d.ts.map +1 -0
  21. package/lib/context-url.js +102 -0
  22. package/lib/context-url.js.map +1 -0
  23. package/lib/context-url.spec.d.ts +14 -0
  24. package/lib/context-url.spec.d.ts.map +1 -0
  25. package/lib/context-url.spec.js +94 -0
  26. package/lib/context-url.spec.js.map +1 -0
  27. package/lib/email-protocol.d.ts +1 -2
  28. package/lib/email-protocol.d.ts.map +1 -1
  29. package/lib/email-protocol.js +4 -4
  30. package/lib/email-protocol.js.map +1 -1
  31. package/lib/encryption/container-module.js +5 -4
  32. package/lib/encryption/container-module.js.map +1 -1
  33. package/lib/encryption/encryption-engine.js +19 -20
  34. package/lib/encryption/encryption-engine.js.map +1 -1
  35. package/lib/encryption/encryption-engine.spec.js +29 -36
  36. package/lib/encryption/encryption-engine.spec.js.map +1 -1
  37. package/lib/encryption/encryption-service.js +29 -43
  38. package/lib/encryption/encryption-service.js.map +1 -1
  39. package/lib/encryption/key-provider.js +25 -30
  40. package/lib/encryption/key-provider.js.map +1 -1
  41. package/lib/env.d.ts +1 -2
  42. package/lib/env.d.ts.map +1 -1
  43. package/lib/env.js +20 -21
  44. package/lib/env.js.map +1 -1
  45. package/lib/gitpod-file-parser.js +25 -41
  46. package/lib/gitpod-file-parser.js.map +1 -1
  47. package/lib/gitpod-file-parser.spec.js +116 -116
  48. package/lib/gitpod-file-parser.spec.js.map +1 -1
  49. package/lib/gitpod-service.d.ts +162 -20
  50. package/lib/gitpod-service.d.ts.map +1 -1
  51. package/lib/gitpod-service.js +170 -256
  52. package/lib/gitpod-service.js.map +1 -1
  53. package/lib/headless-workspace-log.d.ts +8 -11
  54. package/lib/headless-workspace-log.d.ts.map +1 -1
  55. package/lib/headless-workspace-log.js +4 -7
  56. package/lib/headless-workspace-log.js.map +1 -1
  57. package/lib/ide-frontend-service.d.ts +4 -0
  58. package/lib/ide-frontend-service.d.ts.map +1 -1
  59. package/lib/ide-protocol.d.ts +105 -0
  60. package/lib/ide-protocol.d.ts.map +1 -0
  61. package/lib/ide-protocol.js +8 -0
  62. package/lib/ide-protocol.js.map +1 -0
  63. package/lib/index.d.ts +6 -0
  64. package/lib/index.d.ts.map +1 -1
  65. package/lib/index.js +7 -1
  66. package/lib/index.js.map +1 -1
  67. package/lib/installation-admin-protocol.d.ts +27 -0
  68. package/lib/installation-admin-protocol.d.ts.map +1 -0
  69. package/lib/installation-admin-protocol.js +30 -0
  70. package/lib/installation-admin-protocol.js.map +1 -0
  71. package/lib/messaging/browser/connection.d.ts +5 -3
  72. package/lib/messaging/browser/connection.d.ts.map +1 -1
  73. package/lib/messaging/browser/connection.js +183 -33
  74. package/lib/messaging/browser/connection.js.map +1 -1
  75. package/lib/messaging/browser/window-connection.js +35 -55
  76. package/lib/messaging/browser/window-connection.js.map +1 -1
  77. package/lib/messaging/client-call-metrics.d.ts +35 -0
  78. package/lib/messaging/client-call-metrics.d.ts.map +1 -0
  79. package/lib/messaging/client-call-metrics.js +83 -0
  80. package/lib/messaging/client-call-metrics.js.map +1 -0
  81. package/lib/messaging/error.d.ts +5 -1
  82. package/lib/messaging/error.d.ts.map +1 -1
  83. package/lib/messaging/error.js +10 -2
  84. package/lib/messaging/error.js.map +1 -1
  85. package/lib/messaging/handler.d.ts +10 -0
  86. package/lib/messaging/handler.d.ts.map +1 -1
  87. package/lib/messaging/node/connection.d.ts +1 -17
  88. package/lib/messaging/node/connection.d.ts.map +1 -1
  89. package/lib/messaging/node/connection.js +23 -59
  90. package/lib/messaging/node/connection.js.map +1 -1
  91. package/lib/messaging/proxy-factory.d.ts +2 -0
  92. package/lib/messaging/proxy-factory.d.ts.map +1 -1
  93. package/lib/messaging/proxy-factory.js +74 -159
  94. package/lib/messaging/proxy-factory.js.map +1 -1
  95. package/lib/oss-allowlist.d.ts +14 -0
  96. package/lib/oss-allowlist.d.ts.map +1 -0
  97. package/lib/oss-allowlist.js +8 -0
  98. package/lib/oss-allowlist.js.map +1 -0
  99. package/lib/payment-protocol.d.ts +18 -0
  100. package/lib/payment-protocol.d.ts.map +1 -0
  101. package/lib/payment-protocol.js +13 -0
  102. package/lib/payment-protocol.js.map +1 -0
  103. package/lib/permission.d.ts +8 -3
  104. package/lib/permission.d.ts.map +1 -1
  105. package/lib/permission.js +36 -19
  106. package/lib/permission.js.map +1 -1
  107. package/lib/plans.d.ts +210 -0
  108. package/lib/plans.d.ts.map +1 -0
  109. package/lib/plans.js +570 -0
  110. package/lib/plans.js.map +1 -0
  111. package/lib/protocol.d.ts +118 -58
  112. package/lib/protocol.d.ts.map +1 -1
  113. package/lib/protocol.js +116 -130
  114. package/lib/protocol.js.map +1 -1
  115. package/lib/snapshot-url.d.ts +14 -0
  116. package/lib/snapshot-url.d.ts.map +1 -0
  117. package/lib/snapshot-url.js +26 -0
  118. package/lib/snapshot-url.js.map +1 -0
  119. package/{src/util/without.ts → lib/snapshot-url.spec.d.ts} +2 -3
  120. package/lib/snapshot-url.spec.d.ts.map +1 -0
  121. package/lib/snapshot-url.spec.js +41 -0
  122. package/lib/snapshot-url.spec.js.map +1 -0
  123. package/lib/team-subscription-protocol.d.ts +73 -0
  124. package/lib/team-subscription-protocol.d.ts.map +1 -0
  125. package/lib/team-subscription-protocol.js +63 -0
  126. package/lib/team-subscription-protocol.js.map +1 -0
  127. package/lib/teams-projects-protocol.d.ts +113 -0
  128. package/lib/teams-projects-protocol.d.ts.map +1 -0
  129. package/lib/teams-projects-protocol.js +30 -0
  130. package/lib/teams-projects-protocol.js.map +1 -0
  131. package/lib/util/analytics.d.ts +8 -0
  132. package/lib/util/analytics.d.ts.map +1 -0
  133. package/lib/util/analytics.js +79 -0
  134. package/lib/util/analytics.js.map +1 -0
  135. package/lib/util/async-iterator.js +55 -133
  136. package/lib/util/async-iterator.js.map +1 -1
  137. package/lib/util/cancelable.js +17 -59
  138. package/lib/util/cancelable.js.map +1 -1
  139. package/lib/util/date-time.js +8 -8
  140. package/lib/util/date-time.js.map +1 -1
  141. package/lib/util/deferred.js +10 -12
  142. package/lib/util/deferred.js.map +1 -1
  143. package/lib/util/disposable.js +26 -39
  144. package/lib/util/disposable.js.map +1 -1
  145. package/lib/util/event.js +58 -74
  146. package/lib/util/event.js.map +1 -1
  147. package/lib/util/garbage-collected-cache.d.ts +1 -0
  148. package/lib/util/garbage-collected-cache.d.ts.map +1 -1
  149. package/lib/util/garbage-collected-cache.js +26 -46
  150. package/lib/util/garbage-collected-cache.js.map +1 -1
  151. package/lib/util/generate-workspace-id.d.ts +4 -0
  152. package/lib/util/generate-workspace-id.d.ts.map +1 -0
  153. package/lib/util/generate-workspace-id.js +487 -0
  154. package/lib/util/generate-workspace-id.js.map +1 -0
  155. package/lib/util/{without.d.ts → generate-workspace-id.spec.d.ts} +2 -2
  156. package/lib/util/generate-workspace-id.spec.d.ts.map +1 -0
  157. package/lib/util/generate-workspace-id.spec.js +87 -0
  158. package/lib/util/generate-workspace-id.spec.js.map +1 -0
  159. package/lib/util/gitpod-cookie.d.ts +20 -0
  160. package/lib/util/gitpod-cookie.d.ts.map +1 -0
  161. package/lib/util/gitpod-cookie.js +44 -0
  162. package/lib/util/gitpod-cookie.js.map +1 -0
  163. package/lib/util/gitpod-host-url.d.ts +2 -2
  164. package/lib/util/gitpod-host-url.d.ts.map +1 -1
  165. package/lib/util/gitpod-host-url.js +96 -95
  166. package/lib/util/gitpod-host-url.js.map +1 -1
  167. package/lib/util/gitpod-host-url.spec.d.ts +8 -1
  168. package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
  169. package/lib/util/gitpod-host-url.spec.js +104 -22
  170. package/lib/util/gitpod-host-url.spec.js.map +1 -1
  171. package/lib/util/grpc.d.ts +15 -0
  172. package/lib/util/grpc.d.ts.map +1 -0
  173. package/lib/util/grpc.js +18 -0
  174. package/lib/util/grpc.js.map +1 -0
  175. package/lib/util/jaeger-client-types.d.ts +68 -0
  176. package/lib/util/jaeger-client-types.d.ts.map +1 -0
  177. package/lib/util/{without.js → jaeger-client-types.js} +1 -1
  178. package/lib/util/jaeger-client-types.js.map +1 -0
  179. package/lib/util/logging.d.ts +49 -33
  180. package/lib/util/logging.d.ts.map +1 -1
  181. package/lib/util/logging.js +107 -110
  182. package/lib/util/logging.js.map +1 -1
  183. package/lib/util/make-link.js +2 -2
  184. package/lib/util/make-link.js.map +1 -1
  185. package/lib/util/parse-workspace-id.d.ts +13 -3
  186. package/lib/util/parse-workspace-id.d.ts.map +1 -1
  187. package/lib/util/parse-workspace-id.js +38 -8
  188. package/lib/util/parse-workspace-id.js.map +1 -1
  189. package/lib/util/parse-workspace-id.spec.d.ts +8 -0
  190. package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
  191. package/lib/util/parse-workspace-id.spec.js +127 -47
  192. package/lib/util/parse-workspace-id.spec.js.map +1 -1
  193. package/lib/util/queue.js +16 -55
  194. package/lib/util/queue.js.map +1 -1
  195. package/lib/util/queue.spec.js +144 -288
  196. package/lib/util/queue.spec.js.map +1 -1
  197. package/lib/util/repeat.d.ts +15 -0
  198. package/lib/util/repeat.d.ts.map +1 -0
  199. package/lib/util/repeat.js +55 -0
  200. package/lib/util/repeat.js.map +1 -0
  201. package/lib/util/semaphore.js +15 -46
  202. package/lib/util/semaphore.js.map +1 -1
  203. package/lib/util/skip-if.js +6 -6
  204. package/lib/util/skip-if.js.map +1 -1
  205. package/lib/util/timeutil.js +28 -16
  206. package/lib/util/timeutil.js.map +1 -1
  207. package/lib/util/timeutil.spec.js +21 -24
  208. package/lib/util/timeutil.spec.js.map +1 -1
  209. package/lib/util/tracing.d.ts +51 -5
  210. package/lib/util/tracing.d.ts.map +1 -1
  211. package/lib/util/tracing.js +197 -62
  212. package/lib/util/tracing.js.map +1 -1
  213. package/lib/util/tracing.spec.d.ts +7 -0
  214. package/lib/util/tracing.spec.d.ts.map +1 -0
  215. package/lib/util/tracing.spec.js +121 -0
  216. package/lib/util/tracing.spec.js.map +1 -0
  217. package/lib/util/workspace-port-authentication.js +3 -2
  218. package/lib/util/workspace-port-authentication.js.map +1 -1
  219. package/lib/workspace-cluster.d.ts +76 -0
  220. package/lib/workspace-cluster.d.ts.map +1 -0
  221. package/lib/workspace-cluster.js +33 -0
  222. package/lib/workspace-cluster.js.map +1 -0
  223. package/lib/workspace-instance.d.ts +26 -2
  224. package/lib/workspace-instance.d.ts.map +1 -1
  225. package/lib/wsready.d.ts +1 -1
  226. package/lib/wsready.js +2 -2
  227. package/package.json +33 -17
  228. package/pkg-yarn.lock +18 -9
  229. package/provenance-bundle.jsonl +2 -0
  230. package/src/accounting-protocol.ts +229 -0
  231. package/src/admin-protocol.ts +53 -5
  232. package/src/analytics.ts +54 -0
  233. package/src/auth.ts +27 -0
  234. package/src/context-url.spec.ts +53 -0
  235. package/src/context-url.ts +107 -0
  236. package/src/email-protocol.ts +2 -3
  237. package/src/env.ts +10 -10
  238. package/src/gitpod-service.ts +237 -38
  239. package/src/headless-workspace-log.ts +7 -11
  240. package/src/ide-frontend-service.ts +5 -1
  241. package/src/ide-protocol.ts +119 -0
  242. package/src/index.ts +7 -1
  243. package/src/installation-admin-protocol.ts +42 -0
  244. package/src/messaging/browser/connection.ts +195 -14
  245. package/src/messaging/client-call-metrics.ts +97 -0
  246. package/src/messaging/error.ts +14 -2
  247. package/src/messaging/handler.ts +12 -0
  248. package/src/messaging/node/connection.ts +21 -68
  249. package/src/messaging/proxy-factory.ts +14 -6
  250. package/src/oss-allowlist.ts +15 -0
  251. package/src/payment-protocol.ts +20 -0
  252. package/src/permission.ts +24 -9
  253. package/src/plans.ts +632 -0
  254. package/src/protocol.ts +192 -87
  255. package/src/snapshot-url.spec.ts +25 -0
  256. package/src/snapshot-url.ts +27 -0
  257. package/src/team-subscription-protocol.ts +113 -0
  258. package/src/teams-projects-protocol.ts +147 -0
  259. package/src/util/analytics.ts +87 -0
  260. package/src/util/deferred.ts +1 -1
  261. package/src/util/garbage-collected-cache.ts +9 -3
  262. package/src/util/generate-workspace-id.spec.ts +48 -0
  263. package/src/util/generate-workspace-id.ts +475 -0
  264. package/src/util/gitpod-cookie.ts +39 -0
  265. package/src/util/gitpod-host-url.spec.ts +30 -1
  266. package/src/util/gitpod-host-url.ts +27 -13
  267. package/src/util/grpc.ts +15 -0
  268. package/src/util/jaeger-client-types.ts +102 -0
  269. package/src/util/logging.ts +102 -38
  270. package/src/util/parse-workspace-id.spec.ts +45 -4
  271. package/src/util/parse-workspace-id.ts +38 -7
  272. package/src/util/queue.spec.ts +1 -1
  273. package/src/util/repeat.ts +45 -0
  274. package/src/util/semaphore.ts +2 -2
  275. package/src/util/skip-if.ts +1 -1
  276. package/src/util/timeutil.ts +4 -4
  277. package/src/util/tracing.spec.ts +83 -0
  278. package/src/util/tracing.ts +183 -17
  279. package/src/workspace-cluster.ts +104 -0
  280. package/src/workspace-instance.ts +51 -13
  281. package/src/wsready.ts +2 -2
  282. package/lib/messaging/connection-error-handler.d.ts +0 -27
  283. package/lib/messaging/connection-error-handler.d.ts.map +0 -1
  284. package/lib/messaging/connection-error-handler.js +0 -46
  285. package/lib/messaging/connection-error-handler.js.map +0 -1
  286. package/lib/util/repeater.d.ts +0 -22
  287. package/lib/util/repeater.d.ts.map +0 -1
  288. package/lib/util/repeater.js +0 -118
  289. package/lib/util/repeater.js.map +0 -1
  290. package/lib/util/safe-promise.d.ts +0 -11
  291. package/lib/util/safe-promise.d.ts.map +0 -1
  292. package/lib/util/safe-promise.js +0 -34
  293. package/lib/util/safe-promise.js.map +0 -1
  294. package/lib/util/without.d.ts.map +0 -1
  295. package/lib/util/without.js.map +0 -1
  296. package/src/messaging/connection-error-handler.ts +0 -62
  297. package/src/util/jaeger-client.d.ts +0 -105
  298. package/src/util/repeater.ts +0 -49
  299. package/src/util/safe-promise.ts +0 -26
package/src/plans.ts ADDED
@@ -0,0 +1,632 @@
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
+ export type Currency = 'USD' | 'EUR';
8
+ export namespace Currency {
9
+ export const getAll = (): Currency[] => {
10
+ return ['USD', 'EUR'];
11
+ }
12
+ export const getSymbol = (c: Currency) => {
13
+ return c === 'USD' ? '$' : '€';
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Different plans of the same type MAY have different prices ($/€, for example) but MUST have the same feature set.
19
+ */
20
+ export type PlanType = 'free' | 'free-50' | 'free-open-source' | 'student' | 'basic' | 'personal' | 'professional' | 'professional-new';
21
+ export type HoursPerMonthType = number | 'unlimited';
22
+ export interface Plan {
23
+ chargebeeId: string
24
+ githubId?: number
25
+ githubPlanNumber?: number
26
+
27
+ name: string
28
+ currency: Currency
29
+ /** In full currencies (Euro, US Dollar, ...) */
30
+ pricePerMonth: number
31
+ hoursPerMonth: HoursPerMonthType
32
+ type: PlanType
33
+ team?: boolean
34
+ }
35
+ export namespace Plan {
36
+ export const is = (o: any): o is Plan => {
37
+ return 'chargebeeId' in o
38
+ && 'name' in o
39
+ && 'currency' in o
40
+ && 'pricePerMonth' in o
41
+ && 'hoursPerMonth' in o
42
+ && 'type' in o;
43
+ }
44
+ }
45
+
46
+ export const MAX_PARALLEL_WORKSPACES = 16;
47
+
48
+ export interface Coupon {
49
+ id: string;
50
+ isGithubStudentCoupon?: boolean;
51
+ }
52
+ export namespace Coupon {
53
+ export const is = (o: any): o is Coupon => {
54
+ return 'id' in o;
55
+ }
56
+ }
57
+ export namespace Coupons {
58
+ export const INTERNAL_GITPOD_GHSP: Coupon = {
59
+ id: "INTERNAL_GITPOD_GHSP",
60
+ isGithubStudentCoupon: true
61
+ };
62
+ export const INTERNAL_GITPOD_GHSP_2: Coupon = {
63
+ id: "INTERNAL_GITPOD_GHSP_2",
64
+ isGithubStudentCoupon: true
65
+ };
66
+ export const GITHUBSTUDENTPACKFORFACULTY: Coupon = {
67
+ id: "GITHUBSTUDENTPACKFORFACULTY",
68
+ isGithubStudentCoupon: true
69
+ };
70
+ export const isGithubStudentCoupon = (id: string): boolean | undefined => {
71
+ const c = getAllCoupons().find(ic => ic.id === id);
72
+ if (!c) {
73
+ return undefined;
74
+ }
75
+ return !!c.isGithubStudentCoupon;
76
+ };
77
+ export const getAllCoupons = (): Coupon[] => {
78
+ return Object.keys(Coupons)
79
+ .map(k => (Coupons as any)[k])
80
+ .filter(a => typeof a === 'object' && Coupon.is(a));
81
+ };
82
+ }
83
+
84
+ // Theoretical maximum of workspace hours: 16 workspaces for 24h a day for 31 days as permitted by the v3 unlimited plan
85
+ // Other unlimited hour plans are restricted by the number of Parallel Workspaces they can start.
86
+ export const ABSOLUTE_MAX_USAGE = MAX_PARALLEL_WORKSPACES * 24 * 31;
87
+
88
+ /**
89
+ * Version history:
90
+ * - v1:
91
+ * - Free
92
+ * - Basic
93
+ * - Professional
94
+ * - Team Professional
95
+ * - v2:
96
+ * - Free
97
+ * - Personal
98
+ * - Unlimited: rebranded professional with unlimited hours
99
+ * - Team Unlimited: rebranded professional with unlimited hours
100
+ * - dropped: Basic
101
+ * - v2.5:
102
+ * + Student Unlimited
103
+ * + Team Unlimited Student
104
+ * - V3:
105
+ * - Free: reduced to 50h (stays default, but not advertised directly anymore)
106
+ * - Personal (8/9)
107
+ * - Professional (23/25)
108
+ * - Unlimited (35/39)
109
+ * - v4:
110
+ * - Professional Open Source (free)
111
+ * - v5:
112
+ * - Unleashed: rebranded Unlimited
113
+ */
114
+ export namespace Plans {
115
+ /**
116
+ * The old default plan (v1): 100h hours for public repos
117
+ */
118
+ export const FREE: Plan = {
119
+ chargebeeId: 'free',
120
+ githubId: 2034,
121
+ githubPlanNumber: 1,
122
+
123
+ type: 'free',
124
+ name: 'Open Source',
125
+ currency: 'USD',
126
+ pricePerMonth: 0,
127
+ hoursPerMonth: 100
128
+ };
129
+
130
+ /**
131
+ * The new default plan (v3): 50h hours for public repos
132
+ */
133
+ export const FREE_50: Plan = {
134
+ chargebeeId: 'free-50',
135
+ githubId: 4902,
136
+ githubPlanNumber: 5,
137
+
138
+ type: 'free-50',
139
+ name: 'Open Source',
140
+ currency: 'USD',
141
+ pricePerMonth: 0,
142
+ hoursPerMonth: 50
143
+ };
144
+
145
+ /**
146
+ * Users created after this date get the FREE_50 plan (v3) instead of the (old) FREE plan (v1)
147
+ */
148
+ export const FREE_50_START_DATE = '2019-12-19T00:00:00.000Z';
149
+
150
+ /**
151
+ * The 'Professional Open Source' plan was introduced to offer professional open-souce developers unlimited hours.
152
+ */
153
+ export const FREE_OPEN_SOURCE: Plan = {
154
+ chargebeeId: 'free-open-source',
155
+ type: 'free-open-source',
156
+ name: 'Professional Open Source',
157
+ currency: 'USD',
158
+ pricePerMonth: 0,
159
+ hoursPerMonth: 'unlimited'
160
+ };
161
+
162
+ /**
163
+ * The 'Student Unleashed' plans were introduced to give students access to the highly-priced unlimited plans.
164
+ */
165
+ export const PROFESSIONAL_STUDENT_EUR: Plan = {
166
+ chargebeeId: 'professional-student-eur',
167
+ type: 'student',
168
+ name: 'Student Unleashed',
169
+ currency: 'EUR',
170
+ pricePerMonth: 8,
171
+ hoursPerMonth: 'unlimited'
172
+ };
173
+
174
+ /**
175
+ * The 'Student Unleashed' plans were introduced to give students access to the highly-priced unlimited plans.
176
+ */
177
+ export const PROFESSIONAL_STUDENT_USD: Plan = {
178
+ chargebeeId: 'professional-student-usd',
179
+ type: 'student',
180
+ name: 'Student Unleashed',
181
+ currency: 'USD',
182
+ pricePerMonth: 9,
183
+ hoursPerMonth: 'unlimited'
184
+ };
185
+
186
+ /**
187
+ * The 'Student Unleashed' plans were introduced to give students access to the highly-priced unlimited plans.
188
+ */
189
+ export const TEAM_PROFESSIONAL_STUDENT_EUR: Plan = {
190
+ chargebeeId: 'team-professional-student-eur',
191
+ type: 'student',
192
+ name: 'Team Student Unleashed',
193
+ team: true,
194
+ currency: 'EUR',
195
+ pricePerMonth: 8,
196
+ hoursPerMonth: 'unlimited'
197
+ };
198
+
199
+ /**
200
+ * The 'Student Unleashed' plans were introduced to give students access to the highly-priced unlimited plans.
201
+ */
202
+ export const TEAM_PROFESSIONAL_STUDENT_USD: Plan = {
203
+ chargebeeId: 'team-professional-student-usd',
204
+ type: 'student',
205
+ name: 'Team Student Unleashed',
206
+ team: true,
207
+ currency: 'USD',
208
+ pricePerMonth: 9,
209
+ hoursPerMonth: 'unlimited'
210
+ };
211
+
212
+ /**
213
+ * The 'basic' plan was the original differentiator between FREE and Professional (v1) but got discarded soon.
214
+ */
215
+ export const BASIC_EUR: Plan = {
216
+ chargebeeId: 'basic-eur',
217
+ type: 'basic',
218
+ name: 'Standard',
219
+ currency: 'EUR',
220
+ pricePerMonth: 17,
221
+ hoursPerMonth: 100
222
+ };
223
+
224
+ /**
225
+ * The 'basic' plan was the original differentiator between FREE and Professional (v1) but got discarded soon.
226
+ */
227
+ export const BASIC_USD: Plan = {
228
+ chargebeeId: 'basic-usd',
229
+ githubId: 2035,
230
+ githubPlanNumber: 2,
231
+
232
+ type: 'basic',
233
+ name: 'Standard',
234
+ currency: 'USD',
235
+ pricePerMonth: 19,
236
+ hoursPerMonth: 100
237
+ };
238
+
239
+ /**
240
+ * The 'personal' plan was introduced to superseed the 'basic' plan (introduced with v2) to be more attractive to hobbyists.
241
+ */
242
+ export const PERSONAL_EUR: Plan = {
243
+ chargebeeId: 'personal-eur',
244
+ type: 'personal',
245
+ name: 'Personal',
246
+ currency: 'EUR',
247
+ pricePerMonth: 8,
248
+ hoursPerMonth: 100
249
+ };
250
+
251
+ /**
252
+ * The 'personal' plan was introduced to superseed the 'basic' plan (introduced with v2) to be more attractive to hobbyists.
253
+ */
254
+ export const PERSONAL_USD: Plan = {
255
+ chargebeeId: 'personal-usd',
256
+ githubId: 2274,
257
+ githubPlanNumber: 4,
258
+
259
+ type: 'personal',
260
+ name: 'Personal',
261
+ currency: 'USD',
262
+ pricePerMonth: 9,
263
+ hoursPerMonth: 100
264
+ };
265
+
266
+ /**
267
+ * This is the 'new' Professional plan (v3), which is meant to fit well between Personal (9$/8€) on the left and
268
+ * Unleashed (39$/35€) on the right.
269
+ */
270
+ export const PROFESSIONAL_NEW_EUR: Plan = {
271
+ chargebeeId: 'professional-new-eur',
272
+ type: 'professional-new',
273
+ name: 'Professional',
274
+ currency: 'EUR',
275
+ pricePerMonth: 23,
276
+ hoursPerMonth: 'unlimited'
277
+ };
278
+
279
+ /**
280
+ * This is the 'new' Professional plan (v3), which is meant to fit well between Personal (9$/8€) on the left and
281
+ * Unleashed (39$/35€) on the right.
282
+ */
283
+ export const PROFESSIONAL_NEW_USD: Plan = {
284
+ chargebeeId: 'professional-new-usd',
285
+ type: 'professional-new',
286
+ name: 'Professional',
287
+ currency: 'USD',
288
+ pricePerMonth: 25,
289
+ hoursPerMonth: 'unlimited'
290
+ };
291
+
292
+ /**
293
+ * This is the 'new' Team Professional plan (v3), which is meant to fit well between Personal (9$/8€) on the left and
294
+ * Unleashed (39$/35€) on the right.
295
+ */
296
+ export const TEAM_PROFESSIONAL_NEW_EUR: Plan = {
297
+ chargebeeId: 'team-professional-new-eur',
298
+ type: 'professional-new',
299
+ name: 'Team Professional',
300
+ currency: 'EUR',
301
+ team: true,
302
+ pricePerMonth: 23,
303
+ hoursPerMonth: 'unlimited'
304
+ };
305
+
306
+ /**
307
+ * This is the 'new' Team Professional plan (v3), which is meant to fit well between Personal (9$/8€) on the left and
308
+ * Unleashed (39$/35€) on the right.
309
+ */
310
+ export const TEAM_PROFESSIONAL_NEW_USD: Plan = {
311
+ chargebeeId: 'team-professional-new-usd',
312
+ type: 'professional-new',
313
+ name: 'Team Professional',
314
+ currency: 'USD',
315
+ team: true,
316
+ pricePerMonth: 25,
317
+ hoursPerMonth: 'unlimited'
318
+ };
319
+
320
+ /**
321
+ * This is the 'Unleashed' plan (v1, rebranded v2, v5)
322
+ * It was originally introduced as 'Professional', and we cannot update the ids, so it stays that way in the code.
323
+ */
324
+ export const PROFESSIONAL_EUR: Plan = {
325
+ chargebeeId: 'professional-eur',
326
+ type: 'professional',
327
+ name: 'Unleashed',
328
+ currency: 'EUR',
329
+ pricePerMonth: 35,
330
+ hoursPerMonth: 'unlimited'
331
+ };
332
+
333
+ /**
334
+ * This is the 'Unleashed' plan (v1, rebranded v2, v5)
335
+ * It was originally introduced as 'Professional', and we cannot update the ids, so it stays that way in the code.
336
+ */
337
+ export const PROFESSIONAL_USD: Plan = {
338
+ chargebeeId: 'professional-usd',
339
+ githubId: 2036,
340
+ githubPlanNumber: 3,
341
+
342
+ type: 'professional',
343
+ name: 'Unleashed',
344
+ currency: 'USD',
345
+ pricePerMonth: 39,
346
+ hoursPerMonth: 'unlimited'
347
+ };
348
+
349
+ /**
350
+ * This is the Team-'Unleashed' plan (v1, rebranded v2, v5)
351
+ * It was originally introduced as 'Professional', and we cannot update the ids, so it stays that way in the code.
352
+ */
353
+ export const TEAM_PROFESSIONAL_USD: Plan = {
354
+ chargebeeId: 'team-professional-usd',
355
+ type: 'professional',
356
+ name: 'Team Unleashed',
357
+ currency: 'USD',
358
+ team: true,
359
+ pricePerMonth: 39,
360
+ hoursPerMonth: 'unlimited'
361
+ };
362
+
363
+ /**
364
+ * This is the Team-'Unleashed' plan (v1, rebranded v2, v5)
365
+ * It was originally introduced as 'Professional', and we cannot update the ids, so it stays that way in the code.
366
+ */
367
+ export const TEAM_PROFESSIONAL_EUR: Plan = {
368
+ chargebeeId: 'team-professional-eur',
369
+ type: 'professional',
370
+ name: 'Team Unleashed',
371
+ currency: 'EUR',
372
+ team: true,
373
+ pricePerMonth: 35,
374
+ hoursPerMonth: 'unlimited'
375
+ };
376
+
377
+ const getAllPlans = (): Plan[] => {
378
+ return Object.keys(Plans)
379
+ .map(k => (Plans as any)[k])
380
+ .filter(a => typeof a === 'object' && Plan.is(a));
381
+ };
382
+
383
+
384
+ /**
385
+ * This function returns all individual plans that might be active (= we have subscriptions for) at the moment
386
+ */
387
+ export function getAvailablePlans(currency: Currency): Plan[] {
388
+ const availablePaidPlans = [
389
+ Plans.BASIC_EUR,
390
+ Plans.BASIC_USD,
391
+ Plans.PERSONAL_EUR,
392
+ Plans.PERSONAL_USD,
393
+ Plans.PROFESSIONAL_NEW_EUR,
394
+ Plans.PROFESSIONAL_NEW_USD,
395
+ Plans.PROFESSIONAL_EUR,
396
+ Plans.PROFESSIONAL_USD
397
+ ];
398
+ return [
399
+ Plans.FREE,
400
+ Plans.FREE_50,
401
+ Plans.FREE_OPEN_SOURCE,
402
+ ...availablePaidPlans.filter(p => p.currency)
403
+ ]
404
+ };
405
+
406
+ export const getAvailableTeamPlans = (currency?: Currency): Plan[] => {
407
+ const teamPlans = getAllPlans().filter(p => !!p.team);
408
+ return currency ? teamPlans.filter(p => p.currency === currency) : teamPlans;
409
+ };
410
+
411
+ export function getById(id: string | undefined): Plan | undefined {
412
+ if (id === undefined) {
413
+ return undefined;
414
+ }
415
+ return getAllPlans()
416
+ .find(p => p.chargebeeId === id) || undefined;
417
+ };
418
+
419
+ export function getByTypeAndCurrency(type: PlanType, currency: Currency): Plan | undefined {
420
+ return getAllPlans()
421
+ .filter(p => p.type)
422
+ .find(p => p.currency === currency);
423
+ }
424
+
425
+ export function getProPlan(currency: Currency): Plan {
426
+ switch (currency) {
427
+ case "EUR": return Plans.PROFESSIONAL_EUR;
428
+ case "USD": return Plans.PROFESSIONAL_USD;
429
+ }
430
+ }
431
+
432
+ export function getNewProPlan(currency: Currency): Plan {
433
+ switch (currency) {
434
+ case "EUR": return Plans.PROFESSIONAL_NEW_EUR;
435
+ case "USD": return Plans.PROFESSIONAL_NEW_USD;
436
+ }
437
+ }
438
+
439
+ export function getStudentProPlan(currency: Currency): Plan {
440
+ switch (currency) {
441
+ case "EUR": return Plans.PROFESSIONAL_STUDENT_EUR;
442
+ case "USD": return Plans.PROFESSIONAL_STUDENT_USD;
443
+ }
444
+ }
445
+
446
+ export function getBasicPlan(currency: Currency): Plan {
447
+ switch (currency) {
448
+ case "EUR": return Plans.BASIC_EUR;
449
+ case "USD": return Plans.BASIC_USD;
450
+ }
451
+ }
452
+
453
+ export function getPersonalPlan(currency: Currency): Plan {
454
+ switch (currency) {
455
+ case "EUR": return Plans.PERSONAL_EUR;
456
+ case "USD": return Plans.PERSONAL_USD;
457
+ }
458
+ }
459
+
460
+ export function getFreePlan(userCreationDate: string): Plan {
461
+ return userCreationDate < Plans.FREE_50_START_DATE ? Plans.FREE : Plans.FREE_50;
462
+ }
463
+
464
+ export function isFreePlan(chargebeeId: string | undefined): boolean {
465
+ return chargebeeId === Plans.FREE.chargebeeId
466
+ || chargebeeId === Plans.FREE_50.chargebeeId
467
+ || chargebeeId === Plans.FREE_OPEN_SOURCE.chargebeeId;
468
+ }
469
+
470
+ export function isFreeNonTransientPlan(chargebeeId: string | undefined): boolean {
471
+ return chargebeeId === Plans.FREE_OPEN_SOURCE.chargebeeId;
472
+ }
473
+
474
+ export function getHoursPerMonth(plan: Plan): number {
475
+ return plan.hoursPerMonth == 'unlimited' ? ABSOLUTE_MAX_USAGE : plan.hoursPerMonth;
476
+ }
477
+
478
+ /**
479
+ * Returns the maximum number of parallel workspaces for the given plan
480
+ * @param plan
481
+ */
482
+ export function getParallelWorkspacesById(planId: string | undefined): number {
483
+ return getParallelWorkspaces(Plans.getById(planId));
484
+ }
485
+
486
+ /**
487
+ * Returns the maximum number of parallel workspaces for the given plan
488
+ * @param plan
489
+ */
490
+ export function getParallelWorkspaces(plan: Plan | undefined): number {
491
+ const DEFAULT = 4;
492
+ if (!plan) {
493
+ return DEFAULT;
494
+ }
495
+
496
+ switch (plan.type) {
497
+ case "professional-new":
498
+ return 8;
499
+
500
+ case "professional":
501
+ case "student":
502
+ return 16;
503
+ }
504
+ return DEFAULT;
505
+ }
506
+
507
+
508
+ /**
509
+ * This declares the plan structure we have in Gitpod: All entries in a sub-array have the same arity in this structure.
510
+ * This is used to impose a partial order on plan types (cmp. compareTypes(...)).
511
+ * The order inside the sub-array carries meaning, too: The first one is the current, preferred plan (we advertise) for the given arity.
512
+ * This is used to be able to get the next "higher" plan (cmp. getNextHigherPlanType).
513
+ */
514
+ const planStructure: PlanType[][] = [
515
+ ["free-50", "free", "free-open-source"],
516
+ ["personal", "basic"],
517
+ ["professional-new"],
518
+ ["professional", "student"]
519
+ ];
520
+
521
+ function getPlanTypeArity(type: PlanType) {
522
+ return planStructure.findIndex((types: PlanType[]) => types.includes(type));
523
+ }
524
+
525
+ function getPlanTypeForArity(arity: number): PlanType | undefined {
526
+ if (arity >= planStructure.length) {
527
+ return undefined;
528
+ }
529
+ return planStructure[arity][0];
530
+ }
531
+
532
+ /**
533
+ * Returns the preferred plan type with the next higher arity
534
+ * @param type
535
+ */
536
+ export function getNextHigherPlanType(type: PlanType): PlanType {
537
+ const arity = getPlanTypeArity(type);
538
+ const nextHigherType = getPlanTypeForArity(arity + 1);
539
+ return nextHigherType || "professional";
540
+ }
541
+
542
+ /**
543
+ * This imposes a partial order on the plan types
544
+ * @param planTypeA
545
+ * @param planTypeB
546
+ */
547
+ export function compareTypes(planTypeA: PlanType, planTypeB: PlanType) {
548
+ const va = getPlanTypeArity(planTypeA);
549
+ const vb = getPlanTypeArity(planTypeB);
550
+ return va < vb ? -1 : va > vb ? 1 : 0;
551
+ }
552
+
553
+ export function subscriptionChange(fromType: PlanType, toType: PlanType): "upgrade" | "downgrade" | "none" {
554
+ const cmp = Plans.compareTypes(fromType, toType);
555
+ if (cmp < 0) {
556
+ return "upgrade";
557
+ } else if (cmp > 0) {
558
+ return "downgrade";
559
+ } else {
560
+ return "none";
561
+ }
562
+ }
563
+
564
+ export interface Feature {
565
+ title: string;
566
+ emph?: boolean;
567
+ link?: string;
568
+ tooltip?: string;
569
+ }
570
+ export namespace Feature {
571
+ export const getFeaturesFor = (p: Plan): Feature[] => {
572
+ switch (p.type) {
573
+ case "free":
574
+ return [
575
+ { title: 'Public repositories' }
576
+ ];
577
+
578
+ case "free-50":
579
+ return [
580
+ { title: 'Public repositories' }
581
+ ];
582
+
583
+ case "free-open-source":
584
+ return [
585
+ { title: 'Public repositories' },
586
+ ];
587
+
588
+ case "student":
589
+ return [
590
+ { title: 'Private & Public repos' },
591
+ { title: `${Plans.getParallelWorkspaces(p)} Parallel Workspaces`, tooltip: 'The number of workspaces running at the same time' },
592
+ { title: 'Team Manageable', link: "/teams/", tooltip: 'Setup Gitpod for an entire Team with a single invoice and credit card' },
593
+ { title: '1h Timeout', tooltip: 'Workspaces without user activity are stopped after 1 hour' },
594
+ { title: '3h Timeout Boost', tooltip: 'You can manually boost the timeout to 3 hours within a running workspace' }
595
+ ];
596
+
597
+ case "basic":
598
+ return [
599
+ { title: 'Private & Public repos' },
600
+ { title: `${Plans.getParallelWorkspaces(p)} Parallel Workspaces`, tooltip: 'The number of workspaces running at the same time.' },
601
+ ];
602
+
603
+ // Personal
604
+ case "personal":
605
+ return [
606
+ { title: 'Private & Public repos' },
607
+ { title: `${Plans.getParallelWorkspaces(p)} Parallel Workspaces`, tooltip: 'The number of workspaces running at the same time' },
608
+ { title: '30min Timeout', tooltip: 'Workspaces without user activity are stopped after 30 minutes' }
609
+ ];
610
+
611
+ // Professional
612
+ case "professional-new":
613
+ return [
614
+ { title: 'Private & Public repos' },
615
+ { title: `${Plans.getParallelWorkspaces(p)} Parallel Workspaces`, tooltip: 'The number of workspaces running at the same time' },
616
+ { title: 'Team Manageable', link: "/teams/", tooltip: 'Setup Gitpod for an entire Team with a single invoice and credit card' },
617
+ { title: '30min Timeout', tooltip: 'Workspaces without user activity are stopped after 30 minutes' }
618
+ ];
619
+
620
+ // Unleashed
621
+ case "professional":
622
+ return [
623
+ { title: 'Private & Public repos' },
624
+ { title: `${Plans.getParallelWorkspaces(p)} Parallel Workspaces`, tooltip: 'The number of workspaces running at the same time' },
625
+ { title: 'Team Manageable', link: "/teams/", tooltip: 'Setup Gitpod for an entire Team with a single invoice and credit card' },
626
+ { title: '1h Timeout', tooltip: 'Workspaces without user activity are stopped after 1 hour' },
627
+ { title: '3h Timeout Boost', tooltip: 'You can manually boost the timeout to 3 hours within a running workspace' }
628
+ ];
629
+ }
630
+ };
631
+ }
632
+ }