@gitpod/gitpod-protocol 0.1.5-to-code-reading.1 → 0.1.5-to-monitor-delete.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/gitpod-schema.json +124 -5
- package/lib/accounting-protocol.d.ts +18 -10
- package/lib/accounting-protocol.d.ts.map +1 -1
- package/lib/accounting-protocol.js +34 -32
- package/lib/accounting-protocol.js.map +1 -1
- package/lib/admin-protocol.d.ts +19 -0
- package/lib/admin-protocol.d.ts.map +1 -1
- package/lib/admin-protocol.js.map +1 -1
- package/lib/analytics.d.ts +4 -5
- package/lib/analytics.d.ts.map +1 -1
- package/lib/analytics.js.map +1 -1
- package/lib/attribution.d.ts +24 -0
- package/lib/attribution.d.ts.map +1 -0
- package/lib/attribution.js +54 -0
- package/lib/attribution.js.map +1 -0
- package/lib/auth.d.ts.map +1 -1
- package/lib/billing-mode.d.ts +45 -0
- package/lib/billing-mode.d.ts.map +1 -0
- package/lib/billing-mode.js +44 -0
- package/lib/billing-mode.js.map +1 -0
- package/lib/blocked-repositories-protocol.d.ts +13 -0
- package/lib/blocked-repositories-protocol.d.ts.map +1 -0
- package/lib/blocked-repositories-protocol.js +8 -0
- package/lib/blocked-repositories-protocol.js.map +1 -0
- package/lib/context-url.d.ts +18 -5
- package/lib/context-url.d.ts.map +1 -1
- package/lib/context-url.js +59 -6
- package/lib/context-url.js.map +1 -1
- package/lib/context-url.spec.d.ts +2 -0
- package/lib/context-url.spec.d.ts.map +1 -1
- package/lib/context-url.spec.js +40 -4
- package/lib/context-url.spec.js.map +1 -1
- package/lib/encryption/container-module.d.ts.map +1 -1
- package/lib/encryption/container-module.js +1 -1
- package/lib/encryption/container-module.js.map +1 -1
- package/lib/encryption/encryption-engine.d.ts.map +1 -1
- package/lib/encryption/encryption-engine.js +9 -9
- package/lib/encryption/encryption-engine.js.map +1 -1
- package/lib/encryption/encryption-engine.spec.d.ts.map +1 -1
- package/lib/encryption/encryption-engine.spec.js +2 -3
- package/lib/encryption/encryption-engine.spec.js.map +1 -1
- package/lib/encryption/encryption-service.d.ts.map +1 -1
- package/lib/encryption/encryption-service.js +1 -1
- package/lib/encryption/encryption-service.js.map +1 -1
- package/lib/encryption/key-provider.d.ts.map +1 -1
- package/lib/encryption/key-provider.js +7 -9
- package/lib/encryption/key-provider.js.map +1 -1
- package/lib/env.d.ts +0 -5
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +1 -20
- package/lib/env.js.map +1 -1
- package/lib/experiments/always-default.d.ts +8 -0
- package/lib/experiments/always-default.d.ts.map +1 -0
- package/lib/experiments/always-default.js +20 -0
- package/lib/experiments/always-default.js.map +1 -0
- package/lib/experiments/configcat-server.d.ts +10 -0
- package/lib/experiments/configcat-server.d.ts.map +1 -0
- package/lib/experiments/configcat-server.js +36 -0
- package/lib/experiments/configcat-server.js.map +1 -0
- package/lib/experiments/configcat.d.ts +21 -0
- package/lib/experiments/configcat.d.ts.map +1 -0
- package/lib/experiments/configcat.js +51 -0
- package/lib/experiments/configcat.js.map +1 -0
- package/lib/experiments/types.d.ts +22 -0
- package/lib/experiments/types.d.ts.map +1 -0
- package/lib/experiments/types.js +10 -0
- package/lib/experiments/types.js.map +1 -0
- package/lib/gitpod-file-parser.d.ts.map +1 -1
- package/lib/gitpod-file-parser.js +6 -6
- package/lib/gitpod-file-parser.js.map +1 -1
- package/lib/gitpod-file-parser.spec.js +42 -39
- package/lib/gitpod-file-parser.spec.js.map +1 -1
- package/lib/gitpod-service.d.ts +83 -45
- package/lib/gitpod-service.d.ts.map +1 -1
- package/lib/gitpod-service.js +52 -33
- package/lib/gitpod-service.js.map +1 -1
- package/lib/headless-workspace-log.d.ts +1 -0
- package/lib/headless-workspace-log.d.ts.map +1 -1
- package/lib/headless-workspace-log.js +2 -1
- package/lib/headless-workspace-log.js.map +1 -1
- package/lib/ide-frontend-service.d.ts +1 -1
- package/lib/ide-protocol.d.ts +38 -6
- package/lib/ide-protocol.d.ts.map +1 -1
- package/lib/index.d.ts +16 -15
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/installation-admin-protocol.d.ts +30 -0
- package/lib/installation-admin-protocol.d.ts.map +1 -0
- package/lib/installation-admin-protocol.js +31 -0
- package/lib/installation-admin-protocol.js.map +1 -0
- package/lib/license-protocol.d.ts +7 -0
- package/lib/license-protocol.d.ts.map +1 -1
- package/lib/license-protocol.js.map +1 -1
- package/lib/messaging/browser/connection.d.ts +1 -1
- package/lib/messaging/browser/connection.d.ts.map +1 -1
- package/lib/messaging/browser/connection.js +19 -19
- package/lib/messaging/browser/connection.js.map +1 -1
- package/lib/messaging/browser/window-connection.d.ts +4 -4
- package/lib/messaging/browser/window-connection.d.ts.map +1 -1
- package/lib/messaging/browser/window-connection.js +9 -6
- package/lib/messaging/browser/window-connection.js.map +1 -1
- package/lib/messaging/client-call-metrics.d.ts +2 -18
- package/lib/messaging/client-call-metrics.d.ts.map +1 -1
- package/lib/messaging/client-call-metrics.js +21 -22
- package/lib/messaging/client-call-metrics.js.map +1 -1
- package/lib/messaging/error.d.ts +8 -1
- package/lib/messaging/error.d.ts.map +1 -1
- package/lib/messaging/error.js +17 -3
- package/lib/messaging/error.js.map +1 -1
- package/lib/messaging/handler.d.ts.map +1 -1
- package/lib/messaging/handler.js +1 -1
- package/lib/messaging/node/connection.js +8 -8
- package/lib/messaging/node/connection.js.map +1 -1
- package/lib/messaging/proxy-factory.d.ts +1 -1
- package/lib/messaging/proxy-factory.d.ts.map +1 -1
- package/lib/messaging/proxy-factory.js +7 -9
- package/lib/messaging/proxy-factory.js.map +1 -1
- package/lib/payment-protocol.d.ts.map +1 -1
- package/lib/payment-protocol.js +1 -1
- package/lib/payment-protocol.js.map +1 -1
- package/lib/permission.d.ts +9 -3
- package/lib/permission.d.ts.map +1 -1
- package/lib/permission.js +34 -25
- package/lib/permission.js.map +1 -1
- package/lib/plans.d.ts +4 -3
- package/lib/plans.d.ts.map +1 -1
- package/lib/plans.js +210 -171
- package/lib/plans.js.map +1 -1
- package/lib/protocol.d.ts +192 -59
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +292 -104
- package/lib/protocol.js.map +1 -1
- package/{src/theia-plugins.ts → lib/protocol.spec.d.ts} +2 -6
- package/lib/protocol.spec.d.ts.map +1 -0
- package/lib/protocol.spec.js +127 -0
- package/lib/protocol.spec.js.map +1 -0
- package/lib/snapshot-url.spec.js.map +1 -1
- package/lib/team-subscription-protocol.d.ts +22 -3
- package/lib/team-subscription-protocol.d.ts.map +1 -1
- package/lib/team-subscription-protocol.js +20 -5
- package/lib/team-subscription-protocol.js.map +1 -1
- package/lib/teams-projects-protocol.d.ts +29 -5
- package/lib/teams-projects-protocol.d.ts.map +1 -1
- package/lib/teams-projects-protocol.js +8 -1
- package/lib/teams-projects-protocol.js.map +1 -1
- package/lib/typings/globals.d.ts +2 -2
- package/lib/typings/globals.d.ts.map +1 -1
- package/lib/usage.d.ts +61 -0
- package/lib/usage.d.ts.map +1 -0
- package/lib/usage.js +14 -0
- package/lib/usage.js.map +1 -0
- package/lib/util/analytics.d.ts.map +1 -1
- package/lib/util/analytics.js +12 -3
- package/lib/util/analytics.js.map +1 -1
- package/lib/util/async-iterator.d.ts.map +1 -1
- package/lib/util/async-iterator.js +3 -3
- package/lib/util/async-iterator.js.map +1 -1
- package/lib/util/cancelable.js.map +1 -1
- package/lib/util/date-time.js +6 -6
- package/lib/util/date-time.js.map +1 -1
- package/lib/util/debug-app.d.ts +25 -0
- package/lib/util/debug-app.d.ts.map +1 -0
- package/lib/util/debug-app.js +100 -0
- package/lib/util/debug-app.js.map +1 -0
- package/lib/util/deferred.js.map +1 -1
- package/lib/util/disposable.d.ts.map +1 -1
- package/lib/util/disposable.js +2 -2
- package/lib/util/disposable.js.map +1 -1
- package/lib/util/event.d.ts.map +1 -1
- package/lib/util/event.js +5 -3
- package/lib/util/event.js.map +1 -1
- package/lib/util/garbage-collected-cache.d.ts.map +1 -1
- package/lib/util/garbage-collected-cache.js +6 -1
- package/lib/util/garbage-collected-cache.js.map +1 -1
- package/lib/util/generate-workspace-id.d.ts +5 -0
- package/lib/util/generate-workspace-id.d.ts.map +1 -1
- package/lib/util/generate-workspace-id.js +446 -442
- package/lib/util/generate-workspace-id.js.map +1 -1
- package/lib/util/generate-workspace-id.spec.js +18 -7
- package/lib/util/generate-workspace-id.spec.js.map +1 -1
- package/lib/util/gitpod-cookie.d.ts +1 -1
- package/lib/util/gitpod-cookie.d.ts.map +1 -1
- package/lib/util/gitpod-cookie.js +0 -3
- package/lib/util/gitpod-cookie.js.map +1 -1
- package/lib/util/gitpod-host-url.d.ts +3 -0
- package/lib/util/gitpod-host-url.d.ts.map +1 -1
- package/lib/util/gitpod-host-url.js +49 -29
- package/lib/util/gitpod-host-url.js.map +1 -1
- package/lib/util/gitpod-host-url.spec.d.ts.map +1 -1
- package/lib/util/gitpod-host-url.spec.js +15 -5
- package/lib/util/gitpod-host-url.spec.js.map +1 -1
- package/lib/util/grpc.d.ts +19 -0
- package/lib/util/grpc.d.ts.map +1 -1
- package/lib/util/grpc.js +73 -1
- package/lib/util/grpc.js.map +1 -1
- package/lib/util/jaeger-client-types.d.ts.map +1 -1
- package/lib/util/logging.d.ts +1 -1
- package/lib/util/logging.d.ts.map +1 -1
- package/lib/util/logging.js +31 -25
- package/lib/util/logging.js.map +1 -1
- package/lib/util/logging.spec.d.ts +7 -0
- package/lib/util/logging.spec.d.ts.map +1 -0
- package/lib/util/logging.spec.js +52 -0
- package/lib/util/logging.spec.js.map +1 -0
- package/lib/util/make-link.js +5 -5
- package/lib/util/make-link.js.map +1 -1
- package/lib/util/nice-grpc.d.ts +9 -0
- package/lib/util/nice-grpc.d.ts.map +1 -0
- package/lib/util/nice-grpc.js +119 -0
- package/lib/util/nice-grpc.js.map +1 -0
- package/lib/util/parse-workspace-id.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.js +1 -2
- package/lib/util/parse-workspace-id.js.map +1 -1
- package/lib/util/parse-workspace-id.spec.d.ts.map +1 -1
- package/lib/util/parse-workspace-id.spec.js.map +1 -1
- package/lib/util/queue.spec.js +9 -6
- package/lib/util/queue.spec.js.map +1 -1
- package/lib/util/semaphore.d.ts.map +1 -1
- package/lib/util/semaphore.js.map +1 -1
- package/lib/util/skip-if.d.ts.map +1 -1
- package/lib/util/skip-if.js.map +1 -1
- package/lib/util/timeutil.d.ts +2 -0
- package/lib/util/timeutil.d.ts.map +1 -1
- package/lib/util/timeutil.js +15 -3
- package/lib/util/timeutil.js.map +1 -1
- package/lib/util/timeutil.spec.d.ts +2 -0
- package/lib/util/timeutil.spec.d.ts.map +1 -1
- package/lib/util/timeutil.spec.js +34 -0
- package/lib/util/timeutil.spec.js.map +1 -1
- package/lib/util/tracing.d.ts +8 -8
- package/lib/util/tracing.d.ts.map +1 -1
- package/lib/util/tracing.js +19 -20
- package/lib/util/tracing.js.map +1 -1
- package/lib/util/tracing.spec.js +3 -3
- package/lib/util/tracing.spec.js.map +1 -1
- package/lib/util/workspace-port-authentication.d.ts +7 -7
- package/lib/util/workspace-port-authentication.d.ts.map +1 -1
- package/lib/util/workspace-port-authentication.js +8 -11
- package/lib/util/workspace-port-authentication.js.map +1 -1
- package/lib/webhook-event.d.ts +44 -0
- package/lib/webhook-event.d.ts.map +1 -0
- package/lib/{theia-plugins.js → webhook-event.js} +2 -2
- package/lib/webhook-event.js.map +1 -0
- package/lib/workspace-class.d.ts +14 -0
- package/lib/workspace-class.d.ts.map +1 -0
- package/lib/workspace-class.js +8 -0
- package/lib/workspace-class.js.map +1 -0
- package/lib/workspace-cluster.d.ts +18 -17
- package/lib/workspace-cluster.d.ts.map +1 -1
- package/lib/workspace-cluster.js +16 -1
- package/lib/workspace-cluster.js.map +1 -1
- package/lib/workspace-instance.d.ts +39 -3
- package/lib/workspace-instance.d.ts.map +1 -1
- package/lib/wsready.d.ts +1 -1
- package/lib/wsready.d.ts.map +1 -1
- package/lib/wsready.js +2 -2
- package/package.json +15 -7
- package/pkg-yarn.lock +11 -6
- package/provenance-bundle.jsonl +3 -1
- package/src/accounting-protocol.ts +66 -51
- package/src/admin-protocol.ts +45 -18
- package/src/analytics.ts +26 -28
- package/src/attribution.ts +63 -0
- package/src/auth.ts +2 -2
- package/src/billing-mode.ts +84 -0
- package/src/blocked-repositories-protocol.ts +13 -0
- package/src/context-url.spec.ts +37 -9
- package/src/context-url.ts +94 -36
- package/src/encryption/container-module.ts +2 -3
- package/src/encryption/encryption-engine.spec.ts +9 -8
- package/src/encryption/encryption-engine.ts +20 -16
- package/src/encryption/encryption-service.ts +4 -5
- package/src/encryption/key-provider.ts +16 -19
- package/src/env.ts +0 -22
- package/src/experiments/always-default.ts +24 -0
- package/src/experiments/configcat-server.ts +41 -0
- package/src/experiments/configcat.ts +56 -0
- package/src/experiments/types.ts +34 -0
- package/src/gitpod-file-parser.spec.ts +55 -61
- package/src/gitpod-file-parser.ts +16 -17
- package/src/gitpod-service.ts +228 -129
- package/src/headless-workspace-log.ts +6 -4
- package/src/ide-frontend-service.ts +2 -2
- package/src/ide-protocol.ts +43 -6
- package/src/index.ts +16 -15
- package/src/installation-admin-protocol.ts +45 -0
- package/src/license-protocol.ts +12 -6
- package/src/messaging/browser/connection.ts +45 -47
- package/src/messaging/browser/window-connection.ts +39 -29
- package/src/messaging/client-call-metrics.ts +62 -82
- package/src/messaging/error.ts +26 -7
- package/src/messaging/handler.ts +6 -6
- package/src/messaging/node/connection.ts +8 -8
- package/src/messaging/proxy-factory.ts +23 -30
- package/src/oss-allowlist.ts +3 -3
- package/src/payment-protocol.ts +2 -2
- package/src/permission.ts +40 -32
- package/src/plans.ts +240 -189
- package/src/protocol.spec.ts +97 -0
- package/src/protocol.ts +556 -258
- package/src/snapshot-url.spec.ts +9 -7
- package/src/team-subscription-protocol.ts +59 -22
- package/src/teams-projects-protocol.ts +43 -12
- package/src/typings/globals.ts +4 -4
- package/src/usage.ts +71 -0
- package/src/util/analytics.ts +46 -24
- package/src/util/async-iterator.ts +4 -5
- package/src/util/cancelable.ts +3 -3
- package/src/util/date-time.ts +8 -8
- package/src/util/debug-app.ts +81 -0
- package/src/util/deferred.ts +6 -6
- package/src/util/disposable.ts +3 -6
- package/src/util/event.ts +9 -11
- package/src/util/garbage-collected-cache.ts +8 -6
- package/src/util/generate-workspace-id.spec.ts +26 -16
- package/src/util/generate-workspace-id.ts +460 -454
- package/src/util/gitpod-cookie.ts +8 -9
- package/src/util/gitpod-host-url.spec.ts +40 -13
- package/src/util/gitpod-host-url.ts +57 -33
- package/src/util/grpc.ts +90 -1
- package/src/util/jaeger-client-types.ts +2 -2
- package/src/util/logging.spec.ts +23 -0
- package/src/util/logging.ts +60 -42
- package/src/util/make-link.ts +6 -7
- package/src/util/nice-grpc.ts +93 -0
- package/src/util/parse-workspace-id.spec.ts +17 -8
- package/src/util/parse-workspace-id.ts +5 -6
- package/src/util/queue.spec.ts +27 -25
- package/src/util/repeat.ts +1 -1
- package/src/util/semaphore.ts +4 -6
- package/src/util/skip-if.ts +9 -6
- package/src/util/timeutil.spec.ts +40 -14
- package/src/util/timeutil.ts +27 -11
- package/src/util/tracing.spec.ts +28 -23
- package/src/util/tracing.ts +58 -54
- package/src/util/workspace-port-authentication.ts +10 -13
- package/src/webhook-event.ts +55 -0
- package/src/workspace-class.ts +14 -0
- package/src/workspace-cluster.ts +34 -20
- package/src/workspace-instance.ts +76 -20
- package/src/wsready.ts +3 -3
- package/data/builtin-theia-plugins.json +0 -372
- package/lib/email-protocol.d.ts +0 -49
- package/lib/email-protocol.d.ts.map +0 -1
- package/lib/email-protocol.js +0 -28
- package/lib/email-protocol.js.map +0 -1
- package/lib/messaging/connection-error-handler.d.ts +0 -27
- package/lib/messaging/connection-error-handler.d.ts.map +0 -1
- package/lib/messaging/connection-error-handler.js +0 -34
- package/lib/messaging/connection-error-handler.js.map +0 -1
- package/lib/theia-plugins.d.ts +0 -11
- package/lib/theia-plugins.d.ts.map +0 -1
- package/lib/theia-plugins.js.map +0 -1
- package/lib/util/safe-promise.d.ts +0 -11
- package/lib/util/safe-promise.d.ts.map +0 -1
- package/lib/util/safe-promise.js +0 -31
- package/lib/util/safe-promise.js.map +0 -1
- package/src/email-protocol.ts +0 -66
- package/src/messaging/connection-error-handler.ts +0 -62
- package/src/util/safe-promise.ts +0 -26
package/src/context-url.spec.ts
CHANGED
|
@@ -4,36 +4,64 @@
|
|
|
4
4
|
* See License-AGPL.txt in the project root for license information.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as chai from
|
|
8
|
-
import { suite, test } from
|
|
9
|
-
import {
|
|
7
|
+
import * as chai from "chai";
|
|
8
|
+
import { suite, test } from "mocha-typescript";
|
|
9
|
+
import { Workspace } from ".";
|
|
10
|
+
import { ContextURL } from "./context-url";
|
|
10
11
|
const expect = chai.expect;
|
|
11
12
|
|
|
13
|
+
type WsContextUrl = Pick<Workspace, "context" | "contextURL">;
|
|
14
|
+
|
|
12
15
|
@suite
|
|
13
16
|
export class ContextUrlTest {
|
|
14
|
-
|
|
15
17
|
@test public parseContextUrl_withEnvVar() {
|
|
16
|
-
const actual = ContextURL.
|
|
18
|
+
const actual = ContextURL.getNormalizedURL({
|
|
19
|
+
contextURL: "passedin=test%20value/https://github.com/gitpod-io/gitpod-test-repo",
|
|
20
|
+
context: {},
|
|
21
|
+
} as WsContextUrl);
|
|
17
22
|
expect(actual?.host).to.equal("github.com");
|
|
18
23
|
expect(actual?.pathname).to.equal("/gitpod-io/gitpod-test-repo");
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
@test public parseContextUrl_withEnvVar_withoutSchema() {
|
|
22
|
-
const actual = ContextURL.
|
|
27
|
+
const actual = ContextURL.getNormalizedURL({
|
|
28
|
+
contextURL: "passedin=test%20value/github.com/gitpod-io/gitpod-test-repo",
|
|
29
|
+
context: {},
|
|
30
|
+
} as WsContextUrl);
|
|
23
31
|
expect(actual?.host).to.equal("github.com");
|
|
24
32
|
expect(actual?.pathname).to.equal("/gitpod-io/gitpod-test-repo");
|
|
25
33
|
}
|
|
26
34
|
|
|
35
|
+
@test public parseContextUrl_withEnvVar_sshUrl() {
|
|
36
|
+
const actual = ContextURL.getNormalizedURL({
|
|
37
|
+
contextURL: "passedin=test%20value/git@github.com:gitpod-io/gitpod-test-repo.git",
|
|
38
|
+
context: {},
|
|
39
|
+
} as WsContextUrl);
|
|
40
|
+
expect(actual?.host).to.equal("github.com");
|
|
41
|
+
expect(actual?.pathname).to.equal("/gitpod-io/gitpod-test-repo.git");
|
|
42
|
+
}
|
|
43
|
+
|
|
27
44
|
@test public parseContextUrl_withPrebuild() {
|
|
28
|
-
const actual = ContextURL.
|
|
45
|
+
const actual = ContextURL.getNormalizedURL({
|
|
46
|
+
contextURL: "prebuild/https://github.com/gitpod-io/gitpod-test-repo",
|
|
47
|
+
context: {},
|
|
48
|
+
} as WsContextUrl);
|
|
29
49
|
expect(actual?.host).to.equal("github.com");
|
|
30
50
|
expect(actual?.pathname).to.equal("/gitpod-io/gitpod-test-repo");
|
|
31
51
|
}
|
|
32
52
|
|
|
33
53
|
@test public parseContextUrl_withPrebuild_withoutSchema() {
|
|
34
|
-
const actual = ContextURL.
|
|
54
|
+
const actual = ContextURL.getNormalizedURL({
|
|
55
|
+
contextURL: "prebuild/github.com/gitpod-io/gitpod-test-repo",
|
|
56
|
+
context: {},
|
|
57
|
+
} as WsContextUrl);
|
|
35
58
|
expect(actual?.host).to.equal("github.com");
|
|
36
59
|
expect(actual?.pathname).to.equal("/gitpod-io/gitpod-test-repo");
|
|
37
60
|
}
|
|
61
|
+
|
|
62
|
+
@test public parseContextUrl_badUrl() {
|
|
63
|
+
const actual = ContextURL.getNormalizedURL({ contextURL: "[Object object]", context: {} } as WsContextUrl);
|
|
64
|
+
expect(actual).to.be.undefined;
|
|
65
|
+
}
|
|
38
66
|
}
|
|
39
|
-
module.exports = new ContextUrlTest()
|
|
67
|
+
module.exports = new ContextUrlTest();
|
package/src/context-url.ts
CHANGED
|
@@ -4,48 +4,106 @@
|
|
|
4
4
|
* See License-AGPL.txt in the project root for license information.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { Workspace } from ".";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The whole point of these methods is to overcome inconsistencies in our data model.
|
|
11
|
+
* Ideally we remove it at some point once we fixed our model, as it:
|
|
12
|
+
* - duplicates logic
|
|
13
|
+
* - but additional burden on clients (using this, copying this to other languages!)
|
|
14
|
+
*
|
|
15
|
+
* TODO(gpl) See if we can get this into `server` code to remove the burden from clients
|
|
16
|
+
*/
|
|
7
17
|
export namespace ContextURL {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export const INCREMENTAL_PREBUILD_PREFIX = "incremental-prebuild";
|
|
19
|
+
export const PREBUILD_PREFIX = "prebuild";
|
|
20
|
+
export const IMAGEBUILD_PREFIX = "imagebuild";
|
|
21
|
+
export const SNAPSHOT_PREFIX = "snapshot";
|
|
22
|
+
export const REFERRER_PREFIX = "referrer:";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This function will (try to) return the HTTP(S) URL of the context the user originally created this workspace on.
|
|
26
|
+
* Especially it will not contain any modifiers or be of different scheme than HTTP(S).
|
|
27
|
+
*
|
|
28
|
+
* Use this function if you need to provided a _working_ URL to the original context.
|
|
29
|
+
* @param ws
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
export function getNormalizedURL(ws: Pick<Workspace, "context" | "contextURL"> | undefined): URL | undefined {
|
|
33
|
+
const normalized = normalize(ws);
|
|
34
|
+
if (!normalized) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
return new URL(normalized);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.debug(`unable to parse URL from normalized contextURL: '${normalized}'`);
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
21
44
|
}
|
|
22
45
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
46
|
+
function normalize(ws: Pick<Workspace, "context" | "contextURL"> | undefined): string | undefined {
|
|
47
|
+
if (!ws) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (ws.context.normalizedContextURL) {
|
|
51
|
+
return ws.context.normalizedContextURL;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// fallback: we do not yet set normalizedContextURL on all workspaces, yet, let alone older existing workspaces
|
|
55
|
+
let fallback: string | undefined = undefined;
|
|
56
|
+
try {
|
|
57
|
+
fallback = removePrefixes(ws.contextURL);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.error(`unable to remove prefixes from contextURL: '${ws.contextURL}'`, err);
|
|
60
|
+
}
|
|
61
|
+
return fallback;
|
|
26
62
|
}
|
|
27
63
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
64
|
+
/**
|
|
65
|
+
* The field "contextUrl" might contain prefixes like:
|
|
66
|
+
* - envvar1=value1/...
|
|
67
|
+
* - prebuild/...
|
|
68
|
+
* This is the analogon to the (Prefix)ContextParser structure in "server".
|
|
69
|
+
*/
|
|
70
|
+
function removePrefixes(contextUrl: string | undefined): string | undefined {
|
|
71
|
+
if (contextUrl === undefined) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
35
74
|
|
|
75
|
+
const segments = contextUrl.split("/");
|
|
76
|
+
if (segments.length === 1) {
|
|
77
|
+
return segments[0]; // this might be something, we just try
|
|
78
|
+
}
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
80
|
+
const segmentsToURL = (offset: number): string => {
|
|
81
|
+
let rest = segments.slice(offset).join("/");
|
|
82
|
+
if (/^git@[^:\/]+:/.test(rest)) {
|
|
83
|
+
rest = rest.replace(/^git@([^:\/]+):/, "https://$1/");
|
|
84
|
+
}
|
|
85
|
+
if (!rest.startsWith("http")) {
|
|
86
|
+
rest = "https://" + rest;
|
|
87
|
+
}
|
|
88
|
+
return rest;
|
|
89
|
+
};
|
|
43
90
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
91
|
+
const firstSegment = segments[0];
|
|
92
|
+
if (
|
|
93
|
+
firstSegment === PREBUILD_PREFIX ||
|
|
94
|
+
firstSegment === INCREMENTAL_PREBUILD_PREFIX ||
|
|
95
|
+
firstSegment === IMAGEBUILD_PREFIX ||
|
|
96
|
+
firstSegment === SNAPSHOT_PREFIX ||
|
|
97
|
+
firstSegment.startsWith(REFERRER_PREFIX)
|
|
98
|
+
) {
|
|
99
|
+
return segmentsToURL(1);
|
|
100
|
+
}
|
|
48
101
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
102
|
+
// check for env vars
|
|
103
|
+
if (firstSegment.indexOf("=") !== -1) {
|
|
104
|
+
return segmentsToURL(1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return segmentsToURL(0);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -19,10 +19,9 @@ import { EncryptionService, EncryptionServiceImpl } from "./encryption-service";
|
|
|
19
19
|
* };
|
|
20
20
|
* }).inSingletonScope();
|
|
21
21
|
*/
|
|
22
|
-
export const encryptionModule: interfaces.ContainerModuleCallBack = bind => {
|
|
23
|
-
|
|
22
|
+
export const encryptionModule: interfaces.ContainerModuleCallBack = (bind) => {
|
|
24
23
|
bind(KeyProvider).to(KeyProviderImpl).inSingletonScope();
|
|
25
24
|
|
|
26
25
|
bind(EncryptionEngine).to(EncryptionEngineImpl).inSingletonScope();
|
|
27
26
|
bind(EncryptionService).to(EncryptionServiceImpl).inSingletonScope();
|
|
28
|
-
};
|
|
27
|
+
};
|
|
@@ -5,25 +5,26 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { suite, test } from "mocha-typescript";
|
|
8
|
-
import * as chai from
|
|
9
|
-
import * as path from
|
|
8
|
+
import * as chai from "chai";
|
|
9
|
+
import * as path from "path";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
|
|
12
12
|
import { EncryptionEngineImpl } from "./encryption-engine";
|
|
13
13
|
|
|
14
14
|
const expect = chai.expect;
|
|
15
15
|
|
|
16
|
-
@suite
|
|
16
|
+
@suite
|
|
17
|
+
class TestEncryptionEngineImpl {
|
|
17
18
|
// Created with openssl rand -rand /dev/urandom -out key -base64 32
|
|
18
|
-
protected get testkey
|
|
19
|
-
const keyFilePath = path.resolve(__dirname,
|
|
19
|
+
protected get testkey() {
|
|
20
|
+
const keyFilePath = path.resolve(__dirname, "../../test/fixtures/encryption/testkey");
|
|
20
21
|
const keyBuffer = fs.readFileSync(keyFilePath);
|
|
21
22
|
return keyBuffer.toString().trim();
|
|
22
|
-
}
|
|
23
|
+
}
|
|
23
24
|
|
|
24
25
|
@test basicSymmetry() {
|
|
25
26
|
const plaintext = "12345678901234567890";
|
|
26
|
-
const key =
|
|
27
|
+
const key = Buffer.from(this.testkey, "base64");
|
|
27
28
|
|
|
28
29
|
const cut = new EncryptionEngineImpl();
|
|
29
30
|
const encryptedData = cut.encrypt(plaintext, key);
|
|
@@ -33,4 +34,4 @@ const expect = chai.expect;
|
|
|
33
34
|
expect(decryptedPlaintext).equals(plaintext);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
|
-
export const t = new TestEncryptionEngineImpl();
|
|
37
|
+
export const t = new TestEncryptionEngineImpl();
|
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
* See License-AGPL.txt in the project root for license information.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as crypto from
|
|
8
|
-
import { injectable } from
|
|
7
|
+
import * as crypto from "crypto";
|
|
8
|
+
import { injectable } from "inversify";
|
|
9
9
|
|
|
10
10
|
export interface KeyParams {
|
|
11
|
-
iv: string
|
|
11
|
+
iv: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface EncryptedData {
|
|
15
15
|
/** utf8 encoded string */
|
|
16
|
-
data: string
|
|
17
|
-
keyParams: KeyParams
|
|
16
|
+
data: string;
|
|
17
|
+
keyParams: KeyParams;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export const EncryptionEngine = Symbol(
|
|
20
|
+
export const EncryptionEngine = Symbol("EncryptionEngine");
|
|
21
21
|
export interface EncryptionEngine {
|
|
22
22
|
/**
|
|
23
23
|
* @param data utf8 encoded string
|
|
@@ -32,28 +32,32 @@ export interface EncryptionEngine {
|
|
|
32
32
|
* - no salt, as we pass in a real key (no salting needed to turn a password into a key)
|
|
33
33
|
* The implementation closely follows the exampes in https://nodejs.org/api/crypto.html.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
@injectable()
|
|
36
36
|
export class EncryptionEngineImpl {
|
|
37
|
-
readonly algorithm =
|
|
38
|
-
readonly enc =
|
|
37
|
+
readonly algorithm = "aes-256-cbc";
|
|
38
|
+
readonly enc = "base64";
|
|
39
39
|
|
|
40
40
|
encrypt(data: string, key: Buffer): EncryptedData {
|
|
41
41
|
const iv = crypto.randomBytes(16);
|
|
42
42
|
const cipher = crypto.createCipheriv(this.algorithm, key, iv);
|
|
43
|
-
const encrypted = cipher.update(
|
|
43
|
+
const encrypted = cipher.update(Buffer.from(data, "utf8"));
|
|
44
44
|
const finalEncrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
45
45
|
return {
|
|
46
46
|
data: finalEncrypted.toString(this.enc),
|
|
47
47
|
keyParams: {
|
|
48
|
-
iv: iv.toString(this.enc)
|
|
49
|
-
}
|
|
48
|
+
iv: iv.toString(this.enc),
|
|
49
|
+
},
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
decrypt(encryptedData: EncryptedData, key: Buffer): string {
|
|
54
|
-
const decipher = crypto.createDecipheriv(
|
|
55
|
-
|
|
54
|
+
const decipher = crypto.createDecipheriv(
|
|
55
|
+
this.algorithm,
|
|
56
|
+
key,
|
|
57
|
+
Buffer.from(encryptedData.keyParams.iv, this.enc),
|
|
58
|
+
);
|
|
59
|
+
let decrypted = decipher.update(Buffer.from(encryptedData.data, this.enc));
|
|
56
60
|
const finalDecrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
57
|
-
return finalDecrypted.toString(
|
|
61
|
+
return finalDecrypted.toString("utf8");
|
|
58
62
|
}
|
|
59
|
-
}
|
|
63
|
+
}
|
|
@@ -9,12 +9,11 @@ import { injectable, inject } from "inversify";
|
|
|
9
9
|
import { EncryptedData, EncryptionEngine } from "./encryption-engine";
|
|
10
10
|
import { KeyProvider, KeyMetadata } from "./key-provider";
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
export interface Encrypted<_T> extends EncryptedData {
|
|
14
|
-
keyMetadata: KeyMetadata
|
|
13
|
+
keyMetadata: KeyMetadata;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
export const EncryptionService = Symbol(
|
|
16
|
+
export const EncryptionService = Symbol("EncryptionService");
|
|
18
17
|
export interface EncryptionService {
|
|
19
18
|
encrypt<T>(data: T): Encrypted<T>;
|
|
20
19
|
decrypt<T>(encrypted: Encrypted<T>): T;
|
|
@@ -32,7 +31,7 @@ export class EncryptionServiceImpl implements EncryptionService {
|
|
|
32
31
|
const encryptedData = this.engine.encrypt(dataStr, key.material);
|
|
33
32
|
return {
|
|
34
33
|
...encryptedData,
|
|
35
|
-
keyMetadata: key.metadata
|
|
34
|
+
keyMetadata: key.metadata,
|
|
36
35
|
};
|
|
37
36
|
}
|
|
38
37
|
|
|
@@ -49,4 +48,4 @@ export class EncryptionServiceImpl implements EncryptionService {
|
|
|
49
48
|
protected deserialize<T>(data: string): T {
|
|
50
49
|
return JSON.parse(data) as T;
|
|
51
50
|
}
|
|
52
|
-
}
|
|
51
|
+
}
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
import { injectable, inject } from "inversify";
|
|
8
8
|
|
|
9
9
|
export interface KeyMetadata {
|
|
10
|
-
name: string
|
|
11
|
-
version: number
|
|
10
|
+
name: string;
|
|
11
|
+
version: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface Key {
|
|
15
|
-
metadata: KeyMetadata
|
|
16
|
-
material: Buffer
|
|
15
|
+
metadata: KeyMetadata;
|
|
16
|
+
material: Buffer;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const KeyProvider = Symbol(
|
|
19
|
+
export const KeyProvider = Symbol("KeyProvider");
|
|
20
20
|
export interface KeyProvider {
|
|
21
21
|
getPrimaryKey(): Key;
|
|
22
22
|
getKeyFor(metadata: KeyMetadata): Key;
|
|
@@ -24,24 +24,21 @@ export interface KeyProvider {
|
|
|
24
24
|
|
|
25
25
|
export type KeyConfig = KeyMetadata & {
|
|
26
26
|
/** base64 encoded */
|
|
27
|
-
material: string
|
|
28
|
-
primary?: boolean
|
|
29
|
-
}
|
|
27
|
+
material: string;
|
|
28
|
+
primary?: boolean;
|
|
29
|
+
};
|
|
30
30
|
|
|
31
|
-
export const KeyProviderConfig = Symbol(
|
|
31
|
+
export const KeyProviderConfig = Symbol("KeyProviderConfig");
|
|
32
32
|
export interface KeyProviderConfig {
|
|
33
|
-
keys: KeyConfig[]
|
|
33
|
+
keys: KeyConfig[];
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
@injectable()
|
|
37
37
|
export class KeyProviderImpl implements KeyProvider {
|
|
38
|
-
|
|
39
38
|
static loadKeyConfigFromJsonString(configStr: string): KeyConfig[] {
|
|
40
39
|
const keys = (JSON.parse(configStr) || []) as KeyConfig[];
|
|
41
|
-
if (!Array.isArray(keys)
|
|
42
|
-
|
|
43
|
-
|| 1 !== keys.reduce((p, k) => k.primary ? p + 1 : p, 0)) {
|
|
44
|
-
throw new Error('Invalid key config!');
|
|
40
|
+
if (!Array.isArray(keys) || keys.length < 0 || 1 !== keys.reduce((p, k) => (k.primary ? p + 1 : p), 0)) {
|
|
41
|
+
throw new Error("Invalid key config!");
|
|
45
42
|
}
|
|
46
43
|
return keys;
|
|
47
44
|
}
|
|
@@ -49,13 +46,13 @@ export class KeyProviderImpl implements KeyProvider {
|
|
|
49
46
|
constructor(@inject(KeyProviderConfig) protected readonly config: KeyProviderConfig) {}
|
|
50
47
|
|
|
51
48
|
protected get keys() {
|
|
52
|
-
return this.config.keys
|
|
49
|
+
return this.config.keys;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
getPrimaryKey(): Key {
|
|
56
53
|
const primaryKey = this.keys.find((key) => !!key.primary);
|
|
57
54
|
if (!primaryKey) {
|
|
58
|
-
throw new Error(
|
|
55
|
+
throw new Error("No primary encryption key found!");
|
|
59
56
|
}
|
|
60
57
|
return this.configToKey(primaryKey);
|
|
61
58
|
}
|
|
@@ -72,9 +69,9 @@ export class KeyProviderImpl implements KeyProvider {
|
|
|
72
69
|
return {
|
|
73
70
|
metadata: {
|
|
74
71
|
name: config.name,
|
|
75
|
-
version: config.version
|
|
72
|
+
version: config.version,
|
|
76
73
|
},
|
|
77
|
-
material:
|
|
74
|
+
material: Buffer.from(config.material, "base64"),
|
|
78
75
|
};
|
|
79
76
|
}
|
|
80
77
|
}
|
package/src/env.ts
CHANGED
|
@@ -6,32 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
import { injectable } from "inversify";
|
|
8
8
|
|
|
9
|
-
const legacyStagenameTranslation: { [key: string]: KubeStage } = {
|
|
10
|
-
"production": "production",
|
|
11
|
-
"staging": "prodcopy",
|
|
12
|
-
"devstaging": "dev",
|
|
13
|
-
"dev": "dev"
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function translateLegacyStagename(kubeStage: string): KubeStage {
|
|
17
|
-
const stage = legacyStagenameTranslation[kubeStage];
|
|
18
|
-
if (!stage) {
|
|
19
|
-
throw new Error(`Invalid KUBE_STAGE: ${kubeStage}`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return stage;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
9
|
@injectable()
|
|
26
10
|
export abstract class AbstractComponentEnv {
|
|
27
|
-
readonly kubeStage: KubeStage = getEnvVarParsed('KUBE_STAGE', translateLegacyStagename);
|
|
28
|
-
|
|
29
|
-
readonly installationLongname: string = getEnvVar("GITPOD_INSTALLATION_LONGNAME")
|
|
30
|
-
readonly installationShortname: string = getEnvVar("GITPOD_INSTALLATION_SHORTNAME")
|
|
31
11
|
}
|
|
32
12
|
|
|
33
|
-
export type KubeStage = 'production' | 'prodcopy' | 'staging' | 'dev';
|
|
34
|
-
|
|
35
13
|
export function getEnvVar(name: string, defaultValue?: string): string {
|
|
36
14
|
const value = process.env[name] || defaultValue;
|
|
37
15
|
if (!value) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
import { Attributes, Client } from "./types";
|
|
7
|
+
|
|
8
|
+
// AlwaysReturningDefaultValueClient is an implemention of an experiments.Client which performs no lookup/network operation
|
|
9
|
+
// and always returns the default value for a given experimentName.
|
|
10
|
+
// This client is used for non-SaaS version of Gitpod, in particular for self-hosted installations where external
|
|
11
|
+
// network connections are not desirable or even possible.
|
|
12
|
+
class AlwaysReturningDefaultValueClient implements Client {
|
|
13
|
+
getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T> {
|
|
14
|
+
return Promise.resolve(defaultValue);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
dispose(): void {
|
|
18
|
+
// there is nothing to dispose, no-op.
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function newAlwaysReturningDefaultValueClient(): Client {
|
|
23
|
+
return new AlwaysReturningDefaultValueClient();
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Client } from "./types";
|
|
8
|
+
import * as configcat from "configcat-node";
|
|
9
|
+
import { LogLevel } from "configcat-common";
|
|
10
|
+
import { ConfigCatClient } from "./configcat";
|
|
11
|
+
import { newAlwaysReturningDefaultValueClient } from "./always-default";
|
|
12
|
+
|
|
13
|
+
let client: Client | undefined;
|
|
14
|
+
|
|
15
|
+
export type ConfigCatClientFactory = () => Client;
|
|
16
|
+
export const ConfigCatClientFactory = Symbol("ConfigCatClientFactory");
|
|
17
|
+
|
|
18
|
+
export function getExperimentsClientForBackend(): Client {
|
|
19
|
+
// We have already instantiated a client, we can just re-use it.
|
|
20
|
+
if (client !== undefined) {
|
|
21
|
+
return client;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Retrieve SDK key from ENV Variable
|
|
25
|
+
const sdkKey = process.env.CONFIGCAT_SDK_KEY;
|
|
26
|
+
|
|
27
|
+
// Self-hosted installations do not set the ConfigCat SDK key, so always use a client which returns the default value.
|
|
28
|
+
if (sdkKey === undefined || sdkKey === "") {
|
|
29
|
+
client = newAlwaysReturningDefaultValueClient();
|
|
30
|
+
return client;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const configCatClient = configcat.createClient(sdkKey, {
|
|
34
|
+
pollIntervalSeconds: 3 * 60, // 3 minutes
|
|
35
|
+
logger: configcat.createConsoleLogger(LogLevel.Error),
|
|
36
|
+
maxInitWaitTimeSeconds: 0,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
client = new ConfigCatClient(configCatClient);
|
|
40
|
+
return client;
|
|
41
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Attributes, Client } from "./types";
|
|
8
|
+
import { User as ConfigCatUser } from "configcat-common/lib/RolloutEvaluator";
|
|
9
|
+
import { IConfigCatClient } from "configcat-common/lib/ConfigCatClient";
|
|
10
|
+
import { User } from "../protocol";
|
|
11
|
+
|
|
12
|
+
export const USER_ID_ATTRIBUTE = "user_id";
|
|
13
|
+
export const PROJECT_ID_ATTRIBUTE = "project_id";
|
|
14
|
+
export const TEAM_ID_ATTRIBUTE = "team_id";
|
|
15
|
+
export const TEAM_NAME_ATTRIBUTE = "team_name";
|
|
16
|
+
export const BILLING_TIER_ATTRIBUTE = "billing_tier";
|
|
17
|
+
|
|
18
|
+
export class ConfigCatClient implements Client {
|
|
19
|
+
private client: IConfigCatClient;
|
|
20
|
+
|
|
21
|
+
constructor(cc: IConfigCatClient) {
|
|
22
|
+
this.client = cc;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T> {
|
|
26
|
+
return this.client.getValueAsync(experimentName, defaultValue, attributesToUser(attributes));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
dispose(): void {
|
|
30
|
+
return this.client.dispose();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function attributesToUser(attributes: Attributes): ConfigCatUser {
|
|
35
|
+
const userId = attributes.user?.id || "";
|
|
36
|
+
const email = User.is(attributes.user) ? User.getPrimaryEmail(attributes.user) : attributes.user?.email || "";
|
|
37
|
+
|
|
38
|
+
const custom: { [key: string]: string } = {};
|
|
39
|
+
if (userId) {
|
|
40
|
+
custom[USER_ID_ATTRIBUTE] = userId;
|
|
41
|
+
}
|
|
42
|
+
if (attributes.projectId) {
|
|
43
|
+
custom[PROJECT_ID_ATTRIBUTE] = attributes.projectId;
|
|
44
|
+
}
|
|
45
|
+
if (attributes.teamId) {
|
|
46
|
+
custom[TEAM_ID_ATTRIBUTE] = attributes.teamId;
|
|
47
|
+
}
|
|
48
|
+
if (attributes.teamName) {
|
|
49
|
+
custom[TEAM_NAME_ATTRIBUTE] = attributes.teamName;
|
|
50
|
+
}
|
|
51
|
+
if (attributes.billingTier) {
|
|
52
|
+
custom[BILLING_TIER_ATTRIBUTE] = attributes.billingTier;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return new ConfigCatUser(userId, email, "", custom);
|
|
56
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
|
|
3
|
+
* Licensed under the GNU Affero General Public License (AGPL).
|
|
4
|
+
* See License-AGPL.txt in the project root for license information.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { BillingTier, User } from "../protocol";
|
|
8
|
+
|
|
9
|
+
export const Client = Symbol("Client");
|
|
10
|
+
|
|
11
|
+
// Attributes define attributes which can be used to segment audiences.
|
|
12
|
+
// Set the attributes which you want to use to group audiences into.
|
|
13
|
+
export interface Attributes {
|
|
14
|
+
// user.id is mapped to ConfigCat's "identifier" + "custom.user_id"
|
|
15
|
+
user?: User | { id: string; email?: string };
|
|
16
|
+
|
|
17
|
+
// The BillingTier of this particular user
|
|
18
|
+
billingTier?: BillingTier;
|
|
19
|
+
|
|
20
|
+
// Currently selected Gitpod Project ID (mapped to "custom.project_id")
|
|
21
|
+
projectId?: string;
|
|
22
|
+
|
|
23
|
+
// Currently selected Gitpod Team ID (mapped to "custom.team_id")
|
|
24
|
+
teamId?: string;
|
|
25
|
+
// Currently selected Gitpod Team Name (mapped to "custom.team_name")
|
|
26
|
+
teamName?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Client {
|
|
30
|
+
getValueAsync<T>(experimentName: string, defaultValue: T, attributes: Attributes): Promise<T>;
|
|
31
|
+
|
|
32
|
+
// dispose will dispose of the client, no longer retrieving flags
|
|
33
|
+
dispose(): void;
|
|
34
|
+
}
|