@shipfox/api-integration-linear 3.0.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.
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 23 files with swc (166.58ms)
2
+ Successfully compiled: 23 files with swc (245.18ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @shipfox/api-integration-linear
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fb70438: Cascades provider installation and token deletion when removing a connection.
8
+
9
+ ### Patch Changes
10
+
11
+ - bb037af: Resolves workspace packages from source during development while published consumers continue to use compiled output.
12
+ - Updated dependencies [2875241]
13
+ - Updated dependencies [bb037af]
14
+ - Updated dependencies [fb70438]
15
+ - @shipfox/api-integration-core-dto@5.0.0
16
+ - @shipfox/api-auth-context@5.0.0
17
+ - @shipfox/api-integration-linear-dto@5.0.0
18
+ - @shipfox/api-secrets@5.0.0
19
+ - @shipfox/api-workspaces@5.0.0
20
+ - @shipfox/config@1.2.2
21
+ - @shipfox/node-drizzle@0.3.1
22
+ - @shipfox/node-fastify@0.2.3
23
+ - @shipfox/node-opentelemetry@0.5.2
24
+ - @shipfox/node-postgres@0.4.2
25
+
26
+ ## 4.0.0
27
+
28
+ ### Patch Changes
29
+
30
+ - bbba3b7: Adds the Slack integration provider scaffold with installation storage, bot-token custody, and flag-gated registration.
31
+ - Updated dependencies [bbba3b7]
32
+ - @shipfox/node-drizzle@0.3.0
33
+ - @shipfox/api-secrets@4.0.0
34
+ - @shipfox/api-workspaces@4.0.0
35
+
3
36
  ## 3.0.0
4
37
 
5
38
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"installations.d.ts","sourceRoot":"","sources":["../../src/db/installations.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,wBAAwB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,MAAM,EAAE,wBAAwB,CAAC;CAClC;AAED,MAAM,WAAW,yCAAyC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC/B;AAWD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,8BAA8B,EACtC,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAyC7B;AAcD,wBAAsB,mCAAmC,CACvD,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAUzC;AAED,wBAAsB,qCAAqC,CACzD,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAUzC;AAED,wBAAsB,mCAAmC,CACvD,MAAM,EAAE,yCAAyC,EACjD,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAazC;AAED,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CASzC;AAED,wBAAsB,sCAAsC,CAC1D,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAC,GAAG;IAAC,QAAQ,EAAE,KAAK,CAAA;CAAC,CAAC;AAExF,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAErC"}
1
+ {"version":3,"file":"installations.d.ts","sourceRoot":"","sources":["../../src/db/installations.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,wBAAwB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,MAAM,EAAE,wBAAwB,CAAC;CAClC;AAED,MAAM,WAAW,yCAAyC;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAC/B;AAKD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,8BAA8B,EACtC,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAyC7B;AAED,wBAAsB,mCAAmC,CACvD,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAUzC;AAED,wBAAsB,qCAAqC,CACzD,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAUzC;AAED,wBAAsB,mCAAmC,CACvD,MAAM,EAAE,yCAAyC,EACjD,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAazC;AAED,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CASzC;AAED,wBAAsB,sCAAsC,CAC1D,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAM,GAC3B,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAC,GAAG;IAAC,QAAQ,EAAE,KAAK,CAAA;CAAC,CAAC;AAExF,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAErC"}
@@ -1,3 +1,4 @@
1
+ import { isUniqueViolation } from '@shipfox/node-drizzle';
1
2
  import { pgClient } from '@shipfox/node-postgres';
2
3
  import { eq } from 'drizzle-orm';
3
4
  import { LinearConnectionAlreadyLinkedError, LinearInstallationAlreadyLinkedError } from '#core/errors.js';
@@ -39,17 +40,6 @@ export async function upsertLinearInstallation(params, options = {}) {
39
40
  if (!row) throw new LinearInstallationAlreadyLinkedError(params.organizationId);
40
41
  return toLinearInstallation(row);
41
42
  }
42
- function isUniqueViolation(error, constraint) {
43
- let current = error;
44
- while(typeof current === 'object' && current !== null){
45
- const postgresError = current;
46
- if (postgresError.code === '23505' && postgresError.constraint === constraint) {
47
- return true;
48
- }
49
- current = postgresError.cause;
50
- }
51
- return false;
52
- }
53
43
  export async function getLinearInstallationByConnectionId(connectionId, options = {}) {
54
44
  const executor = options.tx ?? db();
55
45
  const rows = await executor.select().from(linearInstallations).where(eq(linearInstallations.connectionId, connectionId)).limit(1);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/installations.ts"],"sourcesContent":["import {pgClient} from '@shipfox/node-postgres';\nimport {eq} from 'drizzle-orm';\nimport {\n LinearConnectionAlreadyLinkedError,\n LinearInstallationAlreadyLinkedError,\n} from '#core/errors.js';\nimport {db} from './db.js';\nimport {linearInstallations, toLinearInstallation} from './schema/installations.js';\n\nexport type LinearInstallationStatus = 'installed' | 'revoked';\n\nexport interface LinearInstallation {\n id: string;\n connectionId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt: Date | null;\n status: LinearInstallationStatus;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertLinearInstallationParams {\n connectionId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt?: Date | null | undefined;\n status: LinearInstallationStatus;\n}\n\nexport interface UpdateLinearInstallationTokenExpiryParams {\n connectionId: string;\n tokenExpiresAt: Date | null;\n scopes?: string[] | undefined;\n}\n\ntype LinearDb = ReturnType<typeof db>;\ntype LinearTx = Parameters<Parameters<LinearDb['transaction']>[0]>[0];\n\ninterface PostgresErrorFields {\n code?: unknown;\n constraint?: unknown;\n cause?: unknown;\n}\n\nexport async function upsertLinearInstallation(\n params: UpsertLinearInstallationParams,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const now = new Date();\n let row: typeof linearInstallations.$inferSelect | undefined;\n\n try {\n [row] = await executor\n .insert(linearInstallations)\n .values({\n connectionId: params.connectionId,\n organizationId: params.organizationId,\n organizationUrlKey: params.organizationUrlKey,\n appUserId: params.appUserId,\n scopes: params.scopes,\n tokenExpiresAt: params.tokenExpiresAt ?? null,\n status: params.status,\n })\n .onConflictDoUpdate({\n target: linearInstallations.organizationId,\n setWhere: eq(linearInstallations.connectionId, params.connectionId),\n set: {\n connectionId: params.connectionId,\n organizationId: params.organizationId,\n organizationUrlKey: params.organizationUrlKey,\n appUserId: params.appUserId,\n scopes: params.scopes,\n tokenExpiresAt: params.tokenExpiresAt ?? null,\n status: params.status,\n updatedAt: now,\n },\n })\n .returning();\n } catch (error) {\n if (isUniqueViolation(error, 'integrations_linear_installations_connection_unique')) {\n throw new LinearConnectionAlreadyLinkedError(params.connectionId);\n }\n throw error;\n }\n\n if (!row) throw new LinearInstallationAlreadyLinkedError(params.organizationId);\n return toLinearInstallation(row);\n}\n\nfunction isUniqueViolation(error: unknown, constraint: string): boolean {\n let current = error;\n while (typeof current === 'object' && current !== null) {\n const postgresError = current as PostgresErrorFields;\n if (postgresError.code === '23505' && postgresError.constraint === constraint) {\n return true;\n }\n current = postgresError.cause;\n }\n return false;\n}\n\nexport async function getLinearInstallationByConnectionId(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const rows = await executor\n .select()\n .from(linearInstallations)\n .where(eq(linearInstallations.connectionId, connectionId))\n .limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function getLinearInstallationByOrganizationId(\n organizationId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const rows = await executor\n .select()\n .from(linearInstallations)\n .where(eq(linearInstallations.organizationId, organizationId))\n .limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function updateLinearInstallationTokenExpiry(\n params: UpdateLinearInstallationTokenExpiryParams,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const [row] = await executor\n .update(linearInstallations)\n .set({\n tokenExpiresAt: params.tokenExpiresAt,\n ...(params.scopes === undefined ? {} : {scopes: params.scopes}),\n updatedAt: new Date(),\n })\n .where(eq(linearInstallations.connectionId, params.connectionId))\n .returning();\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function markLinearInstallationRevoked(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const [row] = await executor\n .update(linearInstallations)\n .set({status: 'revoked', updatedAt: new Date()})\n .where(eq(linearInstallations.connectionId, connectionId))\n .returning();\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function deleteLinearInstallationByConnectionId(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<boolean> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const result = await executor\n .delete(linearInstallations)\n .where(eq(linearInstallations.connectionId, connectionId));\n return (result.rowCount ?? 0) > 0;\n}\n\nexport type LinearRefreshLockResult<T> = {acquired: true; value: T} | {acquired: false};\n\nexport function withLinearRefreshLock<T>(\n connectionId: string,\n fn: () => Promise<T>,\n): Promise<LinearRefreshLockResult<T>> {\n return withLinearRefreshLockClient(connectionId, fn);\n}\n\nasync function withLinearRefreshLockClient<T>(\n connectionId: string,\n fn: () => Promise<T>,\n): Promise<LinearRefreshLockResult<T>> {\n const client = await pgClient().connect();\n let acquired = false;\n try {\n const lock = await client.query<{acquired: boolean}>(\n 'SELECT pg_try_advisory_lock(hashtext($1)) AS acquired',\n [connectionId],\n );\n acquired = lock.rows[0]?.acquired === true;\n if (!acquired) return {acquired: false};\n\n const value = await fn();\n return {acquired: true, value};\n } finally {\n try {\n if (acquired) {\n await client.query('SELECT pg_advisory_unlock(hashtext($1))', [connectionId]);\n }\n } finally {\n client.release();\n }\n }\n}\n"],"names":["pgClient","eq","LinearConnectionAlreadyLinkedError","LinearInstallationAlreadyLinkedError","db","linearInstallations","toLinearInstallation","upsertLinearInstallation","params","options","executor","tx","now","Date","row","insert","values","connectionId","organizationId","organizationUrlKey","appUserId","scopes","tokenExpiresAt","status","onConflictDoUpdate","target","setWhere","set","updatedAt","returning","error","isUniqueViolation","constraint","current","postgresError","code","cause","getLinearInstallationByConnectionId","rows","select","from","where","limit","undefined","getLinearInstallationByOrganizationId","updateLinearInstallationTokenExpiry","update","markLinearInstallationRevoked","deleteLinearInstallationByConnectionId","result","delete","rowCount","withLinearRefreshLock","fn","withLinearRefreshLockClient","client","connect","acquired","lock","query","value","release"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/db/installations.ts"],"sourcesContent":["import {isUniqueViolation} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {eq} from 'drizzle-orm';\nimport {\n LinearConnectionAlreadyLinkedError,\n LinearInstallationAlreadyLinkedError,\n} from '#core/errors.js';\nimport {db} from './db.js';\nimport {linearInstallations, toLinearInstallation} from './schema/installations.js';\n\nexport type LinearInstallationStatus = 'installed' | 'revoked';\n\nexport interface LinearInstallation {\n id: string;\n connectionId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt: Date | null;\n status: LinearInstallationStatus;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertLinearInstallationParams {\n connectionId: string;\n organizationId: string;\n organizationUrlKey: string;\n appUserId: string;\n scopes: string[];\n tokenExpiresAt?: Date | null | undefined;\n status: LinearInstallationStatus;\n}\n\nexport interface UpdateLinearInstallationTokenExpiryParams {\n connectionId: string;\n tokenExpiresAt: Date | null;\n scopes?: string[] | undefined;\n}\n\ntype LinearDb = ReturnType<typeof db>;\ntype LinearTx = Parameters<Parameters<LinearDb['transaction']>[0]>[0];\n\nexport async function upsertLinearInstallation(\n params: UpsertLinearInstallationParams,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const now = new Date();\n let row: typeof linearInstallations.$inferSelect | undefined;\n\n try {\n [row] = await executor\n .insert(linearInstallations)\n .values({\n connectionId: params.connectionId,\n organizationId: params.organizationId,\n organizationUrlKey: params.organizationUrlKey,\n appUserId: params.appUserId,\n scopes: params.scopes,\n tokenExpiresAt: params.tokenExpiresAt ?? null,\n status: params.status,\n })\n .onConflictDoUpdate({\n target: linearInstallations.organizationId,\n setWhere: eq(linearInstallations.connectionId, params.connectionId),\n set: {\n connectionId: params.connectionId,\n organizationId: params.organizationId,\n organizationUrlKey: params.organizationUrlKey,\n appUserId: params.appUserId,\n scopes: params.scopes,\n tokenExpiresAt: params.tokenExpiresAt ?? null,\n status: params.status,\n updatedAt: now,\n },\n })\n .returning();\n } catch (error) {\n if (isUniqueViolation(error, 'integrations_linear_installations_connection_unique')) {\n throw new LinearConnectionAlreadyLinkedError(params.connectionId);\n }\n throw error;\n }\n\n if (!row) throw new LinearInstallationAlreadyLinkedError(params.organizationId);\n return toLinearInstallation(row);\n}\n\nexport async function getLinearInstallationByConnectionId(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const rows = await executor\n .select()\n .from(linearInstallations)\n .where(eq(linearInstallations.connectionId, connectionId))\n .limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function getLinearInstallationByOrganizationId(\n organizationId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const rows = await executor\n .select()\n .from(linearInstallations)\n .where(eq(linearInstallations.organizationId, organizationId))\n .limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function updateLinearInstallationTokenExpiry(\n params: UpdateLinearInstallationTokenExpiryParams,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const [row] = await executor\n .update(linearInstallations)\n .set({\n tokenExpiresAt: params.tokenExpiresAt,\n ...(params.scopes === undefined ? {} : {scopes: params.scopes}),\n updatedAt: new Date(),\n })\n .where(eq(linearInstallations.connectionId, params.connectionId))\n .returning();\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function markLinearInstallationRevoked(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<LinearInstallation | undefined> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const [row] = await executor\n .update(linearInstallations)\n .set({status: 'revoked', updatedAt: new Date()})\n .where(eq(linearInstallations.connectionId, connectionId))\n .returning();\n if (!row) return undefined;\n return toLinearInstallation(row);\n}\n\nexport async function deleteLinearInstallationByConnectionId(\n connectionId: string,\n options: {tx?: unknown} = {},\n): Promise<boolean> {\n const executor = (options.tx ?? db()) as LinearDb | LinearTx;\n const result = await executor\n .delete(linearInstallations)\n .where(eq(linearInstallations.connectionId, connectionId));\n return (result.rowCount ?? 0) > 0;\n}\n\nexport type LinearRefreshLockResult<T> = {acquired: true; value: T} | {acquired: false};\n\nexport function withLinearRefreshLock<T>(\n connectionId: string,\n fn: () => Promise<T>,\n): Promise<LinearRefreshLockResult<T>> {\n return withLinearRefreshLockClient(connectionId, fn);\n}\n\nasync function withLinearRefreshLockClient<T>(\n connectionId: string,\n fn: () => Promise<T>,\n): Promise<LinearRefreshLockResult<T>> {\n const client = await pgClient().connect();\n let acquired = false;\n try {\n const lock = await client.query<{acquired: boolean}>(\n 'SELECT pg_try_advisory_lock(hashtext($1)) AS acquired',\n [connectionId],\n );\n acquired = lock.rows[0]?.acquired === true;\n if (!acquired) return {acquired: false};\n\n const value = await fn();\n return {acquired: true, value};\n } finally {\n try {\n if (acquired) {\n await client.query('SELECT pg_advisory_unlock(hashtext($1))', [connectionId]);\n }\n } finally {\n client.release();\n }\n }\n}\n"],"names":["isUniqueViolation","pgClient","eq","LinearConnectionAlreadyLinkedError","LinearInstallationAlreadyLinkedError","db","linearInstallations","toLinearInstallation","upsertLinearInstallation","params","options","executor","tx","now","Date","row","insert","values","connectionId","organizationId","organizationUrlKey","appUserId","scopes","tokenExpiresAt","status","onConflictDoUpdate","target","setWhere","set","updatedAt","returning","error","getLinearInstallationByConnectionId","rows","select","from","where","limit","undefined","getLinearInstallationByOrganizationId","updateLinearInstallationTokenExpiry","update","markLinearInstallationRevoked","deleteLinearInstallationByConnectionId","result","delete","rowCount","withLinearRefreshLock","fn","withLinearRefreshLockClient","client","connect","acquired","lock","query","value","release"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -24,7 +24,7 @@ export { createLinearTokenStore, linearSecretsNamespace, } from '#core/tokens.js
24
24
  export type { HandleLinearWebhookOutcome, HandleLinearWebhookParams } from '#core/webhook.js';
25
25
  export { handleLinearWebhook } from '#core/webhook.js';
26
26
  export type { LinearInstallation, LinearInstallationStatus, UpdateLinearInstallationTokenExpiryParams, UpsertLinearInstallationParams, } from '#db/installations.js';
27
- export { getLinearInstallationByConnectionId, getLinearInstallationByOrganizationId, markLinearInstallationRevoked, updateLinearInstallationTokenExpiry, upsertLinearInstallation, withLinearRefreshLock, } from '#db/installations.js';
27
+ export { deleteLinearInstallationByConnectionId, getLinearInstallationByConnectionId, getLinearInstallationByOrganizationId, markLinearInstallationRevoked, updateLinearInstallationTokenExpiry, upsertLinearInstallation, withLinearRefreshLock, } from '#db/installations.js';
28
28
  export { type CreateLinearE2eRoutesOptions, createLinearE2eRoutes, } from '#presentation/e2eRoutes/index.js';
29
29
  export { closeDb, config, db, migrationsPath };
30
30
  export interface CreateLinearIntegrationProviderOptions {
@@ -35,9 +35,30 @@ export interface CreateLinearIntegrationProviderOptions {
35
35
  callTimeoutMs?: number | undefined;
36
36
  } | undefined;
37
37
  getLinearInstallationByConnectionId?: typeof getLinearInstallationByConnectionId | undefined;
38
+ cleanup?: {
39
+ deleteConnectionRecords?: (connection: {
40
+ id: string;
41
+ }, options: {
42
+ tx: unknown;
43
+ }) => Promise<void>;
44
+ deleteConnectionSecrets?: (connection: {
45
+ id: string;
46
+ workspaceId: string;
47
+ }) => Promise<void>;
48
+ } | undefined;
38
49
  routes?: (Omit<CreateLinearIntegrationRoutesOptions, 'linear' | 'connectionCapabilities'> & Partial<CreateLinearWebhookRoutesOptions>) | undefined;
39
50
  }
40
51
  export declare function createLinearIntegrationProvider(options?: CreateLinearIntegrationProviderOptions): {
52
+ routes: import("@shipfox/node-fastify").RouteGroup[];
53
+ deleteConnectionRecords?: (connection: {
54
+ id: string;
55
+ }, options: {
56
+ tx: unknown;
57
+ }) => Promise<void>;
58
+ deleteConnectionSecrets?: (connection: {
59
+ id: string;
60
+ workspaceId: string;
61
+ }) => Promise<void>;
41
62
  provider: string;
42
63
  displayName: string;
43
64
  adapters: {
@@ -48,6 +69,5 @@ export declare function createLinearIntegrationProvider(options?: CreateLinearIn
48
69
  connectionExternalUrl(connection: {
49
70
  id: string;
50
71
  }): Promise<string | undefined>;
51
- routes: import("@shipfox/node-fastify").RouteGroup[];
52
72
  };
53
73
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ export { assertLinearAuthorizationScopes, formatLinearOAuthScopes, LINEAR_OAUTH_
16
16
  export { signLinearInstallState, verifyLinearInstallState } from '#core/state.js';
17
17
  export { createLinearTokenStore, linearSecretsNamespace } from '#core/tokens.js';
18
18
  export { handleLinearWebhook } from '#core/webhook.js';
19
- export { getLinearInstallationByConnectionId, getLinearInstallationByOrganizationId, markLinearInstallationRevoked, updateLinearInstallationTokenExpiry, upsertLinearInstallation, withLinearRefreshLock } from '#db/installations.js';
19
+ export { deleteLinearInstallationByConnectionId, getLinearInstallationByConnectionId, getLinearInstallationByOrganizationId, markLinearInstallationRevoked, updateLinearInstallationTokenExpiry, upsertLinearInstallation, withLinearRefreshLock } from '#db/installations.js';
20
20
  export { createLinearE2eRoutes } from '#presentation/e2eRoutes/index.js';
21
21
  export { closeDb, config, db, migrationsPath };
22
22
  export function createLinearIntegrationProvider(options = {}) {
@@ -46,6 +46,7 @@ export function createLinearIntegrationProvider(options = {}) {
46
46
  if (!installation?.organizationUrlKey) return undefined;
47
47
  return `https://linear.app/${encodeURIComponent(installation.organizationUrlKey)}/settings`;
48
48
  },
49
+ ...options.cleanup,
49
50
  routes
50
51
  };
51
52
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {LINEAR_PROVIDER} from '@shipfox/api-integration-linear-dto';\nimport {createLinearApiClient, type LinearApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {LinearAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getLinearInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateLinearIntegrationRoutesOptions,\n createLinearIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateLinearWebhookRoutesOptions,\n createLinearWebhookRoutes,\n} from '#presentation/routes/webhooks.js';\n\nexport type {LinearProvider} from '@shipfox/api-integration-linear-dto';\nexport type {LinearApiClient, LinearAuthorization, LinearIdentity} from '#api/client.js';\nexport {createLinearApiClient} from '#api/client.js';\nexport type {\n LinearAgentToolCatalogEntry,\n LinearAgentToolCategory,\n LinearAgentToolId,\n LinearAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n linearAgentToolCatalog,\n linearAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport {\n type DisconnectLinearInstallationParams,\n disconnectLinearInstallation,\n} from '#core/disconnect.js';\nexport {\n LinearAccessTokenMissingError,\n LinearAuthorizationScopeMismatchError,\n LinearConnectionAlreadyLinkedError,\n LinearConnectionNotFoundError,\n LinearInstallationAlreadyLinkedError,\n LinearInstallStateActorMismatchError,\n LinearInstallStateError,\n LinearIntegrationProviderError,\n LinearOAuthCallbackError,\n LinearTokenUnrefreshableError,\n} from '#core/errors.js';\nexport type {ConnectLinearInstallationInput, HandleLinearCallbackParams} from '#core/install.js';\nexport {handleLinearCallback, handleLinearOAuthCallbackError} from '#core/install.js';\nexport {\n assertLinearAuthorizationScopes,\n formatLinearOAuthScopes,\n LINEAR_OAUTH_SCOPES,\n} from '#core/scopes.js';\nexport type {LinearInstallStateClaims} from '#core/state.js';\nexport {signLinearInstallState, verifyLinearInstallState} from '#core/state.js';\nexport type {\n CreateLinearTokenStoreParams,\n GetLinearAccessTokenParams,\n LinearConnectionResolverResult,\n LinearSecretsStore,\n LinearTokenStore,\n StoreLinearTokensParams,\n} from '#core/tokens.js';\nexport {\n createLinearTokenStore,\n linearSecretsNamespace,\n} from '#core/tokens.js';\nexport type {HandleLinearWebhookOutcome, HandleLinearWebhookParams} from '#core/webhook.js';\nexport {handleLinearWebhook} from '#core/webhook.js';\nexport type {\n LinearInstallation,\n LinearInstallationStatus,\n UpdateLinearInstallationTokenExpiryParams,\n UpsertLinearInstallationParams,\n} from '#db/installations.js';\nexport {\n getLinearInstallationByConnectionId,\n getLinearInstallationByOrganizationId,\n markLinearInstallationRevoked,\n updateLinearInstallationTokenExpiry,\n upsertLinearInstallation,\n withLinearRefreshLock,\n} from '#db/installations.js';\nexport {\n type CreateLinearE2eRoutesOptions,\n createLinearE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateLinearIntegrationProviderOptions {\n linear?: LinearApiClient | undefined;\n agentTools?:\n | {\n tokenStore: Pick<LinearTokenStore, 'getAccessToken'>;\n endpoint?: string | URL | undefined;\n callTimeoutMs?: number | undefined;\n }\n | undefined;\n getLinearInstallationByConnectionId?: typeof getLinearInstallationByConnectionId | undefined;\n routes?:\n | (Omit<CreateLinearIntegrationRoutesOptions, 'linear' | 'connectionCapabilities'> &\n Partial<CreateLinearWebhookRoutesOptions>)\n | undefined;\n}\n\nexport function createLinearIntegrationProvider(\n options: CreateLinearIntegrationProviderOptions = {},\n) {\n const linear = options.linear ?? createLinearApiClient();\n const getInstallationByConnectionId =\n options.getLinearInstallationByConnectionId ?? getLinearInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new LinearAgentToolsProvider(options.agentTools),\n }\n : {};\n\n const routes = options.routes\n ? [\n createLinearIntegrationRoutes({\n linear,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n ...options.routes,\n }),\n ]\n : [];\n if (options.routes && hasLinearWebhookRoutesOptions(options.routes)) {\n routes.push(createLinearWebhookRoutes(options.routes));\n }\n\n return {\n provider: LINEAR_PROVIDER,\n displayName: 'Linear',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation?.organizationUrlKey) return undefined;\n return `https://linear.app/${encodeURIComponent(installation.organizationUrlKey)}/settings`;\n },\n routes,\n };\n}\n\nfunction hasLinearWebhookRoutesOptions(\n routes: Partial<CreateLinearWebhookRoutesOptions>,\n): routes is CreateLinearWebhookRoutesOptions {\n return (\n routes.coreDb !== undefined &&\n routes.publishIntegrationEventReceived !== undefined &&\n routes.recordDeliveryOnly !== undefined &&\n routes.getIntegrationConnectionById !== undefined\n );\n}\n"],"names":["LINEAR_PROVIDER","createLinearApiClient","config","LinearAgentToolsProvider","closeDb","db","getLinearInstallationByConnectionId","migrationsPath","createLinearIntegrationRoutes","createLinearWebhookRoutes","linearAgentToolCatalog","linearAgentToolSelectionCatalog","disconnectLinearInstallation","LinearAccessTokenMissingError","LinearAuthorizationScopeMismatchError","LinearConnectionAlreadyLinkedError","LinearConnectionNotFoundError","LinearInstallationAlreadyLinkedError","LinearInstallStateActorMismatchError","LinearInstallStateError","LinearIntegrationProviderError","LinearOAuthCallbackError","LinearTokenUnrefreshableError","handleLinearCallback","handleLinearOAuthCallbackError","assertLinearAuthorizationScopes","formatLinearOAuthScopes","LINEAR_OAUTH_SCOPES","signLinearInstallState","verifyLinearInstallState","createLinearTokenStore","linearSecretsNamespace","handleLinearWebhook","getLinearInstallationByOrganizationId","markLinearInstallationRevoked","updateLinearInstallationTokenExpiry","upsertLinearInstallation","withLinearRefreshLock","createLinearE2eRoutes","createLinearIntegrationProvider","options","linear","getInstallationByConnectionId","adapters","agentTools","agent_tools","routes","connectionCapabilities","hasLinearWebhookRoutesOptions","push","provider","displayName","connectionExternalUrl","connection","installation","id","organizationUrlKey","undefined","encodeURIComponent","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById"],"mappings":"AAAA,SAAQA,eAAe,QAAO,sCAAsC;AACpE,SAAQC,qBAAqB,QAA6B,iBAAiB;AAC3E,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,wBAAwB,QAAO,gCAAgC;AAEvE,SAAQC,OAAO,EAAEC,EAAE,QAAO,YAAY;AACtC,SAAQC,mCAAmC,QAAO,uBAAuB;AACzE,SAAQC,cAAc,QAAO,oBAAoB;AACjD,SAEEC,6BAA6B,QACxB,kCAAkC;AACzC,SAEEC,yBAAyB,QACpB,mCAAmC;AAI1C,SAAQR,qBAAqB,QAAO,iBAAiB;AAOrD,SACES,sBAAsB,EACtBC,+BAA+B,QAC1B,uBAAuB;AAC9B,SAEEC,4BAA4B,QACvB,sBAAsB;AAC7B,SACEC,6BAA6B,EAC7BC,qCAAqC,EACrCC,kCAAkC,EAClCC,6BAA6B,EAC7BC,oCAAoC,EACpCC,oCAAoC,EACpCC,uBAAuB,EACvBC,8BAA8B,EAC9BC,wBAAwB,EACxBC,6BAA6B,QACxB,kBAAkB;AAEzB,SAAQC,oBAAoB,EAAEC,8BAA8B,QAAO,mBAAmB;AACtF,SACEC,+BAA+B,EAC/BC,uBAAuB,EACvBC,mBAAmB,QACd,kBAAkB;AAEzB,SAAQC,sBAAsB,EAAEC,wBAAwB,QAAO,iBAAiB;AAShF,SACEC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AAEzB,SAAQC,mBAAmB,QAAO,mBAAmB;AAOrD,SACE1B,mCAAmC,EACnC2B,qCAAqC,EACrCC,6BAA6B,EAC7BC,mCAAmC,EACnCC,wBAAwB,EACxBC,qBAAqB,QAChB,uBAAuB;AAC9B,SAEEC,qBAAqB,QAChB,mCAAmC;AAC1C,SAAQlC,OAAO,EAAEF,MAAM,EAAEG,EAAE,EAAEE,cAAc,GAAE;AAkB7C,OAAO,SAASgC,gCACdC,UAAkD,CAAC,CAAC;IAEpD,MAAMC,SAASD,QAAQC,MAAM,IAAIxC;IACjC,MAAMyC,gCACJF,QAAQlC,mCAAmC,IAAIA;IACjD,MAAMqC,WAAWH,QAAQI,UAAU,GAC/B;QACEC,aAAa,IAAI1C,yBAAyBqC,QAAQI,UAAU;IAC9D,IACA,CAAC;IAEL,MAAME,SAASN,QAAQM,MAAM,GACzB;QACEtC,8BAA8B;YAC5BiC;YACAM,wBAAwBJ,SAASE,WAAW,GAAG;gBAAC;aAAc,GAAG,EAAE;YACnE,GAAGL,QAAQM,MAAM;QACnB;KACD,GACD,EAAE;IACN,IAAIN,QAAQM,MAAM,IAAIE,8BAA8BR,QAAQM,MAAM,GAAG;QACnEA,OAAOG,IAAI,CAACxC,0BAA0B+B,QAAQM,MAAM;IACtD;IAEA,OAAO;QACLI,UAAUlD;QACVmD,aAAa;QACbR;QACA,MAAMS,uBAAsBC,UAAwB;YAClD,MAAMC,eAAe,MAAMZ,8BAA8BW,WAAWE,EAAE;YACtE,IAAI,CAACD,cAAcE,oBAAoB,OAAOC;YAC9C,OAAO,CAAC,mBAAmB,EAAEC,mBAAmBJ,aAAaE,kBAAkB,EAAE,SAAS,CAAC;QAC7F;QACAV;IACF;AACF;AAEA,SAASE,8BACPF,MAAiD;IAEjD,OACEA,OAAOa,MAAM,KAAKF,aAClBX,OAAOc,+BAA+B,KAAKH,aAC3CX,OAAOe,kBAAkB,KAAKJ,aAC9BX,OAAOgB,4BAA4B,KAAKL;AAE5C"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {LINEAR_PROVIDER} from '@shipfox/api-integration-linear-dto';\nimport {createLinearApiClient, type LinearApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {LinearAgentToolsProvider} from '#core/agent-tools-provider.js';\nimport type {LinearTokenStore} from '#core/tokens.js';\nimport {closeDb, db} from '#db/db.js';\nimport {getLinearInstallationByConnectionId} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateLinearIntegrationRoutesOptions,\n createLinearIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {\n type CreateLinearWebhookRoutesOptions,\n createLinearWebhookRoutes,\n} from '#presentation/routes/webhooks.js';\n\nexport type {LinearProvider} from '@shipfox/api-integration-linear-dto';\nexport type {LinearApiClient, LinearAuthorization, LinearIdentity} from '#api/client.js';\nexport {createLinearApiClient} from '#api/client.js';\nexport type {\n LinearAgentToolCatalogEntry,\n LinearAgentToolCategory,\n LinearAgentToolId,\n LinearAgentToolRequiredScope,\n} from '#core/agent-tools.js';\nexport {\n linearAgentToolCatalog,\n linearAgentToolSelectionCatalog,\n} from '#core/agent-tools.js';\nexport {\n type DisconnectLinearInstallationParams,\n disconnectLinearInstallation,\n} from '#core/disconnect.js';\nexport {\n LinearAccessTokenMissingError,\n LinearAuthorizationScopeMismatchError,\n LinearConnectionAlreadyLinkedError,\n LinearConnectionNotFoundError,\n LinearInstallationAlreadyLinkedError,\n LinearInstallStateActorMismatchError,\n LinearInstallStateError,\n LinearIntegrationProviderError,\n LinearOAuthCallbackError,\n LinearTokenUnrefreshableError,\n} from '#core/errors.js';\nexport type {ConnectLinearInstallationInput, HandleLinearCallbackParams} from '#core/install.js';\nexport {handleLinearCallback, handleLinearOAuthCallbackError} from '#core/install.js';\nexport {\n assertLinearAuthorizationScopes,\n formatLinearOAuthScopes,\n LINEAR_OAUTH_SCOPES,\n} from '#core/scopes.js';\nexport type {LinearInstallStateClaims} from '#core/state.js';\nexport {signLinearInstallState, verifyLinearInstallState} from '#core/state.js';\nexport type {\n CreateLinearTokenStoreParams,\n GetLinearAccessTokenParams,\n LinearConnectionResolverResult,\n LinearSecretsStore,\n LinearTokenStore,\n StoreLinearTokensParams,\n} from '#core/tokens.js';\nexport {\n createLinearTokenStore,\n linearSecretsNamespace,\n} from '#core/tokens.js';\nexport type {HandleLinearWebhookOutcome, HandleLinearWebhookParams} from '#core/webhook.js';\nexport {handleLinearWebhook} from '#core/webhook.js';\nexport type {\n LinearInstallation,\n LinearInstallationStatus,\n UpdateLinearInstallationTokenExpiryParams,\n UpsertLinearInstallationParams,\n} from '#db/installations.js';\nexport {\n deleteLinearInstallationByConnectionId,\n getLinearInstallationByConnectionId,\n getLinearInstallationByOrganizationId,\n markLinearInstallationRevoked,\n updateLinearInstallationTokenExpiry,\n upsertLinearInstallation,\n withLinearRefreshLock,\n} from '#db/installations.js';\nexport {\n type CreateLinearE2eRoutesOptions,\n createLinearE2eRoutes,\n} from '#presentation/e2eRoutes/index.js';\nexport {closeDb, config, db, migrationsPath};\n\nexport interface CreateLinearIntegrationProviderOptions {\n linear?: LinearApiClient | undefined;\n agentTools?:\n | {\n tokenStore: Pick<LinearTokenStore, 'getAccessToken'>;\n endpoint?: string | URL | undefined;\n callTimeoutMs?: number | undefined;\n }\n | undefined;\n getLinearInstallationByConnectionId?: typeof getLinearInstallationByConnectionId | undefined;\n cleanup?:\n | {\n deleteConnectionRecords?: (\n connection: {id: string},\n options: {tx: unknown},\n ) => Promise<void>;\n deleteConnectionSecrets?: (connection: {id: string; workspaceId: string}) => Promise<void>;\n }\n | undefined;\n routes?:\n | (Omit<CreateLinearIntegrationRoutesOptions, 'linear' | 'connectionCapabilities'> &\n Partial<CreateLinearWebhookRoutesOptions>)\n | undefined;\n}\n\nexport function createLinearIntegrationProvider(\n options: CreateLinearIntegrationProviderOptions = {},\n) {\n const linear = options.linear ?? createLinearApiClient();\n const getInstallationByConnectionId =\n options.getLinearInstallationByConnectionId ?? getLinearInstallationByConnectionId;\n const adapters = options.agentTools\n ? {\n agent_tools: new LinearAgentToolsProvider(options.agentTools),\n }\n : {};\n\n const routes = options.routes\n ? [\n createLinearIntegrationRoutes({\n linear,\n connectionCapabilities: adapters.agent_tools ? ['agent_tools'] : [],\n ...options.routes,\n }),\n ]\n : [];\n if (options.routes && hasLinearWebhookRoutesOptions(options.routes)) {\n routes.push(createLinearWebhookRoutes(options.routes));\n }\n\n return {\n provider: LINEAR_PROVIDER,\n displayName: 'Linear',\n adapters,\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation?.organizationUrlKey) return undefined;\n return `https://linear.app/${encodeURIComponent(installation.organizationUrlKey)}/settings`;\n },\n ...options.cleanup,\n routes,\n };\n}\n\nfunction hasLinearWebhookRoutesOptions(\n routes: Partial<CreateLinearWebhookRoutesOptions>,\n): routes is CreateLinearWebhookRoutesOptions {\n return (\n routes.coreDb !== undefined &&\n routes.publishIntegrationEventReceived !== undefined &&\n routes.recordDeliveryOnly !== undefined &&\n routes.getIntegrationConnectionById !== undefined\n );\n}\n"],"names":["LINEAR_PROVIDER","createLinearApiClient","config","LinearAgentToolsProvider","closeDb","db","getLinearInstallationByConnectionId","migrationsPath","createLinearIntegrationRoutes","createLinearWebhookRoutes","linearAgentToolCatalog","linearAgentToolSelectionCatalog","disconnectLinearInstallation","LinearAccessTokenMissingError","LinearAuthorizationScopeMismatchError","LinearConnectionAlreadyLinkedError","LinearConnectionNotFoundError","LinearInstallationAlreadyLinkedError","LinearInstallStateActorMismatchError","LinearInstallStateError","LinearIntegrationProviderError","LinearOAuthCallbackError","LinearTokenUnrefreshableError","handleLinearCallback","handleLinearOAuthCallbackError","assertLinearAuthorizationScopes","formatLinearOAuthScopes","LINEAR_OAUTH_SCOPES","signLinearInstallState","verifyLinearInstallState","createLinearTokenStore","linearSecretsNamespace","handleLinearWebhook","deleteLinearInstallationByConnectionId","getLinearInstallationByOrganizationId","markLinearInstallationRevoked","updateLinearInstallationTokenExpiry","upsertLinearInstallation","withLinearRefreshLock","createLinearE2eRoutes","createLinearIntegrationProvider","options","linear","getInstallationByConnectionId","adapters","agentTools","agent_tools","routes","connectionCapabilities","hasLinearWebhookRoutesOptions","push","provider","displayName","connectionExternalUrl","connection","installation","id","organizationUrlKey","undefined","encodeURIComponent","cleanup","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById"],"mappings":"AAAA,SAAQA,eAAe,QAAO,sCAAsC;AACpE,SAAQC,qBAAqB,QAA6B,iBAAiB;AAC3E,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,wBAAwB,QAAO,gCAAgC;AAEvE,SAAQC,OAAO,EAAEC,EAAE,QAAO,YAAY;AACtC,SAAQC,mCAAmC,QAAO,uBAAuB;AACzE,SAAQC,cAAc,QAAO,oBAAoB;AACjD,SAEEC,6BAA6B,QACxB,kCAAkC;AACzC,SAEEC,yBAAyB,QACpB,mCAAmC;AAI1C,SAAQR,qBAAqB,QAAO,iBAAiB;AAOrD,SACES,sBAAsB,EACtBC,+BAA+B,QAC1B,uBAAuB;AAC9B,SAEEC,4BAA4B,QACvB,sBAAsB;AAC7B,SACEC,6BAA6B,EAC7BC,qCAAqC,EACrCC,kCAAkC,EAClCC,6BAA6B,EAC7BC,oCAAoC,EACpCC,oCAAoC,EACpCC,uBAAuB,EACvBC,8BAA8B,EAC9BC,wBAAwB,EACxBC,6BAA6B,QACxB,kBAAkB;AAEzB,SAAQC,oBAAoB,EAAEC,8BAA8B,QAAO,mBAAmB;AACtF,SACEC,+BAA+B,EAC/BC,uBAAuB,EACvBC,mBAAmB,QACd,kBAAkB;AAEzB,SAAQC,sBAAsB,EAAEC,wBAAwB,QAAO,iBAAiB;AAShF,SACEC,sBAAsB,EACtBC,sBAAsB,QACjB,kBAAkB;AAEzB,SAAQC,mBAAmB,QAAO,mBAAmB;AAOrD,SACEC,sCAAsC,EACtC3B,mCAAmC,EACnC4B,qCAAqC,EACrCC,6BAA6B,EAC7BC,mCAAmC,EACnCC,wBAAwB,EACxBC,qBAAqB,QAChB,uBAAuB;AAC9B,SAEEC,qBAAqB,QAChB,mCAAmC;AAC1C,SAAQnC,OAAO,EAAEF,MAAM,EAAEG,EAAE,EAAEE,cAAc,GAAE;AA2B7C,OAAO,SAASiC,gCACdC,UAAkD,CAAC,CAAC;IAEpD,MAAMC,SAASD,QAAQC,MAAM,IAAIzC;IACjC,MAAM0C,gCACJF,QAAQnC,mCAAmC,IAAIA;IACjD,MAAMsC,WAAWH,QAAQI,UAAU,GAC/B;QACEC,aAAa,IAAI3C,yBAAyBsC,QAAQI,UAAU;IAC9D,IACA,CAAC;IAEL,MAAME,SAASN,QAAQM,MAAM,GACzB;QACEvC,8BAA8B;YAC5BkC;YACAM,wBAAwBJ,SAASE,WAAW,GAAG;gBAAC;aAAc,GAAG,EAAE;YACnE,GAAGL,QAAQM,MAAM;QACnB;KACD,GACD,EAAE;IACN,IAAIN,QAAQM,MAAM,IAAIE,8BAA8BR,QAAQM,MAAM,GAAG;QACnEA,OAAOG,IAAI,CAACzC,0BAA0BgC,QAAQM,MAAM;IACtD;IAEA,OAAO;QACLI,UAAUnD;QACVoD,aAAa;QACbR;QACA,MAAMS,uBAAsBC,UAAwB;YAClD,MAAMC,eAAe,MAAMZ,8BAA8BW,WAAWE,EAAE;YACtE,IAAI,CAACD,cAAcE,oBAAoB,OAAOC;YAC9C,OAAO,CAAC,mBAAmB,EAAEC,mBAAmBJ,aAAaE,kBAAkB,EAAE,SAAS,CAAC;QAC7F;QACA,GAAGhB,QAAQmB,OAAO;QAClBb;IACF;AACF;AAEA,SAASE,8BACPF,MAAiD;IAEjD,OACEA,OAAOc,MAAM,KAAKH,aAClBX,OAAOe,+BAA+B,KAAKJ,aAC3CX,OAAOgB,kBAAkB,KAAKL,aAC9BX,OAAOiB,4BAA4B,KAAKN;AAE5C"}