@mastra/factory 0.17.0-alpha.2 → 0.17.0-alpha.3
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/README.md
CHANGED
|
@@ -426,7 +426,7 @@ With no constructor options, the integration reads `GITLAB_ACCESS_TOKEN`, `GITLA
|
|
|
426
426
|
|
|
427
427
|
`GITLAB_BASE_URL` must use HTTPS. Plain HTTP is accepted only for loopback development instances (`localhost`, `127.0.0.0/8`, or `::1`), where the access token is sent without transport encryption.
|
|
428
428
|
|
|
429
|
-
For a Mastra Platform/Nango connection, use `PlatformGitLabIntegration`. `MastraFactory` installs it automatically whenever Platform credentials are configured and no integration with id `gitlab` was supplied. It discovers every active
|
|
429
|
+
For a Mastra Platform/Nango connection, use `PlatformGitLabIntegration`. `MastraFactory` installs it automatically whenever Platform credentials are configured and no integration with id `gitlab` was supplied. It discovers every active connection of the organization on the Platform's `gitlab` (OAuth) integration, proxies provider requests through `/v2/connections/{connectionId}/proxy`, and polls the Platform event log for GitLab events. `MASTRA_GITLAB_CONNECTION_ID` (or the `connectionId` constructor option) is optional and only narrows discovery to one connection. An explicit integration with id `gitlab` takes precedence.
|
|
430
430
|
|
|
431
431
|
```typescript
|
|
432
432
|
import { PlatformGitLabIntegration } from '@mastra/factory/integrations/platform/gitlab/integration';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/gitlab/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,eAAe,EAAkB,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAoB,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAG1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAIhE,UAAU,6BAA6B;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,cAAc,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,UAAU,qBAAqB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,eAAe,CAAC;IACrB,UAAU,EAAE,qBAAqB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/gitlab/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,eAAe,EAAkB,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAoB,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAG1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAIhE,UAAU,6BAA6B;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,QAAQ,GAAG,cAAc,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,UAAU,qBAAqB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,eAAe,CAAC;IACrB,UAAU,EAAE,qBAAqB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAQD,MAAM,WAAW,+BAA+B;IAC9C,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,YAAY,CAAC,EAAE,uBAAuB,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4FAA4F;IAC5F,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qGAAqG;IACrG,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,yBAA0B,SAAQ,qBAAqB;;gBAQtD,MAAM,GAAE,+BAAoC;IAclD,eAAe,IAAI,OAAO,CAAC,6BAA6B,EAAE,CAAC;IAclD,iBAAiB,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAI/D,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAI9C,kBAAkB,IAAI,MAAM;IAI5B,cAAuB,aAAa,IAAI,MAAM,GAAG,SAAS,CAEzD;cAEe,cAAc,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;cAIlD,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAMjF;;;;;OAKG;IACM,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,YAAY,EAAE;IAoBzD,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CA4CvC"}
|
|
@@ -4,12 +4,8 @@ import { attachGitLabRules } from "../../gitlab/rules.js";
|
|
|
4
4
|
import { GitLabIntegrationBase, gitlabConnection } from "../../gitlab/integration.js";
|
|
5
5
|
import { PlatformGitLabEventWorker } from "./event-worker.js";
|
|
6
6
|
//#region src/integrations/platform/gitlab/integration.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"gitlab-group",
|
|
10
|
-
"gitlab-group-token",
|
|
11
|
-
"gitlab-pat"
|
|
12
|
-
]);
|
|
7
|
+
/** The Platform's GitLab (OAuth) integration. It is the only GitLab credential flow Factory discovers. */
|
|
8
|
+
const GITLAB_INTEGRATION_ID = "gitlab";
|
|
13
9
|
var PlatformGitLabIntegration = class extends GitLabIntegrationBase {
|
|
14
10
|
#client;
|
|
15
11
|
#connectionId;
|
|
@@ -29,15 +25,7 @@ var PlatformGitLabIntegration = class extends GitLabIntegrationBase {
|
|
|
29
25
|
this.#pollingIntervalMs = config.pollingIntervalMs ?? optionalPositiveIntegerEnv("MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS");
|
|
30
26
|
}
|
|
31
27
|
async listConnections() {
|
|
32
|
-
|
|
33
|
-
return (await this.#client.request("GET", `/v2/connections?providerKey=${encodeURIComponent(integrationId)}`)).connections;
|
|
34
|
-
}));
|
|
35
|
-
const seen = /* @__PURE__ */ new Set();
|
|
36
|
-
return pages.flat().filter((connection) => {
|
|
37
|
-
if (this.#connectionId && connection.id !== this.#connectionId || !GITLAB_INTEGRATION_IDS.has(connection.integrationId) || seen.has(connection.id)) return false;
|
|
38
|
-
seen.add(connection.id);
|
|
39
|
-
return true;
|
|
40
|
-
});
|
|
28
|
+
return (await this.#client.request("GET", `/v2/connections?providerKey=${encodeURIComponent(GITLAB_INTEGRATION_ID)}`)).connections.filter((connection) => connection.integrationId === GITLAB_INTEGRATION_ID && (!this.#connectionId || connection.id === this.#connectionId));
|
|
41
29
|
}
|
|
42
30
|
async statusConnections() {
|
|
43
31
|
return this.listConnections();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.js","names":["#client","#connectionId","#endpointHost","#webhookSecret","#pollingEnabled","#pollingIntervalMs","#activeConnections","#context"],"sources":["../../../../src/integrations/platform/gitlab/integration.ts"],"sourcesContent":["import type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type { IntegrationContext } from '../../base.js';\nimport { GitLabApiClient, GitLabApiError } from '../../gitlab/api.js';\nimport type { GitLabRuleOverrides } from '../../gitlab/default-rules.js';\nimport { gitlabConnection, GitLabIntegrationBase } from '../../gitlab/integration.js';\nimport type { GitLabStatusConnection } from '../../gitlab/integration.js';\nimport { attachGitLabRules } from '../../gitlab/rules.js';\nimport { PlatformApiClient, platformApiClientConfigFromEnv } from '../api-client.js';\nimport type { PlatformApiClientConfig } from '../api-client.js';\nimport { PlatformGitLabEventWorker } from './event-worker.js';\nimport type { PlatformGitLabEventStorage } from './event-worker.js';\n\ninterface PlatformIntegrationConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\ninterface PlatformGitLabContext {\n id: string;\n label: string | null;\n api: GitLabApiClient;\n connection: IntegrationConnection;\n host: string;\n repositoryAccessToken: () => Promise<string>;\n}\n\ntype PlatformGitLabCredential =\n { type: 'oauth2'; accessToken: string; expiresAt: string | null } | { type: 'api_key'; apiKey: string };\n\nconst GITLAB_INTEGRATION_IDS = new Set(['gitlab', 'gitlab-group', 'gitlab-group-token', 'gitlab-pat']);\n\nexport interface PlatformGitLabIntegrationConfig {\n rules?: GitLabRuleOverrides;\n clientConfig?: PlatformApiClientConfig;\n connectionId?: string;\n /**\n * Optional. Only a direct project webhook to `/web/gitlab/webhook` needs it;\n * a Platform-connected deployment receives events by polling instead.\n */\n webhookSecret?: string;\n /** Defaults to `MASTRA_PLATFORM_GITLAB_POLLING_ENABLED`, and to true when that is unset. */\n pollingEnabled?: boolean;\n /** Defaults to `MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS`, and to the worker's 20 s when unset. */\n pollingIntervalMs?: number;\n}\n\nexport class PlatformGitLabIntegration extends GitLabIntegrationBase {\n readonly #client: PlatformApiClient;\n readonly #connectionId: string | undefined;\n readonly #endpointHost: string;\n readonly #webhookSecret: string | undefined;\n readonly #pollingEnabled: boolean;\n readonly #pollingIntervalMs: number | undefined;\n\n constructor(config: PlatformGitLabIntegrationConfig = {}) {\n super(config.rules);\n const connectionId = config.connectionId?.trim() || process.env.MASTRA_GITLAB_CONNECTION_ID?.trim() || undefined;\n const clientConfig = config.clientConfig ?? platformApiClientConfigFromEnv();\n this.#client = new PlatformApiClient(clientConfig);\n this.#connectionId = connectionId;\n this.#endpointHost = new URL(clientConfig.baseUrl).host;\n this.#webhookSecret = config.webhookSecret?.trim() || process.env.MASTRA_GITLAB_WEBHOOK_SECRET?.trim() || undefined;\n this.#pollingEnabled =\n config.pollingEnabled ?? process.env.MASTRA_PLATFORM_GITLAB_POLLING_ENABLED?.trim().toLowerCase() !== 'false';\n this.#pollingIntervalMs =\n config.pollingIntervalMs ?? optionalPositiveIntegerEnv('MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS');\n }\n\n async listConnections(): Promise<PlatformIntegrationConnection[]> {\n // Platform's providerKey filter matches a single integration ID, so query\n // each supported GitLab credential flow before applying the exact ID filter.\n const pages = await Promise.all(\n [...GITLAB_INTEGRATION_IDS].map(async integrationId => {\n const result = await this.#client.request<{ connections: PlatformIntegrationConnection[] }>(\n 'GET',\n `/v2/connections?providerKey=${encodeURIComponent(integrationId)}`,\n );\n return result.connections;\n }),\n );\n const seen = new Set<string>();\n return pages.flat().filter(connection => {\n if (\n (this.#connectionId && connection.id !== this.#connectionId) ||\n !GITLAB_INTEGRATION_IDS.has(connection.integrationId) ||\n seen.has(connection.id)\n ) {\n return false;\n }\n seen.add(connection.id);\n return true;\n });\n }\n\n override async statusConnections(): Promise<GitLabStatusConnection[]> {\n return this.listConnections();\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return (await this.#activeConnections()).length > 0;\n }\n\n authFailureMessage(): string {\n return 'GitLab rejected the connected account. Reconnect it in Mastra Platform.';\n }\n\n protected override get webhookSecret(): string | undefined {\n return this.#webhookSecret;\n }\n\n protected async activeContexts(): Promise<PlatformGitLabContext[]> {\n return (await this.#activeConnections()).map(connection => this.#context(connection));\n }\n\n protected async contextById(connectionId: string): Promise<PlatformGitLabContext> {\n const connection = (await this.#activeConnections()).find(candidate => candidate.id === connectionId);\n if (!connection) throw new GitLabApiError('GitLab connection is unavailable or requires reauthentication.', 401);\n return this.#context(connection);\n }\n\n /**\n * The reconcile sweeps from the base class plus, when polling is on, the\n * Platform event poller. Polling replaces the direct project webhook: the\n * webhook route stays mounted for deployments that also configured a secret,\n * but nothing in Platform mode requires one.\n */\n override workers(ctx: IntegrationContext): MastraWorker[] {\n const workers = super.workers(ctx);\n if (!this.#pollingEnabled) return workers;\n if (!ctx.controller) {\n throw new Error('Platform GitLab event polling requires the mounted Mastra Code controller.');\n }\n return [\n ...workers,\n new PlatformGitLabEventWorker({\n client: this.#client,\n controller: ctx.controller,\n gitlab: this,\n storage: ctx.storage.generic as unknown as PlatformGitLabEventStorage,\n listConnections: () => this.listConnections(),\n ingestFactoryEvent: attachGitLabRules(this, ctx),\n intervalMs: this.#pollingIntervalMs,\n }),\n ];\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n configured: true,\n mode: 'platform',\n endpointHost: this.#endpointHost,\n connectionFilterConfigured: Boolean(this.#connectionId),\n webhookConfigured: Boolean(this.#webhookSecret),\n pollingEnabled: this.#pollingEnabled,\n ...(this.#pollingIntervalMs === undefined ? {} : { pollingIntervalMs: this.#pollingIntervalMs }),\n };\n }\n\n async #activeConnections(): Promise<PlatformIntegrationConnection[]> {\n return (await this.listConnections()).filter(connection => connection.status === 'active');\n }\n\n #context(connection: PlatformIntegrationConnection): PlatformGitLabContext {\n return {\n id: connection.id,\n label: connection.accountLabel,\n api: new GitLabApiClient({ client: this.#client, connectionId: connection.id }),\n connection: gitlabConnection(connection.id),\n // Platform does not currently expose the connected GitLab instance host.\n host: 'gitlab.com',\n repositoryAccessToken: async () => {\n // Fetch for each git operation so an expiring OAuth token is refreshed by Platform.\n // Never persist or log the returned credential.\n const credential = await this.#client.request<PlatformGitLabCredential>(\n 'GET',\n `/v2/connections/${encodeURIComponent(connection.id)}/credentials`,\n );\n const token =\n credential?.type === 'oauth2'\n ? credential.accessToken\n : credential?.type === 'api_key'\n ? credential.apiKey\n : undefined;\n if (typeof token !== 'string' || !token.trim()) {\n throw new GitLabApiError('GitLab connection did not provide a repository credential.', 502);\n }\n return token;\n },\n };\n }\n}\n\nfunction optionalPositiveIntegerEnv(name: 'MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS'): number | undefined {\n const value = process.env[name]?.trim();\n if (!value) return undefined;\n const parsed = Number(value);\n if (!/^[1-9]\\d*$/.test(value) || !Number.isSafeInteger(parsed)) {\n throw new Error(`${name} must be a positive integer.`);\n }\n return parsed;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"integration.js","names":["#client","#connectionId","#endpointHost","#webhookSecret","#pollingEnabled","#pollingIntervalMs","#activeConnections","#context"],"sources":["../../../../src/integrations/platform/gitlab/integration.ts"],"sourcesContent":["import type { MastraWorker } from '@mastra/core/worker';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type { IntegrationContext } from '../../base.js';\nimport { GitLabApiClient, GitLabApiError } from '../../gitlab/api.js';\nimport type { GitLabRuleOverrides } from '../../gitlab/default-rules.js';\nimport { gitlabConnection, GitLabIntegrationBase } from '../../gitlab/integration.js';\nimport type { GitLabStatusConnection } from '../../gitlab/integration.js';\nimport { attachGitLabRules } from '../../gitlab/rules.js';\nimport { PlatformApiClient, platformApiClientConfigFromEnv } from '../api-client.js';\nimport type { PlatformApiClientConfig } from '../api-client.js';\nimport { PlatformGitLabEventWorker } from './event-worker.js';\nimport type { PlatformGitLabEventStorage } from './event-worker.js';\n\ninterface PlatformIntegrationConnection {\n id: string;\n integrationId: string;\n status: 'active' | 'needs_reauth';\n accountLabel: string | null;\n}\n\ninterface PlatformGitLabContext {\n id: string;\n label: string | null;\n api: GitLabApiClient;\n connection: IntegrationConnection;\n host: string;\n repositoryAccessToken: () => Promise<string>;\n}\n\ntype PlatformGitLabCredential =\n { type: 'oauth2'; accessToken: string; expiresAt: string | null } | { type: 'api_key'; apiKey: string };\n\n/** The Platform's GitLab (OAuth) integration. It is the only GitLab credential flow Factory discovers. */\nconst GITLAB_INTEGRATION_ID = 'gitlab';\n\nexport interface PlatformGitLabIntegrationConfig {\n rules?: GitLabRuleOverrides;\n clientConfig?: PlatformApiClientConfig;\n connectionId?: string;\n /**\n * Optional. Only a direct project webhook to `/web/gitlab/webhook` needs it;\n * a Platform-connected deployment receives events by polling instead.\n */\n webhookSecret?: string;\n /** Defaults to `MASTRA_PLATFORM_GITLAB_POLLING_ENABLED`, and to true when that is unset. */\n pollingEnabled?: boolean;\n /** Defaults to `MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS`, and to the worker's 20 s when unset. */\n pollingIntervalMs?: number;\n}\n\nexport class PlatformGitLabIntegration extends GitLabIntegrationBase {\n readonly #client: PlatformApiClient;\n readonly #connectionId: string | undefined;\n readonly #endpointHost: string;\n readonly #webhookSecret: string | undefined;\n readonly #pollingEnabled: boolean;\n readonly #pollingIntervalMs: number | undefined;\n\n constructor(config: PlatformGitLabIntegrationConfig = {}) {\n super(config.rules);\n const connectionId = config.connectionId?.trim() || process.env.MASTRA_GITLAB_CONNECTION_ID?.trim() || undefined;\n const clientConfig = config.clientConfig ?? platformApiClientConfigFromEnv();\n this.#client = new PlatformApiClient(clientConfig);\n this.#connectionId = connectionId;\n this.#endpointHost = new URL(clientConfig.baseUrl).host;\n this.#webhookSecret = config.webhookSecret?.trim() || process.env.MASTRA_GITLAB_WEBHOOK_SECRET?.trim() || undefined;\n this.#pollingEnabled =\n config.pollingEnabled ?? process.env.MASTRA_PLATFORM_GITLAB_POLLING_ENABLED?.trim().toLowerCase() !== 'false';\n this.#pollingIntervalMs =\n config.pollingIntervalMs ?? optionalPositiveIntegerEnv('MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS');\n }\n\n async listConnections(): Promise<PlatformIntegrationConnection[]> {\n const result = await this.#client.request<{ connections: PlatformIntegrationConnection[] }>(\n 'GET',\n `/v2/connections?providerKey=${encodeURIComponent(GITLAB_INTEGRATION_ID)}`,\n );\n // The providerKey filter is applied server side; the exact ID check guards\n // against a server that answers more loosely than asked.\n return result.connections.filter(\n connection =>\n connection.integrationId === GITLAB_INTEGRATION_ID &&\n (!this.#connectionId || connection.id === this.#connectionId),\n );\n }\n\n override async statusConnections(): Promise<GitLabStatusConnection[]> {\n return this.listConnections();\n }\n\n async hasActiveConnections(): Promise<boolean> {\n return (await this.#activeConnections()).length > 0;\n }\n\n authFailureMessage(): string {\n return 'GitLab rejected the connected account. Reconnect it in Mastra Platform.';\n }\n\n protected override get webhookSecret(): string | undefined {\n return this.#webhookSecret;\n }\n\n protected async activeContexts(): Promise<PlatformGitLabContext[]> {\n return (await this.#activeConnections()).map(connection => this.#context(connection));\n }\n\n protected async contextById(connectionId: string): Promise<PlatformGitLabContext> {\n const connection = (await this.#activeConnections()).find(candidate => candidate.id === connectionId);\n if (!connection) throw new GitLabApiError('GitLab connection is unavailable or requires reauthentication.', 401);\n return this.#context(connection);\n }\n\n /**\n * The reconcile sweeps from the base class plus, when polling is on, the\n * Platform event poller. Polling replaces the direct project webhook: the\n * webhook route stays mounted for deployments that also configured a secret,\n * but nothing in Platform mode requires one.\n */\n override workers(ctx: IntegrationContext): MastraWorker[] {\n const workers = super.workers(ctx);\n if (!this.#pollingEnabled) return workers;\n if (!ctx.controller) {\n throw new Error('Platform GitLab event polling requires the mounted Mastra Code controller.');\n }\n return [\n ...workers,\n new PlatformGitLabEventWorker({\n client: this.#client,\n controller: ctx.controller,\n gitlab: this,\n storage: ctx.storage.generic as unknown as PlatformGitLabEventStorage,\n listConnections: () => this.listConnections(),\n ingestFactoryEvent: attachGitLabRules(this, ctx),\n intervalMs: this.#pollingIntervalMs,\n }),\n ];\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n configured: true,\n mode: 'platform',\n endpointHost: this.#endpointHost,\n connectionFilterConfigured: Boolean(this.#connectionId),\n webhookConfigured: Boolean(this.#webhookSecret),\n pollingEnabled: this.#pollingEnabled,\n ...(this.#pollingIntervalMs === undefined ? {} : { pollingIntervalMs: this.#pollingIntervalMs }),\n };\n }\n\n async #activeConnections(): Promise<PlatformIntegrationConnection[]> {\n return (await this.listConnections()).filter(connection => connection.status === 'active');\n }\n\n #context(connection: PlatformIntegrationConnection): PlatformGitLabContext {\n return {\n id: connection.id,\n label: connection.accountLabel,\n api: new GitLabApiClient({ client: this.#client, connectionId: connection.id }),\n connection: gitlabConnection(connection.id),\n // Platform does not currently expose the connected GitLab instance host.\n host: 'gitlab.com',\n repositoryAccessToken: async () => {\n // Fetch for each git operation so an expiring OAuth token is refreshed by Platform.\n // Never persist or log the returned credential.\n const credential = await this.#client.request<PlatformGitLabCredential>(\n 'GET',\n `/v2/connections/${encodeURIComponent(connection.id)}/credentials`,\n );\n const token =\n credential?.type === 'oauth2'\n ? credential.accessToken\n : credential?.type === 'api_key'\n ? credential.apiKey\n : undefined;\n if (typeof token !== 'string' || !token.trim()) {\n throw new GitLabApiError('GitLab connection did not provide a repository credential.', 502);\n }\n return token;\n },\n };\n }\n}\n\nfunction optionalPositiveIntegerEnv(name: 'MASTRA_PLATFORM_GITLAB_POLLING_INTERVAL_MS'): number | undefined {\n const value = process.env[name]?.trim();\n if (!value) return undefined;\n const parsed = Number(value);\n if (!/^[1-9]\\d*$/.test(value) || !Number.isSafeInteger(parsed)) {\n throw new Error(`${name} must be a positive integer.`);\n }\n return parsed;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/factory",
|
|
3
|
-
"version": "0.17.0-alpha.
|
|
3
|
+
"version": "0.17.0-alpha.3",
|
|
4
4
|
"description": "Mastra Software Factory module: the server core behind the Mastra Software Factory — storage domains, integrations, and surfaces for agent-powered software delivery",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -57,11 +57,11 @@
|
|
|
57
57
|
"hono": "^4.13.7",
|
|
58
58
|
"posthog-node": "^5.46.1",
|
|
59
59
|
"zod": "^4.6.4",
|
|
60
|
-
"@mastra/auth-studio": "1.3.7-alpha.0",
|
|
61
60
|
"@mastra/auth-workos": "1.6.5",
|
|
62
|
-
"@mastra/
|
|
63
|
-
"@mastra/
|
|
64
|
-
"@mastra/slack": "1.6.4"
|
|
61
|
+
"@mastra/auth-studio": "1.3.7-alpha.0",
|
|
62
|
+
"@mastra/code-sdk": "1.8.1-alpha.2",
|
|
63
|
+
"@mastra/slack": "1.6.4",
|
|
64
|
+
"@mastra/core": "1.69.0-alpha.2"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "22.20.1",
|
|
@@ -72,9 +72,9 @@
|
|
|
72
72
|
"vitest": "4.1.11",
|
|
73
73
|
"@internal/lint": "0.0.134",
|
|
74
74
|
"@mastra/libsql": "1.23.1",
|
|
75
|
-
"@mastra/pg": "1.26.0",
|
|
76
75
|
"@internal/types-builder": "0.0.109",
|
|
77
|
-
"@internal/workspace": "0.0.6"
|
|
76
|
+
"@internal/workspace": "0.0.6",
|
|
77
|
+
"@mastra/pg": "1.26.0"
|
|
78
78
|
},
|
|
79
79
|
"engines": {
|
|
80
80
|
"node": ">=22.19.0"
|