@camunda/ccma-api 3.1.0 → 5.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.
- package/dist/index.d.ts +12 -8
- package/dist/index.js +4 -0
- package/dist/index.js.map +2 -2
- package/dist/services/accounts/approvals.m2m.service.d.ts +212 -0
- package/dist/services/accounts/approvals.m2m.service.js +330 -0
- package/dist/services/accounts/approvals.m2m.service.js.map +2 -2
- package/dist/services/accounts/early-access-features.service.d.ts +4 -0
- package/dist/services/accounts/early-access-features.service.js.map +2 -2
- package/dist/services/accounts/hdp.service.d.ts +16 -3
- package/dist/services/accounts/hdp.service.js +45 -2
- package/dist/services/accounts/hdp.service.js.map +2 -2
- package/dist/services/accounts/orgs.service.d.ts +5 -0
- package/dist/services/accounts/orgs.service.js.map +2 -2
- package/dist/services/console/console.approvals.m2m.service.d.ts +95 -1
- package/dist/services/console/console.approvals.m2m.service.js +142 -0
- package/dist/services/console/console.approvals.m2m.service.js.map +2 -2
- package/dist/services/console/console.cluster-parameters.service.d.ts +6 -0
- package/dist/services/console/console.cluster-parameters.service.js.map +2 -2
- package/dist/services/console/console.cluster.service.d.ts +2 -0
- package/dist/services/console/console.cluster.service.js.map +2 -2
- package/dist/services/console/generation.service.d.ts +17 -1
- package/dist/services/console/generation.service.js +52 -1
- package/dist/services/console/generation.service.js.map +2 -2
- package/dist/services/control/control.approvals.service.d.ts +421 -0
- package/dist/services/control/control.approvals.service.js +209 -1
- package/dist/services/control/control.approvals.service.js.map +2 -2
- package/dist/services/control/control.approvals.service.spec.d.ts +1 -0
- package/dist/services/control/control.dashboards.service.d.ts +76 -0
- package/dist/services/control/control.dashboards.service.js +180 -0
- package/dist/services/control/control.dashboards.service.js.map +7 -0
- package/dist/services/control/control.dashboards.service.spec.d.ts +1 -0
- package/dist/services/control/control.feature-flags.service.d.ts +53 -0
- package/dist/services/control/control.feature-flags.service.js +123 -0
- package/dist/services/control/control.feature-flags.service.js.map +7 -0
- package/dist/services/control/control.feature-flags.service.spec.d.ts +1 -0
- package/dist/services/control/control.platform.service.d.ts +14 -0
- package/dist/services/control/control.platform.service.js +27 -0
- package/dist/services/control/control.platform.service.js.map +2 -2
- package/dist/services/control/control.platform.service.spec.d.ts +1 -0
- package/dist/services/external/external.accounts.service.d.ts +2 -2
- package/dist/services/external/external.accounts.service.js.map +2 -2
- package/dist/services/github/github.service.d.ts +20 -0
- package/dist/services/github/github.service.js +50 -1
- package/dist/services/github/github.service.js.map +2 -2
- package/dist/services/openrouter/openrouter.service.d.ts +35 -0
- package/dist/services/openrouter/openrouter.service.js +45 -0
- package/dist/services/openrouter/openrouter.service.js.map +2 -2
- package/dist/services/slack/slack-blockkit.service.d.ts +7 -0
- package/dist/services/slack/slack-blockkit.service.js +1 -0
- package/dist/services/slack/slack-blockkit.service.js.map +2 -2
- package/dist/utils/environments.js +3 -4
- package/dist/utils/environments.js.map +2 -2
- package/dist/utils/sse.d.ts +1 -0
- package/dist/utils/sse.js +7 -0
- package/dist/utils/sse.js.map +2 -2
- package/package.json +2 -2
|
@@ -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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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
|
|
5
|
-
"mappings": "AAOA,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAY1B,MAAM,OAAO,EAAE,IAAI,UAAU;
|
|
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
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExternalClickwrapConfigDto, ExternalOrganizationDto,
|
|
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<
|
|
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
|
|
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,
|
|
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": "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",
|
|
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
|
}
|
|
@@ -169,7 +169,10 @@ class GithubService {
|
|
|
169
169
|
tag_name: release.tag_name,
|
|
170
170
|
body: release.body,
|
|
171
171
|
created_at: release.created_at,
|
|
172
|
-
prerelease: release.prerelease
|
|
172
|
+
prerelease: release.prerelease,
|
|
173
|
+
html_url: release.html_url,
|
|
174
|
+
published_at: release.published_at ?? void 0,
|
|
175
|
+
draft: release.draft
|
|
173
176
|
};
|
|
174
177
|
});
|
|
175
178
|
}
|
|
@@ -275,6 +278,52 @@ class GithubService {
|
|
|
275
278
|
}
|
|
276
279
|
return response.body ?? "";
|
|
277
280
|
}
|
|
281
|
+
static async compareCommits(params) {
|
|
282
|
+
const encodeRef = (ref) => encodeURIComponent(ref).replace(/%2F/gu, "/");
|
|
283
|
+
const base = encodeRef(params.options.base);
|
|
284
|
+
const head = encodeRef(params.options.head);
|
|
285
|
+
const serviceContext = {
|
|
286
|
+
method: {
|
|
287
|
+
name: `GithubService.compareCommits`,
|
|
288
|
+
// per_page=1: callers read the counts, not the commit list.
|
|
289
|
+
url: `https://api.github.com/repos/${params.options.owner}/${params.options.repo}/compare/${base}...${head}?per_page=1`,
|
|
290
|
+
normalizedUrl: `https://api.github.com/repos/:owner/:repo/compare/:basehead`,
|
|
291
|
+
type: "get"
|
|
292
|
+
},
|
|
293
|
+
source: params.config.metrics?.source || "unset",
|
|
294
|
+
target: {
|
|
295
|
+
name: "github",
|
|
296
|
+
type: "external"
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
const response = await request({
|
|
300
|
+
config: params.config,
|
|
301
|
+
url: serviceContext.method.url,
|
|
302
|
+
method: serviceContext.method.type,
|
|
303
|
+
metricsDetails: serviceContext,
|
|
304
|
+
type: "json",
|
|
305
|
+
headers: {
|
|
306
|
+
Accept: "application/vnd.github+json",
|
|
307
|
+
Authorization: `Bearer ${params.options.apiToken}`
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
if (!response.ok) {
|
|
311
|
+
throw new HttpError(
|
|
312
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
313
|
+
response.status,
|
|
314
|
+
response.statusText
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
const aheadBy = response.body?.ahead_by;
|
|
318
|
+
if (typeof aheadBy !== "number") {
|
|
319
|
+
throw new HttpError(
|
|
320
|
+
`${serviceContext.method.name}: no ahead_by in the answer`,
|
|
321
|
+
response.status,
|
|
322
|
+
response.statusText
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
return { aheadBy, htmlUrl: response.body?.html_url ?? "" };
|
|
326
|
+
}
|
|
278
327
|
}
|
|
279
328
|
export {
|
|
280
329
|
GithubService
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/services/github/github.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 { HOUR } from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { Cache } from '../../utils/cache.js'\nimport { HttpError } from '../../utils/errors.js'\n\nconst releaseCache = new Cache<string, GithubRelease[]>(HOUR)\n\n/**\n * How many release pages are fetched at once.\n *\n * GitHub's *secondary* rate limit is about concurrency, not a request budget:\n * firing every iteration in one `Promise.all` is what answered\n * `GET /api/releases/release-train/:trainName` with \"You have exceeded a\n * secondary rate limit\". Batching keeps the walk parallel enough to stay fast\n * while bounding how much of it is in flight.\n */\nconst PAGE_BATCH_SIZE = 5\n\nexport interface GithubListMajorMinorReleasesRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n iterations?: number\n onlyLatest?: boolean\n includeAlphas?: boolean\n onlyPrerelease?: boolean\n replaceBugfixSuffix?: boolean\n }\n}\n\nexport interface GithubListReleasesRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n pageSize?: number\n currentPage?: number\n }\n}\n\nexport interface GithubGetNextBugfixReleaseVersionRequest\n extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n iterations?: number\n onlyLatest?: boolean\n majorMinor: string\n }\n}\n\nexport interface GithubRelease {\n url: string\n tag_name: string\n body: string\n created_at: string\n prerelease: boolean\n}\n\nexport interface GithubListDirectoryContentRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n path: string\n ref?: string\n }\n}\n\nexport interface GithubGetRawFileRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n path: string\n ref?: string\n }\n}\n\nexport interface GithubContentItem {\n name: string\n path: string\n sha: string\n size: number\n url: string\n download_url: string | undefined\n type: string\n}\n\nexport class GithubService {\n public static async getNextBugfixReleaseVersion(\n params: GithubGetNextBugfixReleaseVersionRequest,\n ): Promise<string> {\n const releases = await GithubService.listMajorMinorReleases({\n config: params.config,\n options: {\n owner: params.options.owner,\n repo: params.options.repo,\n apiToken: params.options.apiToken,\n onlyLatest: true,\n iterations: params.options.iterations,\n },\n })\n if (releases.length === 0) {\n throw new Error(\n `No releases found for ${params.options.owner}/${params.options.repo}`,\n )\n }\n const latestRelease = releases[0]\n if (latestRelease.tag_name.startsWith(params.options.majorMinor)) {\n throw new Error(\n `Not allowed to create a new bugfix release for ${latestRelease.tag_name}`,\n )\n }\n for (const release of releases) {\n if (release.tag_name.startsWith(params.options.majorMinor)) {\n const versionSplitted = release.tag_name.split('.')\n if (versionSplitted.length !== 3) {\n throw new Error(`Invalid version format: ${release.tag_name}`)\n }\n const majorVersion = Number(versionSplitted[0])\n const minorVersion = Number(versionSplitted[1])\n const patchVersion = Number(versionSplitted[2]) + 1\n return `${majorVersion}.${minorVersion}.${patchVersion}`\n }\n }\n throw new Error(`No bugfix release found for ${params.options.majorMinor}`)\n }\n\n public static async listMajorMinorReleases(\n params: GithubListMajorMinorReleasesRequest,\n ): Promise<GithubRelease[]> {\n // `replaceBugfixSuffix` rewrites the tags in the result, so it has to be\n // part of the key: without it `getNextBugfixReleaseVersion` (which does not\n // set it) and the release-train lookup (which does) shared one entry and\n // whichever loaded first decided what the other saw.\n const cacheKey = `major-minor-${params.options.owner}-${\n params.options.repo\n }-${params.options.onlyLatest ?? false}-${\n params.options.includeAlphas ?? false\n }-${params.options.onlyPrerelease ?? false}-${\n params.options.replaceBugfixSuffix ?? false\n }`\n // Single-flight: several trains are looked up at once and they all land on\n // this key, so without coalescing each concurrent miss ran its own page\n // walk against GitHub.\n return releaseCache.getOrLoad(\n cacheKey,\n () => GithubService.fetchMajorMinorReleases(params),\n { ignoreCache: params.cacheControl?.ignoreCache === true },\n )\n }\n\n private static async fetchMajorMinorReleases(\n params: GithubListMajorMinorReleasesRequest,\n ): Promise<GithubRelease[]> {\n const pageSize = 100\n const ITERATIONS = params.options.iterations || 15\n\n // Walk the pages in bounded-concurrency batches and stop as soon as a page\n // comes back short \u2014 GitHub only returns fewer than `per_page` items on the\n // last page, so every iteration after that was an empty response whose only\n // effect was upstream load.\n const allPageResults: GithubRelease[][] = []\n for (\n let firstPage = 1;\n firstPage <= ITERATIONS;\n firstPage += PAGE_BATCH_SIZE\n ) {\n const batchSize = Math.min(PAGE_BATCH_SIZE, ITERATIONS - firstPage + 1)\n // eslint-disable-next-line no-await-in-loop\n const batch = await Promise.all(\n Array.from({ length: batchSize }, (_, index) =>\n GithubService.getReleases({\n config: params.config,\n options: {\n owner: params.options.owner,\n repo: params.options.repo,\n apiToken: params.options.apiToken,\n pageSize,\n currentPage: firstPage + index,\n },\n }),\n ),\n )\n allPageResults.push(...batch)\n if (batch.some((releases) => releases.length < pageSize)) {\n break\n }\n }\n\n const stableReleases: GithubRelease[] = []\n for (const releases of allPageResults) {\n // replace bugfix suffix\n if (params.options.replaceBugfixSuffix === true) {\n releases.forEach((release) => {\n if (release.tag_name.endsWith('_bugfix')) {\n release.tag_name = release.tag_name.replace(/_bugfix.*/u, '')\n }\n })\n }\n\n const filtered = releases.filter((release) => {\n let includeRelease = !release.prerelease\n if (params.options.onlyPrerelease) {\n includeRelease = release.prerelease\n }\n if (includeRelease && params.options.includeAlphas) {\n includeRelease =\n release.tag_name.includes('-alpha') &&\n !release.tag_name.includes('-alphatest')\n }\n return includeRelease\n })\n stableReleases.push(...filtered)\n }\n\n let releasesToRespond: GithubRelease[] = []\n\n stableReleases.sort((a, b) => {\n return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()\n })\n\n if (params.options.onlyLatest) {\n const onlyLatest: Record<string, number> = {}\n for (const release of stableReleases) {\n const splitted = release.tag_name.split('.')\n const majorMinor = `${splitted[0]}.${splitted[1]}`\n const patchVersion = Number(splitted[2])\n if (!onlyLatest[majorMinor]) {\n onlyLatest[majorMinor] = patchVersion\n } else if (patchVersion > onlyLatest[majorMinor]) {\n onlyLatest[majorMinor] = patchVersion\n }\n }\n const releaseStrings = Object.keys(onlyLatest).map((key) => {\n return `${key}.${onlyLatest[key]}`\n })\n const foundReleases = stableReleases.filter((release) => {\n return releaseStrings.includes(release.tag_name)\n })\n releasesToRespond = foundReleases\n } else {\n releasesToRespond = stableReleases\n }\n // Storing is `getOrLoad`'s job \u2014 it only caches a load that resolved.\n return releasesToRespond\n }\n\n public static async getReleases(\n params: GithubListReleasesRequest,\n ): Promise<GithubRelease[]> {\n const pageSize = params.options.pageSize || 100\n const currentPage = params.options.currentPage || 1\n const queryParams = new URLSearchParams()\n queryParams.append('per_page', pageSize.toString())\n queryParams.append('page', currentPage.toString())\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.getReleases`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/releases?${queryParams.toString()}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<GithubRelease[]>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n type: 'json',\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${params.options.apiToken}`,\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 let releases: GithubRelease[] = []\n if (response.body) {\n releases = response.body.map((release) => {\n return {\n url: release.url,\n tag_name: release.tag_name,\n body: release.body,\n created_at: release.created_at,\n prerelease: release.prerelease,\n }\n })\n }\n return releases\n }\n\n public static async listDirectoryContent(\n params: GithubListDirectoryContentRequest,\n ): Promise<GithubContentItem[]> {\n const queryParams = new URLSearchParams()\n if (params.options.ref) {\n queryParams.append('ref', params.options.ref)\n }\n const encodedPath = encodeURIComponent(params.options.path).replace(\n /%2F/gu,\n '/',\n )\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.listDirectoryContent`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/contents/${encodedPath}${queryParams.size ? `?${queryParams.toString()}` : ''}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo/contents/:path`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<any[]>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n type: 'json',\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${params.options.apiToken}`,\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 let items: GithubContentItem[] = []\n if (Array.isArray(response.body)) {\n items = response.body.map((item: any) => {\n return {\n name: item.name,\n path: item.path,\n sha: item.sha,\n size: item.size,\n url: item.url,\n download_url: item.download_url,\n type: item.type,\n } as GithubContentItem\n })\n }\n return items\n }\n\n public static async getRawFile(\n params: GithubGetRawFileRequest,\n ): Promise<string> {\n const queryParams = new URLSearchParams()\n if (params.options.ref) {\n queryParams.append('ref', params.options.ref)\n }\n const encodedPath = encodeURIComponent(params.options.path).replace(\n /%2F/gu,\n '/',\n )\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.getRawFile`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/contents/${encodedPath}${queryParams.size ? `?${queryParams.toString()}` : ''}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo/contents/:path`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<string>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n // do not set a Content-Type for GET, but expect text back\n type: 'none',\n responseType: 'text',\n headers: {\n Accept: 'application/vnd.github.raw',\n Authorization: `Bearer ${params.options.apiToken}`,\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 return response.body ?? ''\n }\n}\n"],
|
|
5
|
-
"mappings": "AAMA,SAAS,YAAY;AAKrB,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAE1B,MAAM,eAAe,IAAI,MAA+B,IAAI;AAW5D,MAAM,kBAAkB;
|
|
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 { HOUR } from '@camunda/ccma-shared-types'\nimport type {\n RequestBaseParams,\n RequestBaseServiceContext,\n} from '../../types/general.types.js'\nimport { request } from '../../utils/api.js'\nimport { Cache } from '../../utils/cache.js'\nimport { HttpError } from '../../utils/errors.js'\n\nconst releaseCache = new Cache<string, GithubRelease[]>(HOUR)\n\n/**\n * How many release pages are fetched at once.\n *\n * GitHub's *secondary* rate limit is about concurrency, not a request budget:\n * firing every iteration in one `Promise.all` is what answered\n * `GET /api/releases/release-train/:trainName` with \"You have exceeded a\n * secondary rate limit\". Batching keeps the walk parallel enough to stay fast\n * while bounding how much of it is in flight.\n */\nconst PAGE_BATCH_SIZE = 5\n\nexport interface GithubListMajorMinorReleasesRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n iterations?: number\n onlyLatest?: boolean\n includeAlphas?: boolean\n onlyPrerelease?: boolean\n replaceBugfixSuffix?: boolean\n }\n}\n\nexport interface GithubListReleasesRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n pageSize?: number\n currentPage?: number\n }\n}\n\nexport interface GithubGetNextBugfixReleaseVersionRequest\n extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n iterations?: number\n onlyLatest?: boolean\n majorMinor: string\n }\n}\n\nexport interface GithubRelease {\n url: string\n tag_name: string\n body: string\n /** The date of the tagged commit, not of the release. */\n created_at: string\n prerelease: boolean\n html_url?: string\n /** When the release was made. A draft has none. */\n published_at?: string | undefined\n draft?: boolean\n}\n\nexport interface GithubListDirectoryContentRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n path: string\n ref?: string\n }\n}\n\nexport interface GithubGetRawFileRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n path: string\n ref?: string\n }\n}\n\nexport interface GithubContentItem {\n name: string\n path: string\n sha: string\n size: number\n url: string\n download_url: string | undefined\n type: string\n}\n\nexport interface GithubCompareCommitsRequest extends RequestBaseParams {\n options: {\n owner: string\n repo: string\n apiToken: string\n base: string\n head: string\n }\n}\n\nexport interface GithubCommitComparison {\n /** Commits that `head` has and `base` does not have. */\n aheadBy: number\n htmlUrl: string\n}\n\nexport class GithubService {\n public static async getNextBugfixReleaseVersion(\n params: GithubGetNextBugfixReleaseVersionRequest,\n ): Promise<string> {\n const releases = await GithubService.listMajorMinorReleases({\n config: params.config,\n options: {\n owner: params.options.owner,\n repo: params.options.repo,\n apiToken: params.options.apiToken,\n onlyLatest: true,\n iterations: params.options.iterations,\n },\n })\n if (releases.length === 0) {\n throw new Error(\n `No releases found for ${params.options.owner}/${params.options.repo}`,\n )\n }\n const latestRelease = releases[0]\n if (latestRelease.tag_name.startsWith(params.options.majorMinor)) {\n throw new Error(\n `Not allowed to create a new bugfix release for ${latestRelease.tag_name}`,\n )\n }\n for (const release of releases) {\n if (release.tag_name.startsWith(params.options.majorMinor)) {\n const versionSplitted = release.tag_name.split('.')\n if (versionSplitted.length !== 3) {\n throw new Error(`Invalid version format: ${release.tag_name}`)\n }\n const majorVersion = Number(versionSplitted[0])\n const minorVersion = Number(versionSplitted[1])\n const patchVersion = Number(versionSplitted[2]) + 1\n return `${majorVersion}.${minorVersion}.${patchVersion}`\n }\n }\n throw new Error(`No bugfix release found for ${params.options.majorMinor}`)\n }\n\n public static async listMajorMinorReleases(\n params: GithubListMajorMinorReleasesRequest,\n ): Promise<GithubRelease[]> {\n // `replaceBugfixSuffix` rewrites the tags in the result, so it has to be\n // part of the key: without it `getNextBugfixReleaseVersion` (which does not\n // set it) and the release-train lookup (which does) shared one entry and\n // whichever loaded first decided what the other saw.\n const cacheKey = `major-minor-${params.options.owner}-${\n params.options.repo\n }-${params.options.onlyLatest ?? false}-${\n params.options.includeAlphas ?? false\n }-${params.options.onlyPrerelease ?? false}-${\n params.options.replaceBugfixSuffix ?? false\n }`\n // Single-flight: several trains are looked up at once and they all land on\n // this key, so without coalescing each concurrent miss ran its own page\n // walk against GitHub.\n return releaseCache.getOrLoad(\n cacheKey,\n () => GithubService.fetchMajorMinorReleases(params),\n { ignoreCache: params.cacheControl?.ignoreCache === true },\n )\n }\n\n private static async fetchMajorMinorReleases(\n params: GithubListMajorMinorReleasesRequest,\n ): Promise<GithubRelease[]> {\n const pageSize = 100\n const ITERATIONS = params.options.iterations || 15\n\n // Walk the pages in bounded-concurrency batches and stop as soon as a page\n // comes back short \u2014 GitHub only returns fewer than `per_page` items on the\n // last page, so every iteration after that was an empty response whose only\n // effect was upstream load.\n const allPageResults: GithubRelease[][] = []\n for (\n let firstPage = 1;\n firstPage <= ITERATIONS;\n firstPage += PAGE_BATCH_SIZE\n ) {\n const batchSize = Math.min(PAGE_BATCH_SIZE, ITERATIONS - firstPage + 1)\n // eslint-disable-next-line no-await-in-loop\n const batch = await Promise.all(\n Array.from({ length: batchSize }, (_, index) =>\n GithubService.getReleases({\n config: params.config,\n options: {\n owner: params.options.owner,\n repo: params.options.repo,\n apiToken: params.options.apiToken,\n pageSize,\n currentPage: firstPage + index,\n },\n }),\n ),\n )\n allPageResults.push(...batch)\n if (batch.some((releases) => releases.length < pageSize)) {\n break\n }\n }\n\n const stableReleases: GithubRelease[] = []\n for (const releases of allPageResults) {\n // replace bugfix suffix\n if (params.options.replaceBugfixSuffix === true) {\n releases.forEach((release) => {\n if (release.tag_name.endsWith('_bugfix')) {\n release.tag_name = release.tag_name.replace(/_bugfix.*/u, '')\n }\n })\n }\n\n const filtered = releases.filter((release) => {\n let includeRelease = !release.prerelease\n if (params.options.onlyPrerelease) {\n includeRelease = release.prerelease\n }\n if (includeRelease && params.options.includeAlphas) {\n includeRelease =\n release.tag_name.includes('-alpha') &&\n !release.tag_name.includes('-alphatest')\n }\n return includeRelease\n })\n stableReleases.push(...filtered)\n }\n\n let releasesToRespond: GithubRelease[] = []\n\n stableReleases.sort((a, b) => {\n return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()\n })\n\n if (params.options.onlyLatest) {\n const onlyLatest: Record<string, number> = {}\n for (const release of stableReleases) {\n const splitted = release.tag_name.split('.')\n const majorMinor = `${splitted[0]}.${splitted[1]}`\n const patchVersion = Number(splitted[2])\n if (!onlyLatest[majorMinor]) {\n onlyLatest[majorMinor] = patchVersion\n } else if (patchVersion > onlyLatest[majorMinor]) {\n onlyLatest[majorMinor] = patchVersion\n }\n }\n const releaseStrings = Object.keys(onlyLatest).map((key) => {\n return `${key}.${onlyLatest[key]}`\n })\n const foundReleases = stableReleases.filter((release) => {\n return releaseStrings.includes(release.tag_name)\n })\n releasesToRespond = foundReleases\n } else {\n releasesToRespond = stableReleases\n }\n // Storing is `getOrLoad`'s job \u2014 it only caches a load that resolved.\n return releasesToRespond\n }\n\n public static async getReleases(\n params: GithubListReleasesRequest,\n ): Promise<GithubRelease[]> {\n const pageSize = params.options.pageSize || 100\n const currentPage = params.options.currentPage || 1\n const queryParams = new URLSearchParams()\n queryParams.append('per_page', pageSize.toString())\n queryParams.append('page', currentPage.toString())\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.getReleases`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/releases?${queryParams.toString()}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<\n (Omit<GithubRelease, 'published_at'> & { published_at: string | null })[]\n >({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n type: 'json',\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${params.options.apiToken}`,\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 let releases: GithubRelease[] = []\n if (response.body) {\n releases = response.body.map((release) => {\n return {\n url: release.url,\n tag_name: release.tag_name,\n body: release.body,\n created_at: release.created_at,\n prerelease: release.prerelease,\n html_url: release.html_url,\n published_at: release.published_at ?? undefined,\n draft: release.draft,\n }\n })\n }\n return releases\n }\n\n public static async listDirectoryContent(\n params: GithubListDirectoryContentRequest,\n ): Promise<GithubContentItem[]> {\n const queryParams = new URLSearchParams()\n if (params.options.ref) {\n queryParams.append('ref', params.options.ref)\n }\n const encodedPath = encodeURIComponent(params.options.path).replace(\n /%2F/gu,\n '/',\n )\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.listDirectoryContent`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/contents/${encodedPath}${queryParams.size ? `?${queryParams.toString()}` : ''}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo/contents/:path`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<any[]>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n type: 'json',\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${params.options.apiToken}`,\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 let items: GithubContentItem[] = []\n if (Array.isArray(response.body)) {\n items = response.body.map((item: any) => {\n return {\n name: item.name,\n path: item.path,\n sha: item.sha,\n size: item.size,\n url: item.url,\n download_url: item.download_url,\n type: item.type,\n } as GithubContentItem\n })\n }\n return items\n }\n\n public static async getRawFile(\n params: GithubGetRawFileRequest,\n ): Promise<string> {\n const queryParams = new URLSearchParams()\n if (params.options.ref) {\n queryParams.append('ref', params.options.ref)\n }\n const encodedPath = encodeURIComponent(params.options.path).replace(\n /%2F/gu,\n '/',\n )\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.getRawFile`,\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/contents/${encodedPath}${queryParams.size ? `?${queryParams.toString()}` : ''}`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo/contents/:path`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<string>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n // do not set a Content-Type for GET, but expect text back\n type: 'none',\n responseType: 'text',\n headers: {\n Accept: 'application/vnd.github.raw',\n Authorization: `Bearer ${params.options.apiToken}`,\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 return response.body ?? ''\n }\n\n public static async compareCommits(\n params: GithubCompareCommitsRequest,\n ): Promise<GithubCommitComparison> {\n const encodeRef = (ref: string) =>\n encodeURIComponent(ref).replace(/%2F/gu, '/')\n const base = encodeRef(params.options.base)\n const head = encodeRef(params.options.head)\n const serviceContext: RequestBaseServiceContext = {\n method: {\n name: `GithubService.compareCommits`,\n // per_page=1: callers read the counts, not the commit list.\n url: `https://api.github.com/repos/${params.options.owner}/${\n params.options.repo\n }/compare/${base}...${head}?per_page=1`,\n normalizedUrl: `https://api.github.com/repos/:owner/:repo/compare/:basehead`,\n type: 'get',\n },\n source: params.config.metrics?.source || 'unset',\n target: {\n name: 'github',\n type: 'external',\n },\n }\n\n const response = await request<{ ahead_by?: number; html_url?: string }>({\n config: params.config,\n url: serviceContext.method.url,\n method: serviceContext.method.type,\n metricsDetails: serviceContext,\n type: 'json',\n headers: {\n Accept: 'application/vnd.github+json',\n Authorization: `Bearer ${params.options.apiToken}`,\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 // `request` gives `{}` for a body that is not JSON. A missing count must\n // not read as \"no new commits\".\n const aheadBy = response.body?.ahead_by\n if (typeof aheadBy !== 'number') {\n throw new HttpError(\n `${serviceContext.method.name}: no ahead_by in the answer`,\n response.status,\n response.statusText,\n )\n }\n\n return { aheadBy, htmlUrl: response.body?.html_url ?? '' }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -64,6 +64,11 @@ export interface CreateOpenRouterKeyRequest extends RequestBaseParams {
|
|
|
64
64
|
limit?: number;
|
|
65
65
|
/** When false, credits of a customer-owned provider key do not count. */
|
|
66
66
|
include_byok_in_limit?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* UUID of the workspace that owns the key. When absent, OpenRouter puts the
|
|
69
|
+
* key in the default workspace of the account.
|
|
70
|
+
*/
|
|
71
|
+
workspace_id?: string;
|
|
67
72
|
};
|
|
68
73
|
}
|
|
69
74
|
/**
|
|
@@ -143,6 +148,11 @@ export interface ListOpenRouterKeysRequest extends RequestBaseParams {
|
|
|
143
148
|
offset?: number;
|
|
144
149
|
/** When true, disabled keys are part of the result. */
|
|
145
150
|
includeDisabled?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* UUID of the workspace to list. When absent, OpenRouter lists the default
|
|
153
|
+
* workspace only, so a key in another workspace is not in the result.
|
|
154
|
+
*/
|
|
155
|
+
workspace_id?: string;
|
|
146
156
|
};
|
|
147
157
|
}
|
|
148
158
|
/**
|
|
@@ -151,6 +161,23 @@ export interface ListOpenRouterKeysRequest extends RequestBaseParams {
|
|
|
151
161
|
export interface ListOpenRouterKeysResponse {
|
|
152
162
|
data: OpenRouterKeyData[];
|
|
153
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Request to read one workspace
|
|
166
|
+
* GET /workspaces/{id}
|
|
167
|
+
*/
|
|
168
|
+
export interface GetOpenRouterWorkspaceRequest extends RequestBaseParams {
|
|
169
|
+
options: OpenRouterRequestOptions & {
|
|
170
|
+
/** UUID of the workspace to read. */
|
|
171
|
+
workspaceId: string;
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Response from reading one workspace. The caller needs the status code only,
|
|
176
|
+
* so the body stays open.
|
|
177
|
+
*/
|
|
178
|
+
export interface GetOpenRouterWorkspaceResponse {
|
|
179
|
+
[key: string]: unknown;
|
|
180
|
+
}
|
|
154
181
|
/**
|
|
155
182
|
* Service for the key management API of OpenRouter.
|
|
156
183
|
*
|
|
@@ -196,5 +223,13 @@ export declare class OpenRouterService {
|
|
|
196
223
|
* GET /keys
|
|
197
224
|
*/
|
|
198
225
|
static listKeys(params: ListOpenRouterKeysRequest): Promise<ListOpenRouterKeysResponse>;
|
|
226
|
+
/**
|
|
227
|
+
* Read one workspace.
|
|
228
|
+
*
|
|
229
|
+
* A 404 means that the workspace does not exist. A caller uses this to check
|
|
230
|
+
* a workspace id before it creates keys in that workspace.
|
|
231
|
+
* GET /workspaces/{id}
|
|
232
|
+
*/
|
|
233
|
+
static getWorkspace(params: GetOpenRouterWorkspaceRequest): Promise<GetOpenRouterWorkspaceResponse>;
|
|
199
234
|
}
|
|
200
235
|
export {};
|
|
@@ -27,6 +27,9 @@ class OpenRouterService {
|
|
|
27
27
|
},
|
|
28
28
|
...params.options.include_byok_in_limit !== void 0 && {
|
|
29
29
|
include_byok_in_limit: params.options.include_byok_in_limit
|
|
30
|
+
},
|
|
31
|
+
...params.options.workspace_id && {
|
|
32
|
+
workspace_id: params.options.workspace_id
|
|
30
33
|
}
|
|
31
34
|
};
|
|
32
35
|
const response = await request({
|
|
@@ -187,6 +190,9 @@ class OpenRouterService {
|
|
|
187
190
|
if (params.options.includeDisabled) {
|
|
188
191
|
query.set("include_disabled", "true");
|
|
189
192
|
}
|
|
193
|
+
if (params.options.workspace_id) {
|
|
194
|
+
query.set("workspace_id", params.options.workspace_id);
|
|
195
|
+
}
|
|
190
196
|
const queryString = query.toString();
|
|
191
197
|
const serviceContext = {
|
|
192
198
|
method: {
|
|
@@ -219,6 +225,45 @@ class OpenRouterService {
|
|
|
219
225
|
}
|
|
220
226
|
return response.body;
|
|
221
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Read one workspace.
|
|
230
|
+
*
|
|
231
|
+
* A 404 means that the workspace does not exist. A caller uses this to check
|
|
232
|
+
* a workspace id before it creates keys in that workspace.
|
|
233
|
+
* GET /workspaces/{id}
|
|
234
|
+
*/
|
|
235
|
+
static async getWorkspace(params) {
|
|
236
|
+
const serviceContext = {
|
|
237
|
+
method: {
|
|
238
|
+
name: "OpenRouterService.getWorkspace",
|
|
239
|
+
url: `${params.options.openRouterApiBaseUrl}/workspaces/${encodeURIComponent(params.options.workspaceId)}`,
|
|
240
|
+
normalizedUrl: "/workspaces/:id",
|
|
241
|
+
type: "get"
|
|
242
|
+
},
|
|
243
|
+
source: params.config.metrics?.source || "unset",
|
|
244
|
+
target: {
|
|
245
|
+
name: "openrouter",
|
|
246
|
+
type: "external"
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const response = await request({
|
|
250
|
+
config: params.config,
|
|
251
|
+
url: serviceContext.method.url,
|
|
252
|
+
method: serviceContext.method.type,
|
|
253
|
+
metricsDetails: serviceContext,
|
|
254
|
+
headers: {
|
|
255
|
+
Authorization: `Bearer ${params.options.apiToken}`
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
if (!response.ok) {
|
|
259
|
+
throw new HttpError(
|
|
260
|
+
`${serviceContext.method.name}: ${response.status} ${response.statusText}`,
|
|
261
|
+
response.status,
|
|
262
|
+
response.statusText
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return response.body ?? {};
|
|
266
|
+
}
|
|
222
267
|
}
|
|
223
268
|
export {
|
|
224
269
|
OPENROUTER_KEY_PAGE_SIZE,
|