@camunda/ccma-api 3.0.0 → 4.0.0

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 (47) hide show
  1. package/dist/index.d.ts +12 -8
  2. package/dist/index.js +4 -0
  3. package/dist/index.js.map +2 -2
  4. package/dist/services/accounts/approvals.m2m.service.d.ts +157 -0
  5. package/dist/services/accounts/approvals.m2m.service.js +226 -0
  6. package/dist/services/accounts/approvals.m2m.service.js.map +2 -2
  7. package/dist/services/accounts/hdp.service.d.ts +16 -3
  8. package/dist/services/accounts/hdp.service.js +45 -2
  9. package/dist/services/accounts/hdp.service.js.map +2 -2
  10. package/dist/services/accounts/orgs.service.d.ts +17 -1
  11. package/dist/services/accounts/orgs.service.js +33 -0
  12. package/dist/services/accounts/orgs.service.js.map +2 -2
  13. package/dist/services/console/console.approvals.m2m.service.d.ts +12 -1
  14. package/dist/services/console/console.approvals.m2m.service.js +31 -0
  15. package/dist/services/console/console.approvals.m2m.service.js.map +2 -2
  16. package/dist/services/control/control.approvals.service.d.ts +276 -0
  17. package/dist/services/control/control.approvals.service.js +155 -0
  18. package/dist/services/control/control.approvals.service.js.map +2 -2
  19. package/dist/services/control/control.dashboards.service.d.ts +76 -0
  20. package/dist/services/control/control.dashboards.service.js +180 -0
  21. package/dist/services/control/control.dashboards.service.js.map +7 -0
  22. package/dist/services/control/control.dashboards.service.spec.d.ts +1 -0
  23. package/dist/services/control/control.feature-flags.service.d.ts +53 -0
  24. package/dist/services/control/control.feature-flags.service.js +123 -0
  25. package/dist/services/control/control.feature-flags.service.js.map +7 -0
  26. package/dist/services/control/control.feature-flags.service.spec.d.ts +1 -0
  27. package/dist/services/control/control.platform.service.d.ts +14 -0
  28. package/dist/services/control/control.platform.service.js +27 -0
  29. package/dist/services/control/control.platform.service.js.map +2 -2
  30. package/dist/services/control/control.platform.service.spec.d.ts +1 -0
  31. package/dist/services/external/external.accounts.service.d.ts +2 -2
  32. package/dist/services/external/external.accounts.service.js.map +2 -2
  33. package/dist/services/github/github.service.d.ts +20 -0
  34. package/dist/services/github/github.service.js +50 -1
  35. package/dist/services/github/github.service.js.map +2 -2
  36. package/dist/services/openrouter/openrouter.service.d.ts +35 -0
  37. package/dist/services/openrouter/openrouter.service.js +45 -0
  38. package/dist/services/openrouter/openrouter.service.js.map +2 -2
  39. package/dist/services/slack/slack-blockkit.service.d.ts +7 -0
  40. package/dist/services/slack/slack-blockkit.service.js +1 -0
  41. package/dist/services/slack/slack-blockkit.service.js.map +2 -2
  42. package/dist/utils/environments.js +3 -4
  43. package/dist/utils/environments.js.map +2 -2
  44. package/dist/utils/sse.d.ts +1 -0
  45. package/dist/utils/sse.js +7 -0
  46. package/dist/utils/sse.js.map +2 -2
  47. package/package.json +2 -2
@@ -0,0 +1,180 @@
1
+ import { request } from "../../utils/api.js";
2
+ import { HttpError } from "../../utils/errors.js";
3
+ const BASE = { id: "control" };
4
+ function contextFor(name, url, normalizedUrl, type, source) {
5
+ return {
6
+ method: {
7
+ name: `ControlDashboardsService.${name}`,
8
+ url,
9
+ normalizedUrl,
10
+ type
11
+ },
12
+ source,
13
+ target: { name: "control", type: "internal" }
14
+ };
15
+ }
16
+ function queryOf(params = {}) {
17
+ const query = new URLSearchParams();
18
+ for (const [key, value] of Object.entries(params)) {
19
+ if (value !== void 0) {
20
+ query.set(key, String(value));
21
+ }
22
+ }
23
+ return query.size > 0 ? `?${query.toString()}` : "";
24
+ }
25
+ class ControlDashboardsService {
26
+ /**
27
+ * What a dashboard definition can hold on this stage: the kinds of tiles,
28
+ * the cards, the chart metrics and the limits. The chart metrics are empty
29
+ * where `control.dashboardCharts` is off.
30
+ */
31
+ static async catalogue(params) {
32
+ return ControlDashboardsService.send(
33
+ params,
34
+ "catalogue",
35
+ "api/dashboards/catalogue",
36
+ "api/dashboards/catalogue",
37
+ "get"
38
+ );
39
+ }
40
+ /**
41
+ * Checks a chart query and gives the spec of a chart tile. A query with a
42
+ * mistake is an answer with `valid: false`, and not a failure. Answers 404
43
+ * where `control.dashboardCharts` is off.
44
+ */
45
+ static async checkChartQuery(params) {
46
+ return ControlDashboardsService.send(
47
+ params,
48
+ "checkChartQuery",
49
+ "api/dashboards/chart-queries/check",
50
+ "api/dashboards/chart-queries/check",
51
+ "post",
52
+ { query: params.params.query }
53
+ );
54
+ }
55
+ /** One page of the live or the archived dashboards, with no tiles. */
56
+ static async list(params) {
57
+ const url = `api/dashboards${queryOf(params.params)}`;
58
+ return ControlDashboardsService.send(
59
+ params,
60
+ "list",
61
+ url,
62
+ "api/dashboards",
63
+ "get"
64
+ );
65
+ }
66
+ static async get(params) {
67
+ const { dashboard } = await ControlDashboardsService.send(
68
+ params,
69
+ "get",
70
+ `api/dashboards/${params.params.id}`,
71
+ "api/dashboards/:id",
72
+ "get"
73
+ );
74
+ return dashboard;
75
+ }
76
+ static async create(params) {
77
+ const { dashboard } = await ControlDashboardsService.send(
78
+ params,
79
+ "create",
80
+ "api/dashboards",
81
+ "api/dashboards",
82
+ "post",
83
+ params.params
84
+ );
85
+ return dashboard;
86
+ }
87
+ /** Saves the title and the tiles. Answers 409 for a stale `version`. */
88
+ static async update(params) {
89
+ const { id, ...body } = params.params;
90
+ const { dashboard } = await ControlDashboardsService.send(
91
+ params,
92
+ "update",
93
+ `api/dashboards/${id}`,
94
+ "api/dashboards/:id",
95
+ "put",
96
+ body
97
+ );
98
+ return dashboard;
99
+ }
100
+ /**
101
+ * Adds a tile after the last tile: to the right of the last row when it
102
+ * fits there, else under every tile. It needs no version.
103
+ */
104
+ static async addTile(params) {
105
+ const { dashboard } = await ControlDashboardsService.send(
106
+ params,
107
+ "addTile",
108
+ `api/dashboards/${params.params.id}/tiles`,
109
+ "api/dashboards/:id/tiles",
110
+ "post",
111
+ { tile: params.params.tile }
112
+ );
113
+ return dashboard;
114
+ }
115
+ static async archive(params) {
116
+ return ControlDashboardsService.action(params, "archive");
117
+ }
118
+ static async restore(params) {
119
+ return ControlDashboardsService.action(params, "restore");
120
+ }
121
+ /** Pins the dashboard for the caller alone. */
122
+ static async pin(params) {
123
+ await ControlDashboardsService.send(
124
+ params,
125
+ "pin",
126
+ `api/dashboards/${params.params.id}/pin`,
127
+ "api/dashboards/:id/pin",
128
+ "post"
129
+ );
130
+ }
131
+ static async unpin(params) {
132
+ await ControlDashboardsService.send(
133
+ params,
134
+ "unpin",
135
+ `api/dashboards/${params.params.id}/pin`,
136
+ "api/dashboards/:id/pin",
137
+ "delete"
138
+ );
139
+ }
140
+ static async action(params, name) {
141
+ const { dashboard } = await ControlDashboardsService.send(
142
+ params,
143
+ name,
144
+ `api/dashboards/${params.params.id}/${name}`,
145
+ `api/dashboards/:id/${name}`,
146
+ "post"
147
+ );
148
+ return dashboard;
149
+ }
150
+ static async send(params, name, url, normalizedUrl, method, body) {
151
+ const serviceContext = contextFor(
152
+ name,
153
+ url,
154
+ normalizedUrl,
155
+ method,
156
+ params.config.metrics?.source || "unset"
157
+ );
158
+ const response = await request({
159
+ ...params,
160
+ config: params.config,
161
+ base: BASE,
162
+ url,
163
+ method,
164
+ metricsDetails: serviceContext,
165
+ body
166
+ });
167
+ if (!response.ok) {
168
+ throw new HttpError(
169
+ `${serviceContext.method.name}: ${response.status} ${response.statusText}`,
170
+ response.status,
171
+ response.statusText
172
+ );
173
+ }
174
+ return response.body;
175
+ }
176
+ }
177
+ export {
178
+ ControlDashboardsService
179
+ };
180
+ //# sourceMappingURL=control.dashboards.service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/services/control/control.dashboards.service.ts"],
4
+ "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n ChartQueryCheck,\n DashboardCatalogue,\n DashboardDefinition,\n DashboardDto,\n DashboardListDto,\n DashboardNewTile,\n} from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseMethodType,\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\n/**\n * The dashboards of control-backend. A tile holds the filters of a page and\n * never its data, so the client runs each tile itself.\n *\n * Every route answers 404 while the feature flag `control.dashboards` is off\n * on the stage. The chart check answers 404 while `control.dashboardCharts` is\n * off too.\n */\n\nconst BASE = { id: 'control' } as const\n\nexport interface ListDashboardsRequest extends RequestBaseParams {\n params?: { archived?: boolean; limit?: number; offset?: number }\n}\n\nexport interface DashboardIdRequest extends RequestBaseParams {\n params: { id: string }\n}\n\nexport interface CreateDashboardRequest extends RequestBaseParams {\n params: { title: string; definition?: DashboardDefinition }\n}\n\nexport interface UpdateDashboardRequest extends RequestBaseParams {\n params: {\n id: string\n title: string\n definition: DashboardDefinition\n /**\n * The `version` of the read that the edit started from. The backend\n * answers 409 when the row moved on, so a stale tab never replaces a\n * newer save.\n */\n version: number\n }\n}\n\nexport interface AddDashboardTileRequest extends RequestBaseParams {\n params: { id: string; tile: DashboardNewTile }\n}\n\nexport interface CheckChartQueryRequest extends RequestBaseParams {\n params: { query: string }\n}\n\nfunction contextFor(\n name: string,\n url: string,\n normalizedUrl: string,\n type: RequestBaseMethodType,\n source: string,\n): RequestBaseServiceContext {\n return {\n method: {\n name: `ControlDashboardsService.${name}`,\n url,\n normalizedUrl,\n type,\n },\n source,\n target: { name: 'control', type: 'internal' },\n }\n}\n\nfunction queryOf(params: Record<string, unknown> = {}): string {\n const query = new URLSearchParams()\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n query.set(key, String(value))\n }\n }\n return query.size > 0 ? `?${query.toString()}` : ''\n}\n\nexport class ControlDashboardsService {\n /**\n * What a dashboard definition can hold on this stage: the kinds of tiles,\n * the cards, the chart metrics and the limits. The chart metrics are empty\n * where `control.dashboardCharts` is off.\n */\n public static async catalogue(\n params: RequestBaseParams,\n ): Promise<DashboardCatalogue> {\n return ControlDashboardsService.send<DashboardCatalogue>(\n params,\n 'catalogue',\n 'api/dashboards/catalogue',\n 'api/dashboards/catalogue',\n 'get',\n )\n }\n\n /**\n * Checks a chart query and gives the spec of a chart tile. A query with a\n * mistake is an answer with `valid: false`, and not a failure. Answers 404\n * where `control.dashboardCharts` is off.\n */\n public static async checkChartQuery(\n params: CheckChartQueryRequest,\n ): Promise<ChartQueryCheck> {\n return ControlDashboardsService.send<ChartQueryCheck>(\n params,\n 'checkChartQuery',\n 'api/dashboards/chart-queries/check',\n 'api/dashboards/chart-queries/check',\n 'post',\n { query: params.params.query },\n )\n }\n\n /** One page of the live or the archived dashboards, with no tiles. */\n public static async list(\n params: ListDashboardsRequest,\n ): Promise<DashboardListDto> {\n const url = `api/dashboards${queryOf(params.params)}`\n return ControlDashboardsService.send<DashboardListDto>(\n params,\n 'list',\n url,\n 'api/dashboards',\n 'get',\n )\n }\n\n public static async get(params: DashboardIdRequest): Promise<DashboardDto> {\n const { dashboard } = await ControlDashboardsService.send<{\n dashboard: DashboardDto\n }>(\n params,\n 'get',\n `api/dashboards/${params.params.id}`,\n 'api/dashboards/:id',\n 'get',\n )\n return dashboard\n }\n\n public static async create(\n params: CreateDashboardRequest,\n ): Promise<DashboardDto> {\n const { dashboard } = await ControlDashboardsService.send<{\n dashboard: DashboardDto\n }>(\n params,\n 'create',\n 'api/dashboards',\n 'api/dashboards',\n 'post',\n params.params,\n )\n return dashboard\n }\n\n /** Saves the title and the tiles. Answers 409 for a stale `version`. */\n public static async update(\n params: UpdateDashboardRequest,\n ): Promise<DashboardDto> {\n const { id, ...body } = params.params\n const { dashboard } = await ControlDashboardsService.send<{\n dashboard: DashboardDto\n }>(\n params,\n 'update',\n `api/dashboards/${id}`,\n 'api/dashboards/:id',\n 'put',\n body,\n )\n return dashboard\n }\n\n /**\n * Adds a tile after the last tile: to the right of the last row when it\n * fits there, else under every tile. It needs no version.\n */\n public static async addTile(\n params: AddDashboardTileRequest,\n ): Promise<DashboardDto> {\n const { dashboard } = await ControlDashboardsService.send<{\n dashboard: DashboardDto\n }>(\n params,\n 'addTile',\n `api/dashboards/${params.params.id}/tiles`,\n 'api/dashboards/:id/tiles',\n 'post',\n { tile: params.params.tile },\n )\n return dashboard\n }\n\n public static async archive(\n params: DashboardIdRequest,\n ): Promise<DashboardDto> {\n return ControlDashboardsService.action(params, 'archive')\n }\n\n public static async restore(\n params: DashboardIdRequest,\n ): Promise<DashboardDto> {\n return ControlDashboardsService.action(params, 'restore')\n }\n\n /** Pins the dashboard for the caller alone. */\n public static async pin(params: DashboardIdRequest): Promise<void> {\n await ControlDashboardsService.send<undefined>(\n params,\n 'pin',\n `api/dashboards/${params.params.id}/pin`,\n 'api/dashboards/:id/pin',\n 'post',\n )\n }\n\n public static async unpin(params: DashboardIdRequest): Promise<void> {\n await ControlDashboardsService.send<undefined>(\n params,\n 'unpin',\n `api/dashboards/${params.params.id}/pin`,\n 'api/dashboards/:id/pin',\n 'delete',\n )\n }\n\n private static async action(\n params: DashboardIdRequest,\n name: 'archive' | 'restore',\n ): Promise<DashboardDto> {\n const { dashboard } = await ControlDashboardsService.send<{\n dashboard: DashboardDto\n }>(\n params,\n name,\n `api/dashboards/${params.params.id}/${name}`,\n `api/dashboards/:id/${name}`,\n 'post',\n )\n return dashboard\n }\n\n private static async send<TResponse>(\n params: RequestBaseParams,\n name: string,\n url: string,\n normalizedUrl: string,\n method: RequestBaseMethodType,\n body?: object,\n ): Promise<TResponse> {\n const serviceContext = contextFor(\n name,\n url,\n normalizedUrl,\n method,\n params.config.metrics?.source || 'unset',\n )\n const response = await request<TResponse>({\n ...params,\n config: params.config,\n base: BASE,\n url,\n method,\n metricsDetails: serviceContext,\n body,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n // `pin` and `unpin` answer 204 with no body, and their callers read\n // nothing.\n return response.body as TResponse\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,53 @@
1
+ import type { CreateFeatureFlagDto, FeatureFlagAnswer, FeatureFlagDto, FeatureFlagListDto, UpdateFeatureFlagDto } from '@camunda/ccma-shared-types';
2
+ import type { RequestBaseParams } from '../../types/general.types.js';
3
+ /**
4
+ * How long `evaluate` waits, unless the caller gives its own `timeout`. A
5
+ * frontend waits for the first answer before its first page, thus a
6
+ * control-backend that does not answer must not hold the loading screen.
7
+ */
8
+ export declare const EVALUATE_TIMEOUT_MS = 3000;
9
+ export interface CreateFeatureFlagRequest extends RequestBaseParams {
10
+ params: CreateFeatureFlagDto;
11
+ }
12
+ export interface UpdateFeatureFlagRequest extends RequestBaseParams {
13
+ params: {
14
+ id: string;
15
+ } & UpdateFeatureFlagDto;
16
+ }
17
+ export interface FeatureFlagIdRequest extends RequestBaseParams {
18
+ params: {
19
+ id: string;
20
+ };
21
+ }
22
+ export interface EvaluateFeatureFlagsRequest extends RequestBaseParams {
23
+ /** The org of the caller. It must be in the org claim of the token. */
24
+ params: {
25
+ orgId?: string;
26
+ };
27
+ }
28
+ export declare class ControlFeatureFlagsService {
29
+ /** Every row of the stage, by key. Needs `READ_ALL`. */
30
+ static list(params: RequestBaseParams): Promise<FeatureFlagDto[]>;
31
+ /**
32
+ * The rows, and the versions of the table and of the Redis key. The page of
33
+ * Control compares the two, and warns while the other services read the
34
+ * rows before. Needs `READ_ALL`.
35
+ */
36
+ static listWithVersions(params: RequestBaseParams): Promise<FeatureFlagListDto>;
37
+ static create(params: CreateFeatureFlagRequest): Promise<FeatureFlagDto>;
38
+ /** A field that the request does not hold stays as it is. */
39
+ static update(params: UpdateFeatureFlagRequest): Promise<FeatureFlagDto>;
40
+ static remove(params: FeatureFlagIdRequest): Promise<void>;
41
+ /**
42
+ * The flags of the caller of the token. Needs a valid token and no
43
+ * permission. The email comes from the token alone.
44
+ *
45
+ * A 429 is NOT tried again. `request` tries a 429 up to 8 times with a
46
+ * growing wait, and `config.timeout` applies to each try, thus one call could
47
+ * hang for minutes. The caller has an answer of its own: the last answer,
48
+ * or the code before the first one. For the same reason the call stops
49
+ * after `EVALUATE_TIMEOUT_MS`, unless `config.timeout` says otherwise.
50
+ */
51
+ static evaluate(params: EvaluateFeatureFlagsRequest): Promise<FeatureFlagAnswer>;
52
+ private static send;
53
+ }
@@ -0,0 +1,123 @@
1
+ import { request } from "../../utils/api.js";
2
+ import { HttpError } from "../../utils/errors.js";
3
+ const BASE = { id: "control" };
4
+ const EVALUATE_TIMEOUT_MS = 3e3;
5
+ class ControlFeatureFlagsService {
6
+ /** Every row of the stage, by key. Needs `READ_ALL`. */
7
+ static async list(params) {
8
+ const { flags } = await ControlFeatureFlagsService.listWithVersions(params);
9
+ return flags;
10
+ }
11
+ /**
12
+ * The rows, and the versions of the table and of the Redis key. The page of
13
+ * Control compares the two, and warns while the other services read the
14
+ * rows before. Needs `READ_ALL`.
15
+ */
16
+ static async listWithVersions(params) {
17
+ return ControlFeatureFlagsService.send(
18
+ params,
19
+ "list",
20
+ "api/feature-flags",
21
+ "api/feature-flags",
22
+ "get"
23
+ );
24
+ }
25
+ static async create(params) {
26
+ const { flag } = await ControlFeatureFlagsService.send(
27
+ params,
28
+ "create",
29
+ "api/feature-flags",
30
+ "api/feature-flags",
31
+ "post",
32
+ params.params
33
+ );
34
+ return flag;
35
+ }
36
+ /** A field that the request does not hold stays as it is. */
37
+ static async update(params) {
38
+ const { id, ...body } = params.params;
39
+ const { flag } = await ControlFeatureFlagsService.send(
40
+ params,
41
+ "update",
42
+ `api/feature-flags/${encodeURIComponent(id)}`,
43
+ "api/feature-flags/:id",
44
+ "patch",
45
+ body
46
+ );
47
+ return flag;
48
+ }
49
+ static async remove(params) {
50
+ await ControlFeatureFlagsService.send(
51
+ params,
52
+ "remove",
53
+ `api/feature-flags/${encodeURIComponent(params.params.id)}`,
54
+ "api/feature-flags/:id",
55
+ "delete"
56
+ );
57
+ }
58
+ /**
59
+ * The flags of the caller of the token. Needs a valid token and no
60
+ * permission. The email comes from the token alone.
61
+ *
62
+ * A 429 is NOT tried again. `request` tries a 429 up to 8 times with a
63
+ * growing wait, and `config.timeout` applies to each try, thus one call could
64
+ * hang for minutes. The caller has an answer of its own: the last answer,
65
+ * or the code before the first one. For the same reason the call stops
66
+ * after `EVALUATE_TIMEOUT_MS`, unless `config.timeout` says otherwise.
67
+ */
68
+ static async evaluate(params) {
69
+ const query = params.params.orgId ? `?orgId=${encodeURIComponent(params.params.orgId)}` : "";
70
+ return ControlFeatureFlagsService.send(
71
+ {
72
+ ...params,
73
+ config: {
74
+ ...params.config,
75
+ timeout: params.config.timeout ?? EVALUATE_TIMEOUT_MS
76
+ }
77
+ },
78
+ "evaluate",
79
+ `api/feature-flags/evaluate${query}`,
80
+ "api/feature-flags/evaluate",
81
+ "get",
82
+ void 0,
83
+ { attempts: 1, remaining: 0 }
84
+ );
85
+ }
86
+ static async send(params, name, url, normalizedUrl, method, body, retry) {
87
+ const serviceContext = {
88
+ method: {
89
+ name: `ControlFeatureFlagsService.${name}`,
90
+ url,
91
+ normalizedUrl,
92
+ type: method
93
+ },
94
+ source: params.config.metrics?.source || "unset",
95
+ target: { name: "control", type: "internal" }
96
+ };
97
+ const response = await request({
98
+ // `...params` first, so `cacheControl` and `onCachedResponse` reach the
99
+ // request. See the same note in `control.annotations.service.ts`.
100
+ ...params,
101
+ config: params.config,
102
+ base: BASE,
103
+ url,
104
+ method,
105
+ metricsDetails: serviceContext,
106
+ body,
107
+ retry
108
+ });
109
+ if (!response.ok) {
110
+ throw new HttpError(
111
+ `${serviceContext.method.name}: ${response.status} ${response.statusText}`,
112
+ response.status,
113
+ response.statusText
114
+ );
115
+ }
116
+ return response.body;
117
+ }
118
+ }
119
+ export {
120
+ ControlFeatureFlagsService,
121
+ EVALUATE_TIMEOUT_MS
122
+ };
123
+ //# sourceMappingURL=control.feature-flags.service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/services/control/control.feature-flags.service.ts"],
4
+ "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n CreateFeatureFlagDto,\n FeatureFlagAnswer,\n FeatureFlagDto,\n FeatureFlagListDto,\n UpdateFeatureFlagDto,\n} from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseMethodType,\n RequestBaseParams,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\n/**\n * The feature flag table of control-backend.\n *\n * Each stage holds its own table, thus a row is the value of the flag on that\n * stage. `evaluate` answers the flags of the caller of the token, in the\n * shape of `FeatureFlagAnswer`.\n */\n\nconst BASE = { id: 'control' } as const\n\n/**\n * How long `evaluate` waits, unless the caller gives its own `timeout`. A\n * frontend waits for the first answer before its first page, thus a\n * control-backend that does not answer must not hold the loading screen.\n */\nexport const EVALUATE_TIMEOUT_MS = 3_000\n\nexport interface CreateFeatureFlagRequest extends RequestBaseParams {\n params: CreateFeatureFlagDto\n}\n\nexport interface UpdateFeatureFlagRequest extends RequestBaseParams {\n params: { id: string } & UpdateFeatureFlagDto\n}\n\nexport interface FeatureFlagIdRequest extends RequestBaseParams {\n params: { id: string }\n}\n\nexport interface EvaluateFeatureFlagsRequest extends RequestBaseParams {\n /** The org of the caller. It must be in the org claim of the token. */\n params: { orgId?: string }\n}\n\nexport class ControlFeatureFlagsService {\n /** Every row of the stage, by key. Needs `READ_ALL`. */\n public static async list(\n params: RequestBaseParams,\n ): Promise<FeatureFlagDto[]> {\n const { flags } = await ControlFeatureFlagsService.listWithVersions(params)\n return flags\n }\n\n /**\n * The rows, and the versions of the table and of the Redis key. The page of\n * Control compares the two, and warns while the other services read the\n * rows before. Needs `READ_ALL`.\n */\n public static async listWithVersions(\n params: RequestBaseParams,\n ): Promise<FeatureFlagListDto> {\n return ControlFeatureFlagsService.send<FeatureFlagListDto>(\n params,\n 'list',\n 'api/feature-flags',\n 'api/feature-flags',\n 'get',\n )\n }\n\n public static async create(\n params: CreateFeatureFlagRequest,\n ): Promise<FeatureFlagDto> {\n const { flag } = await ControlFeatureFlagsService.send<{\n flag: FeatureFlagDto\n }>(\n params,\n 'create',\n 'api/feature-flags',\n 'api/feature-flags',\n 'post',\n params.params,\n )\n return flag\n }\n\n /** A field that the request does not hold stays as it is. */\n public static async update(\n params: UpdateFeatureFlagRequest,\n ): Promise<FeatureFlagDto> {\n const { id, ...body } = params.params\n const { flag } = await ControlFeatureFlagsService.send<{\n flag: FeatureFlagDto\n }>(\n params,\n 'update',\n `api/feature-flags/${encodeURIComponent(id)}`,\n 'api/feature-flags/:id',\n 'patch',\n body,\n )\n return flag\n }\n\n public static async remove(params: FeatureFlagIdRequest): Promise<void> {\n await ControlFeatureFlagsService.send<undefined>(\n params,\n 'remove',\n `api/feature-flags/${encodeURIComponent(params.params.id)}`,\n 'api/feature-flags/:id',\n 'delete',\n )\n }\n\n /**\n * The flags of the caller of the token. Needs a valid token and no\n * permission. The email comes from the token alone.\n *\n * A 429 is NOT tried again. `request` tries a 429 up to 8 times with a\n * growing wait, and `config.timeout` applies to each try, thus one call could\n * hang for minutes. The caller has an answer of its own: the last answer,\n * or the code before the first one. For the same reason the call stops\n * after `EVALUATE_TIMEOUT_MS`, unless `config.timeout` says otherwise.\n */\n public static async evaluate(\n params: EvaluateFeatureFlagsRequest,\n ): Promise<FeatureFlagAnswer> {\n const query = params.params.orgId\n ? `?orgId=${encodeURIComponent(params.params.orgId)}`\n : ''\n return ControlFeatureFlagsService.send<FeatureFlagAnswer>(\n {\n ...params,\n config: {\n ...params.config,\n timeout: params.config.timeout ?? EVALUATE_TIMEOUT_MS,\n },\n },\n 'evaluate',\n `api/feature-flags/evaluate${query}`,\n 'api/feature-flags/evaluate',\n 'get',\n undefined,\n { attempts: 1, remaining: 0 },\n )\n }\n\n private static async send<TResponse>(\n params: RequestBaseParams,\n name: string,\n url: string,\n normalizedUrl: string,\n method: RequestBaseMethodType,\n body?: object,\n retry?: { attempts: number; remaining: number },\n ): Promise<TResponse> {\n const serviceContext = {\n method: {\n name: `ControlFeatureFlagsService.${name}`,\n url,\n normalizedUrl,\n type: method,\n },\n source: params.config.metrics?.source || 'unset',\n target: { name: 'control', type: 'internal' as const },\n }\n const response = await request<TResponse>({\n // `...params` first, so `cacheControl` and `onCachedResponse` reach the\n // request. See the same note in `control.annotations.service.ts`.\n ...params,\n config: params.config,\n base: BASE,\n url,\n method,\n metricsDetails: serviceContext,\n body,\n retry,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n // `remove` answers 204 with no body, and its caller reads nothing.\n return response.body as TResponse\n }\n}\n"],
5
+ "mappings": "AAiBA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAU1B,MAAM,OAAO,EAAE,IAAI,UAAU;AAOtB,MAAM,sBAAsB;AAmB5B,MAAM,2BAA2B;AAAA;AAAA,EAEtC,aAAoB,KAClB,QAC2B;AAC3B,UAAM,EAAE,MAAM,IAAI,MAAM,2BAA2B,iBAAiB,MAAM;AAC1E,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAoB,iBAClB,QAC6B;AAC7B,WAAO,2BAA2B;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAoB,OAClB,QACyB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,2BAA2B;AAAA,MAGhD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAoB,OAClB,QACyB;AACzB,UAAM,EAAE,IAAI,GAAG,KAAK,IAAI,OAAO;AAC/B,UAAM,EAAE,KAAK,IAAI,MAAM,2BAA2B;AAAA,MAGhD;AAAA,MACA;AAAA,MACA,qBAAqB,mBAAmB,EAAE,CAAC;AAAA,MAC3C;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,aAAoB,OAAO,QAA6C;AACtE,UAAM,2BAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,qBAAqB,mBAAmB,OAAO,OAAO,EAAE,CAAC;AAAA,MACzD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAoB,SAClB,QAC4B;AAC5B,UAAM,QAAQ,OAAO,OAAO,QACxB,UAAU,mBAAmB,OAAO,OAAO,KAAK,CAAC,KACjD;AACJ,WAAO,2BAA2B;AAAA,MAChC;AAAA,QACE,GAAG;AAAA,QACH,QAAQ;AAAA,UACN,GAAG,OAAO;AAAA,UACV,SAAS,OAAO,OAAO,WAAW;AAAA,QACpC;AAAA,MACF;AAAA,MACA;AAAA,MACA,6BAA6B,KAAK;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,UAAU,GAAG,WAAW,EAAE;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,aAAqB,KACnB,QACA,MACA,KACA,eACA,QACA,MACA,OACoB;AACpB,UAAM,iBAAiB;AAAA,MACrB,QAAQ;AAAA,QACN,MAAM,8BAA8B,IAAI;AAAA,QACxC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ,EAAE,MAAM,WAAW,MAAM,WAAoB;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,QAAmB;AAAA;AAAA;AAAA,MAGxC,GAAG;AAAA,MACH,QAAQ,OAAO;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO,SAAS;AAAA,EAClB;AACF;",
6
+ "names": []
7
+ }
@@ -19,6 +19,20 @@ export interface ControlWhoamiDto {
19
19
  /** The raw permission claims, HiBob roles included. */
20
20
  permissions: string[];
21
21
  }
22
+ /** The build of control-backend, as `GET /info` reports it. */
23
+ export interface ControlInfoDto {
24
+ info: {
25
+ /**
26
+ * The short commit SHA that CI gives the image. Two values name no
27
+ * commit: `local` when `SHORT_SHA` is not set, and an empty string for an
28
+ * image built with no `SHORT_SHA`, as the CI check builds it.
29
+ */
30
+ shortSha: string;
31
+ /** The git ref of the build: `main` on dev, the release tag on int and prod. */
32
+ version: string;
33
+ };
34
+ }
22
35
  export declare class ControlPlatformService {
36
+ static info(params: RequestBaseParams): Promise<ControlInfoDto>;
23
37
  static whoami(params: RequestBaseParams): Promise<ControlWhoamiDto>;
24
38
  }
@@ -2,6 +2,33 @@ import { request } from "../../utils/api.js";
2
2
  import { HttpError } from "../../utils/errors.js";
3
3
  const BASE = { id: "control" };
4
4
  class ControlPlatformService {
5
+ static async info(params) {
6
+ const serviceContext = {
7
+ method: {
8
+ name: "ControlPlatformService.info",
9
+ url: "info",
10
+ normalizedUrl: "info",
11
+ type: "get"
12
+ },
13
+ source: params.config.metrics?.source || "unset",
14
+ target: { name: "control", type: "internal" }
15
+ };
16
+ const response = await request({
17
+ config: params.config,
18
+ base: BASE,
19
+ url: serviceContext.method.url,
20
+ method: "get",
21
+ metricsDetails: serviceContext
22
+ });
23
+ if (!response.ok || !response.body) {
24
+ throw new HttpError(
25
+ `${serviceContext.method.name}: ${response.status} ${response.statusText}`,
26
+ response.status,
27
+ response.statusText
28
+ );
29
+ }
30
+ return response.body;
31
+ }
5
32
  static async whoami(params) {
6
33
  const serviceContext = {
7
34
  method: {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/services/control/control.platform.service.ts"],
4
- "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type { RequestBaseParams } from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\n/**\n * The platform routes of control-backend. They carry no business rule.\n *\n * `whoami` is the one that a frontend needs: it reports the identity that\n * control-backend built from the token of the caller, with the permission\n * claims that the token carries. Every rule of the approval mechanism runs\n * against THAT actor, so a view that wants to disable a button the service\n * would refuse has to ask this route and not another service.\n */\n\nconst BASE = { id: 'control' } as const\n\n/** The actor of control-backend, as `GET /api/whoami` reports it. */\nexport interface ControlWhoamiDto {\n /** The `sub` claim of the token. */\n userId: string\n /**\n * The address of the caller, as control-backend resolves it.\n *\n * Three sources, and the service holds their order: the namespaced claim, a\n * top-level `email` claim, and the subject of the token. A token that names\n * no person \u2014 a machine token \u2014 answers `UNKNOWN_ACTOR_EMAIL` and never an\n * empty string, because `emailFromClaims` of `shared-backend-fastify` ends\n * its chain with that value. The rules of the approval policy read it as\n * \"no person\": `isSameActorEmail` holds that two unknown addresses are not\n * one human, and `hasActorEmail` answers false for it. A reader that tests\n * for an empty string instead would take a machine for a person.\n */\n email: string\n /** The raw permission claims, HiBob roles included. */\n permissions: string[]\n}\n\nexport class ControlPlatformService {\n public static async whoami(\n params: RequestBaseParams,\n ): Promise<ControlWhoamiDto> {\n const serviceContext = {\n method: {\n name: 'ControlPlatformService.whoami',\n url: 'api/whoami',\n normalizedUrl: 'api/whoami',\n type: 'get' as const,\n },\n source: params.config.metrics?.source || 'unset',\n target: { name: 'control', type: 'internal' as const },\n }\n const response = await request<ControlWhoamiDto>({\n config: params.config,\n base: BASE,\n url: serviceContext.method.url,\n method: 'get',\n metricsDetails: serviceContext,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n return response.body!\n }\n}\n"],
5
- "mappings": "AAOA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAY1B,MAAM,OAAO,EAAE,IAAI,UAAU;AAuBtB,MAAM,uBAAuB;AAAA,EAClC,aAAoB,OAClB,QAC2B;AAC3B,UAAM,iBAAiB;AAAA,MACrB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ,EAAE,MAAM,WAAW,MAAM,WAAoB;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,QAA0B;AAAA,MAC/C,QAAQ,OAAO;AAAA,MACf,MAAM;AAAA,MACN,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AACF;",
4
+ "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type { RequestBaseParams } from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\n/**\n * The platform routes of control-backend. They carry no business rule.\n *\n * `whoami` is the one that the approval views need: it reports the identity that\n * control-backend built from the token of the caller, with the permission\n * claims that the token carries. Every rule of the approval mechanism runs\n * against THAT actor, so a view that wants to disable a button the service\n * would refuse has to ask this route and not another service.\n */\n\nconst BASE = { id: 'control' } as const\n\n/** The actor of control-backend, as `GET /api/whoami` reports it. */\nexport interface ControlWhoamiDto {\n /** The `sub` claim of the token. */\n userId: string\n /**\n * The address of the caller, as control-backend resolves it.\n *\n * Three sources, and the service holds their order: the namespaced claim, a\n * top-level `email` claim, and the subject of the token. A token that names\n * no person \u2014 a machine token \u2014 answers `UNKNOWN_ACTOR_EMAIL` and never an\n * empty string, because `emailFromClaims` of `shared-backend-fastify` ends\n * its chain with that value. The rules of the approval policy read it as\n * \"no person\": `isSameActorEmail` holds that two unknown addresses are not\n * one human, and `hasActorEmail` answers false for it. A reader that tests\n * for an empty string instead would take a machine for a person.\n */\n email: string\n /** The raw permission claims, HiBob roles included. */\n permissions: string[]\n}\n\n/** The build of control-backend, as `GET /info` reports it. */\nexport interface ControlInfoDto {\n info: {\n /**\n * The short commit SHA that CI gives the image. Two values name no\n * commit: `local` when `SHORT_SHA` is not set, and an empty string for an\n * image built with no `SHORT_SHA`, as the CI check builds it.\n */\n shortSha: string\n /** The git ref of the build: `main` on dev, the release tag on int and prod. */\n version: string\n }\n}\n\nexport class ControlPlatformService {\n public static async info(params: RequestBaseParams): Promise<ControlInfoDto> {\n const serviceContext = {\n method: {\n name: 'ControlPlatformService.info',\n url: 'info',\n normalizedUrl: 'info',\n type: 'get' as const,\n },\n source: params.config.metrics?.source || 'unset',\n target: { name: 'control', type: 'internal' as const },\n }\n const response = await request<ControlInfoDto>({\n config: params.config,\n base: BASE,\n url: serviceContext.method.url,\n method: 'get',\n metricsDetails: serviceContext,\n })\n if (!response.ok || !response.body) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n return response.body\n }\n\n public static async whoami(\n params: RequestBaseParams,\n ): Promise<ControlWhoamiDto> {\n const serviceContext = {\n method: {\n name: 'ControlPlatformService.whoami',\n url: 'api/whoami',\n normalizedUrl: 'api/whoami',\n type: 'get' as const,\n },\n source: params.config.metrics?.source || 'unset',\n target: { name: 'control', type: 'internal' as const },\n }\n const response = await request<ControlWhoamiDto>({\n config: params.config,\n base: BASE,\n url: serviceContext.method.url,\n method: 'get',\n metricsDetails: serviceContext,\n })\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n return response.body!\n }\n}\n"],
5
+ "mappings": "AAOA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAY1B,MAAM,OAAO,EAAE,IAAI,UAAU;AAqCtB,MAAM,uBAAuB;AAAA,EAClC,aAAoB,KAAK,QAAoD;AAC3E,UAAM,iBAAiB;AAAA,MACrB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ,EAAE,MAAM,WAAW,MAAM,WAAoB;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,QAAwB;AAAA,MAC7C,QAAQ,OAAO;AAAA,MACf,MAAM;AAAA,MACN,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAClC,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,aAAoB,OAClB,QAC2B;AAC3B,UAAM,iBAAiB;AAAA,MACrB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ,EAAE,MAAM,WAAW,MAAM,WAAoB;AAAA,IACvD;AACA,UAAM,WAAW,MAAM,QAA0B;AAAA,MAC/C,QAAQ,OAAO;AAAA,MACf,MAAM;AAAA,MACN,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- import type { ExternalClickwrapConfigDto, ExternalOrganizationDto, Features } from '@camunda/ccma-shared-types';
1
+ import type { ExternalClickwrapConfigDto, ExternalOrganizationDto, FeatureFlagAnswer } from '@camunda/ccma-shared-types';
2
2
  import type { RequestBaseParams } from '../../types/general.types.js';
3
3
  export type UserThemePreference = 'light' | 'dark' | 'system';
4
4
  export interface UpdateUserThemeParams extends RequestBaseParams {
@@ -37,7 +37,7 @@ export declare class ExternalAccountsService {
37
37
  * stage that the client thinks it runs on. The email comes from the access
38
38
  * token alone.
39
39
  */
40
- static getFeatureFlags(params: GetFeatureFlagsParams): Promise<Features>;
40
+ static getFeatureFlags(params: GetFeatureFlagsParams): Promise<FeatureFlagAnswer>;
41
41
  /**
42
42
  * The clickwrap config for the opt-in to alpha features
43
43
  * (`GET external/clickwrap-config`). The deployed accounts-backend owns the
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/services/external/external.accounts.service.ts"],
4
- "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n ExternalClickwrapConfigDto,\n ExternalOrganizationDto,\n Features,\n} from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\nexport type UserThemePreference = 'light' | 'dark' | 'system'\n\nexport interface UpdateUserThemeParams extends RequestBaseParams {\n theme: UserThemePreference\n}\n\nexport interface GetFeatureFlagsParams extends RequestBaseParams {\n params?: {\n /**\n * The organization to evaluate the org-scoped flags for. Omit it before\n * the user selects an organization. The caller must be a member, because\n * the backend answers 403 for every other organization.\n */\n orgId?: string\n }\n}\n\n/**\n * Accounts backend **external** (CORS-enabled) endpoints used to build webapp\n * navigation. Distinct from `OrgsService`/`UsersService`, which target the\n * internal accounts API with admin-scoped DTOs. Use this from any Camunda\n * webapp (console, modeler, operate, \u2026); use the internal services from\n * console/accounts' own admin surfaces.\n */\nexport class ExternalAccountsService {\n /**\n * Organizations the current user belongs to\n * (`GET external/organizations/my`). Source for the org breadcrumb and the\n * organization switcher.\n */\n public static async getMyOrganizations(\n params: RequestBaseParams,\n ): Promise<ExternalOrganizationDto[]> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getMyOrganizations',\n url: 'external/organizations/my',\n normalizedUrl: 'external/organizations/my',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<ExternalOrganizationDto[]>({\n ...params,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body ?? []\n }\n\n /**\n * The evaluated feature flags for the current user\n * (`GET external/feature-flags`). The deployed accounts-backend decides the\n * values, thus a host does not hold a copy of the rules.\n *\n * The stage of the flags is the stage of the backend that answers, not the\n * stage that the client thinks it runs on. The email comes from the access\n * token alone.\n */\n public static async getFeatureFlags(\n params: GetFeatureFlagsParams,\n ): Promise<Features> {\n const orgId = params.params?.orgId\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getFeatureFlags',\n url: orgId\n ? `external/feature-flags?orgId=${encodeURIComponent(orgId)}`\n : 'external/feature-flags',\n normalizedUrl: 'external/feature-flags',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<Features>({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok || !response.body) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body\n }\n\n /**\n * The clickwrap config for the opt-in to alpha features\n * (`GET external/clickwrap-config`). The deployed accounts-backend owns the\n * PactSafe identifiers, thus a host does not hold a copy.\n *\n * A field is absent when the backend has no value for it. A host with no\n * `accessId` shows no opt-in.\n */\n public static async getClickwrapConfig(\n params: RequestBaseParams,\n ): Promise<ExternalClickwrapConfigDto> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getClickwrapConfig',\n url: 'external/clickwrap-config',\n normalizedUrl: 'external/clickwrap-config',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<ExternalClickwrapConfigDto>({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body ?? {}\n }\n\n /**\n * Persist the user's theme preference (`PATCH external/user/theme`). The\n * backend stores it on the user profile and reflects it in the next access\n * token's `https://camunda.com/settings.theme` claim. Response is empty.\n */\n public static async updateUserTheme(\n params: UpdateUserThemeParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.updateUserTheme',\n url: 'external/user/theme',\n normalizedUrl: 'external/user/theme',\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: { theme: params.theme },\n responseType: 'none',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/*\n * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH\n * under one or more contributor license agreements. Licensed under a commercial license.\n * You may not use this file except in compliance with the commercial license.\n */\n\nimport type {\n ExternalClickwrapConfigDto,\n ExternalOrganizationDto,\n FeatureFlagAnswer,\n} from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { HttpError } from '../../utils/errors.js'\n\nexport type UserThemePreference = 'light' | 'dark' | 'system'\n\nexport interface UpdateUserThemeParams extends RequestBaseParams {\n theme: UserThemePreference\n}\n\nexport interface GetFeatureFlagsParams extends RequestBaseParams {\n params?: {\n /**\n * The organization to evaluate the org-scoped flags for. Omit it before\n * the user selects an organization. The caller must be a member, because\n * the backend answers 403 for every other organization.\n */\n orgId?: string\n }\n}\n\n/**\n * Accounts backend **external** (CORS-enabled) endpoints used to build webapp\n * navigation. Distinct from `OrgsService`/`UsersService`, which target the\n * internal accounts API with admin-scoped DTOs. Use this from any Camunda\n * webapp (console, modeler, operate, \u2026); use the internal services from\n * console/accounts' own admin surfaces.\n */\nexport class ExternalAccountsService {\n /**\n * Organizations the current user belongs to\n * (`GET external/organizations/my`). Source for the org breadcrumb and the\n * organization switcher.\n */\n public static async getMyOrganizations(\n params: RequestBaseParams,\n ): Promise<ExternalOrganizationDto[]> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getMyOrganizations',\n url: 'external/organizations/my',\n normalizedUrl: 'external/organizations/my',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<ExternalOrganizationDto[]>({\n ...params,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body ?? []\n }\n\n /**\n * The evaluated feature flags for the current user\n * (`GET external/feature-flags`). The deployed accounts-backend decides the\n * values, thus a host does not hold a copy of the rules.\n *\n * The stage of the flags is the stage of the backend that answers, not the\n * stage that the client thinks it runs on. The email comes from the access\n * token alone.\n */\n public static async getFeatureFlags(\n params: GetFeatureFlagsParams,\n ): Promise<FeatureFlagAnswer> {\n const orgId = params.params?.orgId\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getFeatureFlags',\n url: orgId\n ? `external/feature-flags?orgId=${encodeURIComponent(orgId)}`\n : 'external/feature-flags',\n normalizedUrl: 'external/feature-flags',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<FeatureFlagAnswer>({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok || !response.body) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body\n }\n\n /**\n * The clickwrap config for the opt-in to alpha features\n * (`GET external/clickwrap-config`). The deployed accounts-backend owns the\n * PactSafe identifiers, thus a host does not hold a copy.\n *\n * A field is absent when the backend has no value for it. A host with no\n * `accessId` shows no opt-in.\n */\n public static async getClickwrapConfig(\n params: RequestBaseParams,\n ): Promise<ExternalClickwrapConfigDto> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.getClickwrapConfig',\n url: 'external/clickwrap-config',\n normalizedUrl: 'external/clickwrap-config',\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request<ExternalClickwrapConfigDto>({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n responseType: 'json',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n\n return response.body ?? {}\n }\n\n /**\n * Persist the user's theme preference (`PATCH external/user/theme`). The\n * backend stores it on the user profile and reflects it in the next access\n * token's `https://camunda.com/settings.theme` claim. Response is empty.\n */\n public static async updateUserTheme(\n params: UpdateUserThemeParams,\n ): Promise<void> {\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: 'ExternalAccountsService.updateUserTheme',\n url: 'external/user/theme',\n normalizedUrl: 'external/user/theme',\n type: 'patch',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'accounts',\n type: 'internal',\n },\n }\n\n const response = await request({\n config: params.config,\n base: { id: 'accounts' },\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n body: { theme: params.theme },\n responseType: 'none',\n })\n\n if (!response.ok) {\n throw new HttpError(\n `${serviceContext.method.name}: ${response.status} ${response.statusText}`,\n response.status,\n response.statusText,\n )\n }\n }\n}\n"],
5
+ "mappings": "AAeA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AA0BnB,MAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnC,aAAoB,mBAClB,QACoC;AACpC,UAAM,iBAA4C;AAAA,MAChD,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAmC;AAAA,MACxD,GAAG;AAAA,MACH,MAAM,EAAE,IAAI,WAAW;AAAA,MACvB,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ,eAAe,OAAO;AAAA,MAC9B,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO,SAAS,QAAQ,CAAC;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAoB,gBAClB,QAC4B;AAC5B,UAAM,QAAQ,OAAO,QAAQ;AAC7B,UAAM,iBAA4C;AAAA,MAChD,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK,QACD,gCAAgC,mBAAmB,KAAK,CAAC,KACzD;AAAA,QACJ,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAA2B;AAAA,MAChD,QAAQ,OAAO;AAAA,MACf,MAAM,EAAE,IAAI,WAAW;AAAA,MACvB,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ,eAAe,OAAO;AAAA,MAC9B,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAClC,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAoB,mBAClB,QACqC;AACrC,UAAM,iBAA4C;AAAA,MAChD,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAoC;AAAA,MACzD,QAAQ,OAAO;AAAA,MACf,MAAM,EAAE,IAAI,WAAW;AAAA,MACvB,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ,eAAe,OAAO;AAAA,MAC9B,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO,SAAS,QAAQ,CAAC;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAoB,gBAClB,QACe;AACf,UAAM,iBAA4C;AAAA,MAChD,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,eAAe;AAAA,QACf,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,OAAO,SAAS,UAAU;AAAA,MACzC,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,QAAQ,OAAO;AAAA,MACf,MAAM,EAAE,IAAI,WAAW;AAAA,MACvB,KAAK,eAAe,OAAO;AAAA,MAC3B,QAAQ,eAAe,OAAO;AAAA,MAC9B,gBAAgB;AAAA,MAChB,MAAM,EAAE,OAAO,OAAO,MAAM;AAAA,MAC5B,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,OAAO,IAAI,KAAK,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACxE,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -34,8 +34,13 @@ export interface GithubRelease {
34
34
  url: string;
35
35
  tag_name: string;
36
36
  body: string;
37
+ /** The date of the tagged commit, not of the release. */
37
38
  created_at: string;
38
39
  prerelease: boolean;
40
+ html_url?: string;
41
+ /** When the release was made. A draft has none. */
42
+ published_at?: string | undefined;
43
+ draft?: boolean;
39
44
  }
40
45
  export interface GithubListDirectoryContentRequest extends RequestBaseParams {
41
46
  options: {
@@ -64,6 +69,20 @@ export interface GithubContentItem {
64
69
  download_url: string | undefined;
65
70
  type: string;
66
71
  }
72
+ export interface GithubCompareCommitsRequest extends RequestBaseParams {
73
+ options: {
74
+ owner: string;
75
+ repo: string;
76
+ apiToken: string;
77
+ base: string;
78
+ head: string;
79
+ };
80
+ }
81
+ export interface GithubCommitComparison {
82
+ /** Commits that `head` has and `base` does not have. */
83
+ aheadBy: number;
84
+ htmlUrl: string;
85
+ }
67
86
  export declare class GithubService {
68
87
  static getNextBugfixReleaseVersion(params: GithubGetNextBugfixReleaseVersionRequest): Promise<string>;
69
88
  static listMajorMinorReleases(params: GithubListMajorMinorReleasesRequest): Promise<GithubRelease[]>;
@@ -71,4 +90,5 @@ export declare class GithubService {
71
90
  static getReleases(params: GithubListReleasesRequest): Promise<GithubRelease[]>;
72
91
  static listDirectoryContent(params: GithubListDirectoryContentRequest): Promise<GithubContentItem[]>;
73
92
  static getRawFile(params: GithubGetRawFileRequest): Promise<string>;
93
+ static compareCommits(params: GithubCompareCommitsRequest): Promise<GithubCommitComparison>;
74
94
  }