@shipfox/api-integration-sentry 2.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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +192 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/api/client.d.ts +24 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +101 -0
- package/dist/api/client.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -0
- package/dist/core/errors.d.ts +57 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +67 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/install.d.ts +63 -0
- package/dist/core/install.d.ts.map +1 -0
- package/dist/core/install.js +209 -0
- package/dist/core/install.js.map +1 -0
- package/dist/core/signature.d.ts +7 -0
- package/dist/core/signature.d.ts.map +1 -0
- package/dist/core/signature.js +6 -0
- package/dist/core/signature.js.map +1 -0
- package/dist/core/webhook.d.ts +49 -0
- package/dist/core/webhook.d.ts.map +1 -0
- package/dist/core/webhook.js +175 -0
- package/dist/core/webhook.js.map +1 -0
- package/dist/db/db.d.ts +327 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +18 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/installations.d.ts +74 -0
- package/dist/db/installations.d.ts.map +1 -0
- package/dist/db/installations.js +120 -0
- package/dist/db/installations.js.map +1 -0
- package/dist/db/migrations.d.ts +2 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +5 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/installations.d.ts +165 -0
- package/dist/db/schema/installations.d.ts.map +1 -0
- package/dist/db/schema/installations.js +42 -0
- package/dist/db/schema/installations.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/presentation/dto/integrations.d.ts +15 -0
- package/dist/presentation/dto/integrations.d.ts.map +1 -0
- package/dist/presentation/dto/integrations.js +9 -0
- package/dist/presentation/dto/integrations.js.map +1 -0
- package/dist/presentation/routes/errors.d.ts +2 -0
- package/dist/presentation/routes/errors.d.ts.map +1 -0
- package/dist/presentation/routes/errors.js +51 -0
- package/dist/presentation/routes/errors.js.map +1 -0
- package/dist/presentation/routes/install.d.ts +16 -0
- package/dist/presentation/routes/install.d.ts.map +1 -0
- package/dist/presentation/routes/install.js +76 -0
- package/dist/presentation/routes/install.js.map +1 -0
- package/dist/presentation/routes/installation-handler.d.ts +9 -0
- package/dist/presentation/routes/installation-handler.d.ts.map +1 -0
- package/dist/presentation/routes/installation-handler.js +70 -0
- package/dist/presentation/routes/installation-handler.js.map +1 -0
- package/dist/presentation/routes/issue-handler.d.ts +9 -0
- package/dist/presentation/routes/issue-handler.d.ts.map +1 -0
- package/dist/presentation/routes/issue-handler.js +50 -0
- package/dist/presentation/routes/issue-handler.js.map +1 -0
- package/dist/presentation/routes/webhook-context.d.ts +20 -0
- package/dist/presentation/routes/webhook-context.d.ts.map +1 -0
- package/dist/presentation/routes/webhook-context.js +10 -0
- package/dist/presentation/routes/webhook-context.js.map +1 -0
- package/dist/presentation/routes/webhook-delivery.d.ts +28 -0
- package/dist/presentation/routes/webhook-delivery.d.ts.map +1 -0
- package/dist/presentation/routes/webhook-delivery.js +56 -0
- package/dist/presentation/routes/webhook-delivery.js.map +1 -0
- package/dist/presentation/routes/webhook-request.d.ts +10 -0
- package/dist/presentation/routes/webhook-request.d.ts.map +1 -0
- package/dist/presentation/routes/webhook-request.js +56 -0
- package/dist/presentation/routes/webhook-request.js.map +1 -0
- package/dist/presentation/routes/webhooks.d.ts +5 -0
- package/dist/presentation/routes/webhooks.d.ts.map +1 -0
- package/dist/presentation/routes/webhooks.js +71 -0
- package/dist/presentation/routes/webhooks.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +5 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +8 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/prune-unclaimed-installations.d.ts +4 -0
- package/dist/temporal/activities/prune-unclaimed-installations.d.ts.map +1 -0
- package/dist/temporal/activities/prune-unclaimed-installations.js +11 -0
- package/dist/temporal/activities/prune-unclaimed-installations.js.map +1 -0
- package/dist/temporal/constants.d.ts +2 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +3 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +2 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +3 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/temporal/workflows/prune-unclaimed-installations-cron.d.ts +2 -0
- package/dist/temporal/workflows/prune-unclaimed-installations-cron.d.ts.map +1 -0
- package/dist/temporal/workflows/prune-unclaimed-installations-cron.js +14 -0
- package/dist/temporal/workflows/prune-unclaimed-installations-cron.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +14 -0
- package/drizzle/meta/_journal.json +13 -0
- package/drizzle.config.ts +7 -0
- package/package.json +70 -0
- package/src/api/client.test.ts +147 -0
- package/src/api/client.ts +147 -0
- package/src/config.test.ts +16 -0
- package/src/config.ts +35 -0
- package/src/connection-external-url.test.ts +79 -0
- package/src/core/errors.ts +81 -0
- package/src/core/install.test.ts +343 -0
- package/src/core/install.ts +305 -0
- package/src/core/signature.test.ts +50 -0
- package/src/core/signature.ts +11 -0
- package/src/core/webhook.test.ts +118 -0
- package/src/core/webhook.ts +246 -0
- package/src/db/db.ts +18 -0
- package/src/db/installations.test.ts +224 -0
- package/src/db/installations.ts +207 -0
- package/src/db/migrations.ts +4 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/installations.ts +46 -0
- package/src/index.test.ts +18 -0
- package/src/index.ts +127 -0
- package/src/presentation/dto/integrations.ts +9 -0
- package/src/presentation/routes/errors.ts +48 -0
- package/src/presentation/routes/install.test.ts +325 -0
- package/src/presentation/routes/install.ts +102 -0
- package/src/presentation/routes/installation-handler.ts +76 -0
- package/src/presentation/routes/issue-handler.ts +52 -0
- package/src/presentation/routes/webhook-context.ts +25 -0
- package/src/presentation/routes/webhook-delivery.ts +61 -0
- package/src/presentation/routes/webhook-request.ts +66 -0
- package/src/presentation/routes/webhooks.test.ts +773 -0
- package/src/presentation/routes/webhooks.ts +59 -0
- package/src/temporal/activities/index.ts +7 -0
- package/src/temporal/activities/prune-unclaimed-installations.test.ts +52 -0
- package/src/temporal/activities/prune-unclaimed-installations.ts +11 -0
- package/src/temporal/constants.ts +1 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/src/temporal/workflows/prune-unclaimed-installations-cron.ts +15 -0
- package/test/env.ts +11 -0
- package/test/factories/index.ts +9 -0
- package/test/factories/sentry-installation-webhook.ts +35 -0
- package/test/factories/sentry-installation.ts +44 -0
- package/test/factories/sentry-issue-webhook.ts +34 -0
- package/test/globalSetup.ts +14 -0
- package/test/index.ts +9 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +9 -0
- package/vitest.config.ts +12 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type { SentryInstallation } from '#db/installations.js';
|
|
2
|
+
export declare const sentryInstallations: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
3
|
+
name: "installations";
|
|
4
|
+
schema: undefined;
|
|
5
|
+
columns: {
|
|
6
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
7
|
+
name: "id";
|
|
8
|
+
tableName: "installations";
|
|
9
|
+
dataType: "string";
|
|
10
|
+
columnType: "PgUUID";
|
|
11
|
+
data: string;
|
|
12
|
+
driverParam: string;
|
|
13
|
+
notNull: true;
|
|
14
|
+
hasDefault: true;
|
|
15
|
+
isPrimaryKey: true;
|
|
16
|
+
isAutoincrement: false;
|
|
17
|
+
hasRuntimeDefault: false;
|
|
18
|
+
enumValues: undefined;
|
|
19
|
+
baseColumn: never;
|
|
20
|
+
identity: undefined;
|
|
21
|
+
generated: undefined;
|
|
22
|
+
}, {}, {}>;
|
|
23
|
+
connectionId: import("drizzle-orm/pg-core").PgColumn<{
|
|
24
|
+
name: "connection_id";
|
|
25
|
+
tableName: "installations";
|
|
26
|
+
dataType: "string";
|
|
27
|
+
columnType: "PgUUID";
|
|
28
|
+
data: string;
|
|
29
|
+
driverParam: string;
|
|
30
|
+
notNull: false;
|
|
31
|
+
hasDefault: false;
|
|
32
|
+
isPrimaryKey: false;
|
|
33
|
+
isAutoincrement: false;
|
|
34
|
+
hasRuntimeDefault: false;
|
|
35
|
+
enumValues: undefined;
|
|
36
|
+
baseColumn: never;
|
|
37
|
+
identity: undefined;
|
|
38
|
+
generated: undefined;
|
|
39
|
+
}, {}, {}>;
|
|
40
|
+
installationUuid: import("drizzle-orm/pg-core").PgColumn<{
|
|
41
|
+
name: "installation_uuid";
|
|
42
|
+
tableName: "installations";
|
|
43
|
+
dataType: "string";
|
|
44
|
+
columnType: "PgText";
|
|
45
|
+
data: string;
|
|
46
|
+
driverParam: string;
|
|
47
|
+
notNull: true;
|
|
48
|
+
hasDefault: false;
|
|
49
|
+
isPrimaryKey: false;
|
|
50
|
+
isAutoincrement: false;
|
|
51
|
+
hasRuntimeDefault: false;
|
|
52
|
+
enumValues: [string, ...string[]];
|
|
53
|
+
baseColumn: never;
|
|
54
|
+
identity: undefined;
|
|
55
|
+
generated: undefined;
|
|
56
|
+
}, {}, {}>;
|
|
57
|
+
orgSlug: import("drizzle-orm/pg-core").PgColumn<{
|
|
58
|
+
name: "org_slug";
|
|
59
|
+
tableName: "installations";
|
|
60
|
+
dataType: "string";
|
|
61
|
+
columnType: "PgText";
|
|
62
|
+
data: string;
|
|
63
|
+
driverParam: string;
|
|
64
|
+
notNull: true;
|
|
65
|
+
hasDefault: false;
|
|
66
|
+
isPrimaryKey: false;
|
|
67
|
+
isAutoincrement: false;
|
|
68
|
+
hasRuntimeDefault: false;
|
|
69
|
+
enumValues: [string, ...string[]];
|
|
70
|
+
baseColumn: never;
|
|
71
|
+
identity: undefined;
|
|
72
|
+
generated: undefined;
|
|
73
|
+
}, {}, {}>;
|
|
74
|
+
status: import("drizzle-orm/pg-core").PgColumn<{
|
|
75
|
+
name: "status";
|
|
76
|
+
tableName: "installations";
|
|
77
|
+
dataType: "string";
|
|
78
|
+
columnType: "PgText";
|
|
79
|
+
data: string;
|
|
80
|
+
driverParam: string;
|
|
81
|
+
notNull: true;
|
|
82
|
+
hasDefault: false;
|
|
83
|
+
isPrimaryKey: false;
|
|
84
|
+
isAutoincrement: false;
|
|
85
|
+
hasRuntimeDefault: false;
|
|
86
|
+
enumValues: [string, ...string[]];
|
|
87
|
+
baseColumn: never;
|
|
88
|
+
identity: undefined;
|
|
89
|
+
generated: undefined;
|
|
90
|
+
}, {}, {}>;
|
|
91
|
+
codeHash: import("drizzle-orm/pg-core").PgColumn<{
|
|
92
|
+
name: "code_hash";
|
|
93
|
+
tableName: "installations";
|
|
94
|
+
dataType: "string";
|
|
95
|
+
columnType: "PgText";
|
|
96
|
+
data: string;
|
|
97
|
+
driverParam: string;
|
|
98
|
+
notNull: false;
|
|
99
|
+
hasDefault: false;
|
|
100
|
+
isPrimaryKey: false;
|
|
101
|
+
isAutoincrement: false;
|
|
102
|
+
hasRuntimeDefault: false;
|
|
103
|
+
enumValues: [string, ...string[]];
|
|
104
|
+
baseColumn: never;
|
|
105
|
+
identity: undefined;
|
|
106
|
+
generated: undefined;
|
|
107
|
+
}, {}, {}>;
|
|
108
|
+
installerUserId: import("drizzle-orm/pg-core").PgColumn<{
|
|
109
|
+
name: "installer_user_id";
|
|
110
|
+
tableName: "installations";
|
|
111
|
+
dataType: "string";
|
|
112
|
+
columnType: "PgUUID";
|
|
113
|
+
data: string;
|
|
114
|
+
driverParam: string;
|
|
115
|
+
notNull: false;
|
|
116
|
+
hasDefault: false;
|
|
117
|
+
isPrimaryKey: false;
|
|
118
|
+
isAutoincrement: false;
|
|
119
|
+
hasRuntimeDefault: false;
|
|
120
|
+
enumValues: undefined;
|
|
121
|
+
baseColumn: never;
|
|
122
|
+
identity: undefined;
|
|
123
|
+
generated: undefined;
|
|
124
|
+
}, {}, {}>;
|
|
125
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
126
|
+
name: "created_at";
|
|
127
|
+
tableName: "installations";
|
|
128
|
+
dataType: "date";
|
|
129
|
+
columnType: "PgTimestamp";
|
|
130
|
+
data: Date;
|
|
131
|
+
driverParam: string;
|
|
132
|
+
notNull: true;
|
|
133
|
+
hasDefault: true;
|
|
134
|
+
isPrimaryKey: false;
|
|
135
|
+
isAutoincrement: false;
|
|
136
|
+
hasRuntimeDefault: false;
|
|
137
|
+
enumValues: undefined;
|
|
138
|
+
baseColumn: never;
|
|
139
|
+
identity: undefined;
|
|
140
|
+
generated: undefined;
|
|
141
|
+
}, {}, {}>;
|
|
142
|
+
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
143
|
+
name: "updated_at";
|
|
144
|
+
tableName: "installations";
|
|
145
|
+
dataType: "date";
|
|
146
|
+
columnType: "PgTimestamp";
|
|
147
|
+
data: Date;
|
|
148
|
+
driverParam: string;
|
|
149
|
+
notNull: true;
|
|
150
|
+
hasDefault: true;
|
|
151
|
+
isPrimaryKey: false;
|
|
152
|
+
isAutoincrement: false;
|
|
153
|
+
hasRuntimeDefault: false;
|
|
154
|
+
enumValues: undefined;
|
|
155
|
+
baseColumn: never;
|
|
156
|
+
identity: undefined;
|
|
157
|
+
generated: undefined;
|
|
158
|
+
}, {}, {}>;
|
|
159
|
+
};
|
|
160
|
+
dialect: "pg";
|
|
161
|
+
}>;
|
|
162
|
+
export type SentryInstallationDb = typeof sentryInstallations.$inferSelect;
|
|
163
|
+
export type SentryInstallationCreateDb = typeof sentryInstallations.$inferInsert;
|
|
164
|
+
export declare function toSentryInstallation(row: SentryInstallationDb): SentryInstallation;
|
|
165
|
+
//# sourceMappingURL=installations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installations.d.ts","sourceRoot":"","sources":["../../../src/db/schema/installations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAG7D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuB/B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAC;AAC3E,MAAM,MAAM,0BAA0B,GAAG,OAAO,mBAAmB,CAAC,YAAY,CAAC;AAEjF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,oBAAoB,GAAG,kBAAkB,CAYlF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { uuidv7PrimaryKey } from '@shipfox/node-drizzle';
|
|
2
|
+
import { text, timestamp, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { pgTable } from './common.js';
|
|
4
|
+
export const sentryInstallations = pgTable('installations', {
|
|
5
|
+
id: uuidv7PrimaryKey(),
|
|
6
|
+
// Null until a logged-in user claims the verified install into a workspace.
|
|
7
|
+
// An unclaimed install (`connection_id IS NULL`, `status='installed'`) is
|
|
8
|
+
// persisted by the authoritative webhook before any browser claim arrives.
|
|
9
|
+
connectionId: uuid('connection_id'),
|
|
10
|
+
installationUuid: text('installation_uuid').notNull(),
|
|
11
|
+
orgSlug: text('org_slug').notNull(),
|
|
12
|
+
status: text('status').notNull(),
|
|
13
|
+
// sha256(authorization code) of the exchange that verified this install.
|
|
14
|
+
// The claim presents the code and we match the hash, so a bare uuid alone
|
|
15
|
+
// cannot bind the install (IDOR guard) without storing a live credential.
|
|
16
|
+
codeHash: text('code_hash'),
|
|
17
|
+
installerUserId: uuid('installer_user_id'),
|
|
18
|
+
createdAt: timestamp('created_at', {
|
|
19
|
+
withTimezone: true
|
|
20
|
+
}).notNull().defaultNow(),
|
|
21
|
+
updatedAt: timestamp('updated_at', {
|
|
22
|
+
withTimezone: true
|
|
23
|
+
}).notNull().defaultNow()
|
|
24
|
+
}, (table)=>[
|
|
25
|
+
uniqueIndex('integrations_sentry_installations_connection_unique').on(table.connectionId),
|
|
26
|
+
uniqueIndex('integrations_sentry_installations_installation_unique').on(table.installationUuid)
|
|
27
|
+
]);
|
|
28
|
+
export function toSentryInstallation(row) {
|
|
29
|
+
return {
|
|
30
|
+
id: row.id,
|
|
31
|
+
connectionId: row.connectionId,
|
|
32
|
+
installationUuid: row.installationUuid,
|
|
33
|
+
orgSlug: row.orgSlug,
|
|
34
|
+
status: row.status,
|
|
35
|
+
codeHash: row.codeHash,
|
|
36
|
+
installerUserId: row.installerUserId,
|
|
37
|
+
createdAt: row.createdAt,
|
|
38
|
+
updatedAt: row.updatedAt
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=installations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/db/schema/installations.ts"],"sourcesContent":["import {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {SentryInstallation} from '#db/installations.js';\nimport {pgTable} from './common.js';\n\nexport const sentryInstallations = pgTable(\n 'installations',\n {\n id: uuidv7PrimaryKey(),\n // Null until a logged-in user claims the verified install into a workspace.\n // An unclaimed install (`connection_id IS NULL`, `status='installed'`) is\n // persisted by the authoritative webhook before any browser claim arrives.\n connectionId: uuid('connection_id'),\n installationUuid: text('installation_uuid').notNull(),\n orgSlug: text('org_slug').notNull(),\n status: text('status').notNull(),\n // sha256(authorization code) of the exchange that verified this install.\n // The claim presents the code and we match the hash, so a bare uuid alone\n // cannot bind the install (IDOR guard) without storing a live credential.\n codeHash: text('code_hash'),\n installerUserId: uuid('installer_user_id'),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('integrations_sentry_installations_connection_unique').on(table.connectionId),\n uniqueIndex('integrations_sentry_installations_installation_unique').on(table.installationUuid),\n ],\n);\n\nexport type SentryInstallationDb = typeof sentryInstallations.$inferSelect;\nexport type SentryInstallationCreateDb = typeof sentryInstallations.$inferInsert;\n\nexport function toSentryInstallation(row: SentryInstallationDb): SentryInstallation {\n return {\n id: row.id,\n connectionId: row.connectionId,\n installationUuid: row.installationUuid,\n orgSlug: row.orgSlug,\n status: row.status,\n codeHash: row.codeHash,\n installerUserId: row.installerUserId,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","text","timestamp","uniqueIndex","uuid","pgTable","sentryInstallations","id","connectionId","installationUuid","notNull","orgSlug","status","codeHash","installerUserId","createdAt","withTimezone","defaultNow","updatedAt","table","on","toSentryInstallation","row"],"mappings":"AAAA,SAAQA,gBAAgB,QAAO,wBAAwB;AACvD,SAAQC,IAAI,EAAEC,SAAS,EAAEC,WAAW,EAAEC,IAAI,QAAO,sBAAsB;AAEvE,SAAQC,OAAO,QAAO,cAAc;AAEpC,OAAO,MAAMC,sBAAsBD,QACjC,iBACA;IACEE,IAAIP;IACJ,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3EQ,cAAcJ,KAAK;IACnBK,kBAAkBR,KAAK,qBAAqBS,OAAO;IACnDC,SAASV,KAAK,YAAYS,OAAO;IACjCE,QAAQX,KAAK,UAAUS,OAAO;IAC9B,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1EG,UAAUZ,KAAK;IACfa,iBAAiBV,KAAK;IACtBW,WAAWb,UAAU,cAAc;QAACc,cAAc;IAAI,GAAGN,OAAO,GAAGO,UAAU;IAC7EC,WAAWhB,UAAU,cAAc;QAACc,cAAc;IAAI,GAAGN,OAAO,GAAGO,UAAU;AAC/E,GACA,CAACE,QAAU;QACThB,YAAY,uDAAuDiB,EAAE,CAACD,MAAMX,YAAY;QACxFL,YAAY,yDAAyDiB,EAAE,CAACD,MAAMV,gBAAgB;KAC/F,EACD;AAKF,OAAO,SAASY,qBAAqBC,GAAyB;IAC5D,OAAO;QACLf,IAAIe,IAAIf,EAAE;QACVC,cAAcc,IAAId,YAAY;QAC9BC,kBAAkBa,IAAIb,gBAAgB;QACtCE,SAASW,IAAIX,OAAO;QACpBC,QAAQU,IAAIV,MAAM;QAClBC,UAAUS,IAAIT,QAAQ;QACtBC,iBAAiBQ,IAAIR,eAAe;QACpCC,WAAWO,IAAIP,SAAS;QACxBG,WAAWI,IAAIJ,SAAS;IAC1B;AACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { GetIntegrationConnectionByIdFn, PublishIntegrationEventReceivedFn, RecordDeliveryOnlyFn, UpdateIntegrationConnectionLifecycleStatusFn } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import type { ModuleWorker } from '@shipfox/node-module';
|
|
3
|
+
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
4
|
+
import { type SentryApiClient } from '#api/client.js';
|
|
5
|
+
import { closeDb, db } from '#db/db.js';
|
|
6
|
+
import { getSentryInstallationByConnectionId, persistVerifiedUnclaimedInstallation } from '#db/installations.js';
|
|
7
|
+
import { migrationsPath } from '#db/migrations.js';
|
|
8
|
+
import { type CreateSentryIntegrationRoutesOptions } from '#presentation/routes/install.js';
|
|
9
|
+
export type { SentryApiClient } from '#api/client.js';
|
|
10
|
+
export { SentryClaimProofMismatchError, SentryInstallationAlreadyLinkedError, SentryInstallationDeletedError, SentryIntegrationProviderError, SentryVerificationInProgressError, } from '#core/errors.js';
|
|
11
|
+
export type { ConnectSentryInstallationInput, VerifyAndPersistUnclaimedInstallationParams, } from '#core/install.js';
|
|
12
|
+
export { handleSentryConnect, hashAuthorizationCode, verifyAndPersistUnclaimedInstallation, } from '#core/install.js';
|
|
13
|
+
export { handleSentryInstallationCreated, handleSentryInstallationDeleted, handleSentryIssueEvent, } from '#core/webhook.js';
|
|
14
|
+
export type { PersistVerifiedUnclaimedInstallationParams, SentryInstallation, SentryInstallationStatus, UpsertSentryInstallationParams, } from '#db/installations.js';
|
|
15
|
+
export { getSentryInstallationByInstallationUuid, persistVerifiedUnclaimedInstallation, upsertSentryInstallation, } from '#db/installations.js';
|
|
16
|
+
export { closeDb, db, migrationsPath };
|
|
17
|
+
export interface CreateSentryIntegrationProviderOptions extends Omit<CreateSentryIntegrationRoutesOptions, 'sentry' | 'persistVerifiedUnclaimedInstallation'> {
|
|
18
|
+
sentry?: SentryApiClient | undefined;
|
|
19
|
+
coreDb: () => NodePgDatabase<Record<string, unknown>>;
|
|
20
|
+
publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;
|
|
21
|
+
recordDeliveryOnly: RecordDeliveryOnlyFn;
|
|
22
|
+
getIntegrationConnectionById: GetIntegrationConnectionByIdFn;
|
|
23
|
+
updateConnectionLifecycleStatus: UpdateIntegrationConnectionLifecycleStatusFn;
|
|
24
|
+
getSentryInstallationByConnectionId?: typeof getSentryInstallationByConnectionId | undefined;
|
|
25
|
+
persistVerifiedUnclaimedInstallation?: typeof persistVerifiedUnclaimedInstallation | undefined;
|
|
26
|
+
}
|
|
27
|
+
export declare function createSentryIntegrationProvider(options: CreateSentryIntegrationProviderOptions): {
|
|
28
|
+
provider: "sentry";
|
|
29
|
+
displayName: string;
|
|
30
|
+
connectionExternalUrl(connection: {
|
|
31
|
+
id: string;
|
|
32
|
+
}): Promise<string | undefined>;
|
|
33
|
+
routes: import("@shipfox/node-fastify").RouteGroup[];
|
|
34
|
+
};
|
|
35
|
+
export declare function createSentryMaintenanceWorker(): ModuleWorker;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,8BAA8B,EAC9B,iCAAiC,EACjC,oBAAoB,EACpB,4CAA4C,EAC7C,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAwB,KAAK,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAC,OAAO,EAAE,EAAE,EAAC,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,mCAAmC,EACnC,oCAAoC,EACrC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,cAAc,EAAC,MAAM,mBAAmB,CAAC;AACjD,OAAO,EACL,KAAK,oCAAoC,EAE1C,MAAM,iCAAiC,CAAC;AAKzC,YAAY,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,6BAA6B,EAC7B,oCAAoC,EACpC,8BAA8B,EAC9B,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,8BAA8B,EAC9B,2CAA2C,GAC5C,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,qCAAqC,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,EAC/B,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,0CAA0C,EAC1C,kBAAkB,EAClB,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,uCAAuC,EACvC,oCAAoC,EACpC,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,OAAO,EAAE,EAAE,EAAE,cAAc,EAAC,CAAC;AAErC,MAAM,WAAW,sCACf,SAAQ,IAAI,CACV,oCAAoC,EACpC,QAAQ,GAAG,sCAAsC,CAClD;IACD,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACrC,MAAM,EAAE,MAAM,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,+BAA+B,EAAE,iCAAiC,CAAC;IACnE,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,4BAA4B,EAAE,8BAA8B,CAAC;IAC7D,+BAA+B,EAAE,4CAA4C,CAAC;IAC9E,mCAAmC,CAAC,EAAE,OAAO,mCAAmC,GAAG,SAAS,CAAC;IAC7F,oCAAoC,CAAC,EAAE,OAAO,oCAAoC,GAAG,SAAS,CAAC;CAChG;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,sCAAsC;;;sCAUnD;QAAC,EAAE,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;;EAuBrF;AAKD,wBAAgB,6BAA6B,IAAI,YAAY,CAa5D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { createSentryApiClient } from '#api/client.js';
|
|
4
|
+
import { closeDb, db } from '#db/db.js';
|
|
5
|
+
import { getSentryInstallationByConnectionId, persistVerifiedUnclaimedInstallation } from '#db/installations.js';
|
|
6
|
+
import { migrationsPath } from '#db/migrations.js';
|
|
7
|
+
import { createSentryIntegrationRoutes } from '#presentation/routes/install.js';
|
|
8
|
+
import { createSentryWebhookRoutes } from '#presentation/routes/webhooks.js';
|
|
9
|
+
import { createSentryMaintenanceActivities } from '#temporal/activities/index.js';
|
|
10
|
+
import { SENTRY_MAINTENANCE_TASK_QUEUE } from '#temporal/constants.js';
|
|
11
|
+
export { SentryClaimProofMismatchError, SentryInstallationAlreadyLinkedError, SentryInstallationDeletedError, SentryIntegrationProviderError, SentryVerificationInProgressError } from '#core/errors.js';
|
|
12
|
+
export { handleSentryConnect, hashAuthorizationCode, verifyAndPersistUnclaimedInstallation } from '#core/install.js';
|
|
13
|
+
export { handleSentryInstallationCreated, handleSentryInstallationDeleted, handleSentryIssueEvent } from '#core/webhook.js';
|
|
14
|
+
export { getSentryInstallationByInstallationUuid, persistVerifiedUnclaimedInstallation, upsertSentryInstallation } from '#db/installations.js';
|
|
15
|
+
export { closeDb, db, migrationsPath };
|
|
16
|
+
export function createSentryIntegrationProvider(options) {
|
|
17
|
+
const sentry = options.sentry ?? createSentryApiClient();
|
|
18
|
+
const getInstallationByConnectionId = options.getSentryInstallationByConnectionId ?? getSentryInstallationByConnectionId;
|
|
19
|
+
const persistUnclaimed = options.persistVerifiedUnclaimedInstallation ?? persistVerifiedUnclaimedInstallation;
|
|
20
|
+
return {
|
|
21
|
+
provider: 'sentry',
|
|
22
|
+
displayName: 'Sentry',
|
|
23
|
+
async connectionExternalUrl (connection) {
|
|
24
|
+
const installation = await getInstallationByConnectionId(connection.id);
|
|
25
|
+
if (!installation?.orgSlug) return undefined;
|
|
26
|
+
return `https://sentry.io/organizations/${encodeURIComponent(installation.orgSlug)}/`;
|
|
27
|
+
},
|
|
28
|
+
routes: [
|
|
29
|
+
createSentryIntegrationRoutes({
|
|
30
|
+
sentry,
|
|
31
|
+
getSentryInstallation: options.getSentryInstallation,
|
|
32
|
+
getConnectionById: options.getConnectionById,
|
|
33
|
+
connectSentryInstallation: options.connectSentryInstallation,
|
|
34
|
+
persistVerifiedUnclaimedInstallation: persistUnclaimed
|
|
35
|
+
}),
|
|
36
|
+
createSentryWebhookRoutes({
|
|
37
|
+
sentry,
|
|
38
|
+
coreDb: options.coreDb,
|
|
39
|
+
publishIntegrationEventReceived: options.publishIntegrationEventReceived,
|
|
40
|
+
recordDeliveryOnly: options.recordDeliveryOnly,
|
|
41
|
+
getIntegrationConnectionById: options.getIntegrationConnectionById,
|
|
42
|
+
updateConnectionLifecycleStatus: options.updateConnectionLifecycleStatus
|
|
43
|
+
})
|
|
44
|
+
]
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
48
|
+
const maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
|
|
49
|
+
export function createSentryMaintenanceWorker() {
|
|
50
|
+
return {
|
|
51
|
+
taskQueue: SENTRY_MAINTENANCE_TASK_QUEUE,
|
|
52
|
+
workflowsPath: maintenanceWorkflowsPath,
|
|
53
|
+
activities: createSentryMaintenanceActivities,
|
|
54
|
+
workflows: [
|
|
55
|
+
{
|
|
56
|
+
name: 'pruneUnclaimedSentryInstallationsCron',
|
|
57
|
+
id: 'sentry-prune-unclaimed-installations',
|
|
58
|
+
cronSchedule: '0 4 * * *'
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport type {\n GetIntegrationConnectionByIdFn,\n PublishIntegrationEventReceivedFn,\n RecordDeliveryOnlyFn,\n UpdateIntegrationConnectionLifecycleStatusFn,\n} from '@shipfox/api-integration-core-dto';\nimport type {ModuleWorker} from '@shipfox/node-module';\nimport type {NodePgDatabase} from 'drizzle-orm/node-postgres';\nimport {createSentryApiClient, type SentryApiClient} from '#api/client.js';\nimport {closeDb, db} from '#db/db.js';\nimport {\n getSentryInstallationByConnectionId,\n persistVerifiedUnclaimedInstallation,\n} from '#db/installations.js';\nimport {migrationsPath} from '#db/migrations.js';\nimport {\n type CreateSentryIntegrationRoutesOptions,\n createSentryIntegrationRoutes,\n} from '#presentation/routes/install.js';\nimport {createSentryWebhookRoutes} from '#presentation/routes/webhooks.js';\nimport {createSentryMaintenanceActivities} from '#temporal/activities/index.js';\nimport {SENTRY_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nexport type {SentryApiClient} from '#api/client.js';\nexport {\n SentryClaimProofMismatchError,\n SentryInstallationAlreadyLinkedError,\n SentryInstallationDeletedError,\n SentryIntegrationProviderError,\n SentryVerificationInProgressError,\n} from '#core/errors.js';\nexport type {\n ConnectSentryInstallationInput,\n VerifyAndPersistUnclaimedInstallationParams,\n} from '#core/install.js';\nexport {\n handleSentryConnect,\n hashAuthorizationCode,\n verifyAndPersistUnclaimedInstallation,\n} from '#core/install.js';\nexport {\n handleSentryInstallationCreated,\n handleSentryInstallationDeleted,\n handleSentryIssueEvent,\n} from '#core/webhook.js';\nexport type {\n PersistVerifiedUnclaimedInstallationParams,\n SentryInstallation,\n SentryInstallationStatus,\n UpsertSentryInstallationParams,\n} from '#db/installations.js';\nexport {\n getSentryInstallationByInstallationUuid,\n persistVerifiedUnclaimedInstallation,\n upsertSentryInstallation,\n} from '#db/installations.js';\nexport {closeDb, db, migrationsPath};\n\nexport interface CreateSentryIntegrationProviderOptions\n extends Omit<\n CreateSentryIntegrationRoutesOptions,\n 'sentry' | 'persistVerifiedUnclaimedInstallation'\n > {\n sentry?: SentryApiClient | undefined;\n coreDb: () => NodePgDatabase<Record<string, unknown>>;\n publishIntegrationEventReceived: PublishIntegrationEventReceivedFn;\n recordDeliveryOnly: RecordDeliveryOnlyFn;\n getIntegrationConnectionById: GetIntegrationConnectionByIdFn;\n updateConnectionLifecycleStatus: UpdateIntegrationConnectionLifecycleStatusFn;\n getSentryInstallationByConnectionId?: typeof getSentryInstallationByConnectionId | undefined;\n persistVerifiedUnclaimedInstallation?: typeof persistVerifiedUnclaimedInstallation | undefined;\n}\n\nexport function createSentryIntegrationProvider(options: CreateSentryIntegrationProviderOptions) {\n const sentry = options.sentry ?? createSentryApiClient();\n const getInstallationByConnectionId =\n options.getSentryInstallationByConnectionId ?? getSentryInstallationByConnectionId;\n const persistUnclaimed =\n options.persistVerifiedUnclaimedInstallation ?? persistVerifiedUnclaimedInstallation;\n\n return {\n provider: 'sentry' as const,\n displayName: 'Sentry',\n async connectionExternalUrl(connection: {id: string}): Promise<string | undefined> {\n const installation = await getInstallationByConnectionId(connection.id);\n if (!installation?.orgSlug) return undefined;\n return `https://sentry.io/organizations/${encodeURIComponent(installation.orgSlug)}/`;\n },\n routes: [\n createSentryIntegrationRoutes({\n sentry,\n getSentryInstallation: options.getSentryInstallation,\n getConnectionById: options.getConnectionById,\n connectSentryInstallation: options.connectSentryInstallation,\n persistVerifiedUnclaimedInstallation: persistUnclaimed,\n }),\n createSentryWebhookRoutes({\n sentry,\n coreDb: options.coreDb,\n publishIntegrationEventReceived: options.publishIntegrationEventReceived,\n recordDeliveryOnly: options.recordDeliveryOnly,\n getIntegrationConnectionById: options.getIntegrationConnectionById,\n updateConnectionLifecycleStatus: options.updateConnectionLifecycleStatus,\n }),\n ],\n };\n}\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst maintenanceWorkflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nexport function createSentryMaintenanceWorker(): ModuleWorker {\n return {\n taskQueue: SENTRY_MAINTENANCE_TASK_QUEUE,\n workflowsPath: maintenanceWorkflowsPath,\n activities: createSentryMaintenanceActivities,\n workflows: [\n {\n name: 'pruneUnclaimedSentryInstallationsCron',\n id: 'sentry-prune-unclaimed-installations',\n cronSchedule: '0 4 * * *',\n },\n ],\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","createSentryApiClient","closeDb","db","getSentryInstallationByConnectionId","persistVerifiedUnclaimedInstallation","migrationsPath","createSentryIntegrationRoutes","createSentryWebhookRoutes","createSentryMaintenanceActivities","SENTRY_MAINTENANCE_TASK_QUEUE","SentryClaimProofMismatchError","SentryInstallationAlreadyLinkedError","SentryInstallationDeletedError","SentryIntegrationProviderError","SentryVerificationInProgressError","handleSentryConnect","hashAuthorizationCode","verifyAndPersistUnclaimedInstallation","handleSentryInstallationCreated","handleSentryInstallationDeleted","handleSentryIssueEvent","getSentryInstallationByInstallationUuid","upsertSentryInstallation","createSentryIntegrationProvider","options","sentry","getInstallationByConnectionId","persistUnclaimed","provider","displayName","connectionExternalUrl","connection","installation","id","orgSlug","undefined","encodeURIComponent","routes","getSentryInstallation","getConnectionById","connectSentryInstallation","coreDb","publishIntegrationEventReceived","recordDeliveryOnly","getIntegrationConnectionById","updateConnectionLifecycleStatus","packageRoot","url","maintenanceWorkflowsPath","createSentryMaintenanceWorker","taskQueue","workflowsPath","activities","workflows","name","cronSchedule"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AASvC,SAAQC,qBAAqB,QAA6B,iBAAiB;AAC3E,SAAQC,OAAO,EAAEC,EAAE,QAAO,YAAY;AACtC,SACEC,mCAAmC,EACnCC,oCAAoC,QAC/B,uBAAuB;AAC9B,SAAQC,cAAc,QAAO,oBAAoB;AACjD,SAEEC,6BAA6B,QACxB,kCAAkC;AACzC,SAAQC,yBAAyB,QAAO,mCAAmC;AAC3E,SAAQC,iCAAiC,QAAO,gCAAgC;AAChF,SAAQC,6BAA6B,QAAO,yBAAyB;AAGrE,SACEC,6BAA6B,EAC7BC,oCAAoC,EACpCC,8BAA8B,EAC9BC,8BAA8B,EAC9BC,iCAAiC,QAC5B,kBAAkB;AAKzB,SACEC,mBAAmB,EACnBC,qBAAqB,EACrBC,qCAAqC,QAChC,mBAAmB;AAC1B,SACEC,+BAA+B,EAC/BC,+BAA+B,EAC/BC,sBAAsB,QACjB,mBAAmB;AAO1B,SACEC,uCAAuC,EACvCjB,oCAAoC,EACpCkB,wBAAwB,QACnB,uBAAuB;AAC9B,SAAQrB,OAAO,EAAEC,EAAE,EAAEG,cAAc,GAAE;AAiBrC,OAAO,SAASkB,gCAAgCC,OAA+C;IAC7F,MAAMC,SAASD,QAAQC,MAAM,IAAIzB;IACjC,MAAM0B,gCACJF,QAAQrB,mCAAmC,IAAIA;IACjD,MAAMwB,mBACJH,QAAQpB,oCAAoC,IAAIA;IAElD,OAAO;QACLwB,UAAU;QACVC,aAAa;QACb,MAAMC,uBAAsBC,UAAwB;YAClD,MAAMC,eAAe,MAAMN,8BAA8BK,WAAWE,EAAE;YACtE,IAAI,CAACD,cAAcE,SAAS,OAAOC;YACnC,OAAO,CAAC,gCAAgC,EAAEC,mBAAmBJ,aAAaE,OAAO,EAAE,CAAC,CAAC;QACvF;QACAG,QAAQ;YACN/B,8BAA8B;gBAC5BmB;gBACAa,uBAAuBd,QAAQc,qBAAqB;gBACpDC,mBAAmBf,QAAQe,iBAAiB;gBAC5CC,2BAA2BhB,QAAQgB,yBAAyB;gBAC5DpC,sCAAsCuB;YACxC;YACApB,0BAA0B;gBACxBkB;gBACAgB,QAAQjB,QAAQiB,MAAM;gBACtBC,iCAAiClB,QAAQkB,+BAA+B;gBACxEC,oBAAoBnB,QAAQmB,kBAAkB;gBAC9CC,8BAA8BpB,QAAQoB,4BAA4B;gBAClEC,iCAAiCrB,QAAQqB,+BAA+B;YAC1E;SACD;IACH;AACF;AAEA,MAAMC,cAAchD,QAAQD,QAAQE,cAAc,YAAYgD,GAAG,IAAI;AACrE,MAAMC,2BAA2BlD,QAAQgD,aAAa;AAEtD,OAAO,SAASG;IACd,OAAO;QACLC,WAAWzC;QACX0C,eAAeH;QACfI,YAAY5C;QACZ6C,WAAW;YACT;gBACEC,MAAM;gBACNrB,IAAI;gBACJsB,cAAc;YAChB;SACD;IACH;AACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type IntegrationConnection } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
export declare function toIntegrationConnectionDto(connection: IntegrationConnection<'sentry'>): {
|
|
3
|
+
created_at: string;
|
|
4
|
+
updated_at: string;
|
|
5
|
+
external_url?: string;
|
|
6
|
+
id: string;
|
|
7
|
+
workspace_id: string;
|
|
8
|
+
provider: string;
|
|
9
|
+
external_account_id: string;
|
|
10
|
+
slug: string;
|
|
11
|
+
display_name: string;
|
|
12
|
+
lifecycle_status: import("@shipfox/api-integration-core-dto").IntegrationConnectionLifecycleStatus;
|
|
13
|
+
capabilities: import("@shipfox/api-integration-core-dto").IntegrationCapability[];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=integrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/integrations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAE3B,MAAM,mCAAmC,CAAC;AAG3C,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,qBAAqB,CAAC,QAAQ,CAAC;;;;;;;;;;;;EAErF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { toIntegrationConnectionDto as toCoreIntegrationConnectionDto } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
// Sentry exposes no adapters, so its connections carry no capabilities.
|
|
3
|
+
export function toIntegrationConnectionDto(connection) {
|
|
4
|
+
return toCoreIntegrationConnectionDto(connection, {
|
|
5
|
+
capabilities: []
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=integrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/dto/integrations.ts"],"sourcesContent":["import {\n type IntegrationConnection,\n toIntegrationConnectionDto as toCoreIntegrationConnectionDto,\n} from '@shipfox/api-integration-core-dto';\n\n// Sentry exposes no adapters, so its connections carry no capabilities.\nexport function toIntegrationConnectionDto(connection: IntegrationConnection<'sentry'>) {\n return toCoreIntegrationConnectionDto(connection, {capabilities: []});\n}\n"],"names":["toIntegrationConnectionDto","toCoreIntegrationConnectionDto","connection","capabilities"],"mappings":"AAAA,SAEEA,8BAA8BC,8BAA8B,QACvD,oCAAoC;AAE3C,wEAAwE;AACxE,OAAO,SAASD,2BAA2BE,UAA2C;IACpF,OAAOD,+BAA+BC,YAAY;QAACC,cAAc,EAAE;IAAA;AACrE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/errors.ts"],"names":[],"mappings":"AAmBA,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CA4B7D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ConnectionSlugConflictError } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { ClientError } from '@shipfox/node-fastify';
|
|
3
|
+
import { SentryClaimProofMismatchError, SentryInstallationAlreadyLinkedError, SentryInstallationDeletedError, SentryIntegrationProviderError, SentryVerificationInProgressError } from '#core/errors.js';
|
|
4
|
+
function providerStatus(reason) {
|
|
5
|
+
if (reason === 'rate-limited') return 429;
|
|
6
|
+
if (reason === 'timeout' || reason === 'provider-unavailable') return 503;
|
|
7
|
+
return 422;
|
|
8
|
+
}
|
|
9
|
+
export function sentryRouteErrorHandler(error) {
|
|
10
|
+
if (error instanceof SentryInstallationAlreadyLinkedError) {
|
|
11
|
+
throw new ClientError(error.message, 'sentry-installation-already-linked', {
|
|
12
|
+
status: 409
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
if (error instanceof SentryInstallationDeletedError) {
|
|
16
|
+
throw new ClientError(error.message, 'sentry-installation-deleted', {
|
|
17
|
+
status: 409
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (error instanceof SentryClaimProofMismatchError) {
|
|
21
|
+
throw new ClientError(error.message, 'sentry-claim-proof-mismatch', {
|
|
22
|
+
status: 403
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (error instanceof ConnectionSlugConflictError) {
|
|
26
|
+
throw new ClientError(error.message, 'slug-conflict', {
|
|
27
|
+
status: 409
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (error instanceof SentryVerificationInProgressError) {
|
|
31
|
+
// Retryable: a concurrent webhook is mid-exchange. 503 + retry_after lands in
|
|
32
|
+
// the client backoff that already treats >= 500 as retryable.
|
|
33
|
+
throw new ClientError(error.message, 'sentry-verification-in-progress', {
|
|
34
|
+
status: 503,
|
|
35
|
+
details: {
|
|
36
|
+
retry_after_seconds: error.retryAfterSeconds
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (error instanceof SentryIntegrationProviderError) {
|
|
41
|
+
throw new ClientError(error.message, error.reason, {
|
|
42
|
+
details: {
|
|
43
|
+
retry_after_seconds: error.retryAfterSeconds
|
|
44
|
+
},
|
|
45
|
+
status: providerStatus(error.reason)
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/errors.ts"],"sourcesContent":["import {\n ConnectionSlugConflictError,\n type IntegrationProviderErrorReason,\n} from '@shipfox/api-integration-core-dto';\nimport {ClientError} from '@shipfox/node-fastify';\nimport {\n SentryClaimProofMismatchError,\n SentryInstallationAlreadyLinkedError,\n SentryInstallationDeletedError,\n SentryIntegrationProviderError,\n SentryVerificationInProgressError,\n} from '#core/errors.js';\n\nfunction providerStatus(reason: IntegrationProviderErrorReason): number {\n if (reason === 'rate-limited') return 429;\n if (reason === 'timeout' || reason === 'provider-unavailable') return 503;\n return 422;\n}\n\nexport function sentryRouteErrorHandler(error: unknown): never {\n if (error instanceof SentryInstallationAlreadyLinkedError) {\n throw new ClientError(error.message, 'sentry-installation-already-linked', {status: 409});\n }\n if (error instanceof SentryInstallationDeletedError) {\n throw new ClientError(error.message, 'sentry-installation-deleted', {status: 409});\n }\n if (error instanceof SentryClaimProofMismatchError) {\n throw new ClientError(error.message, 'sentry-claim-proof-mismatch', {status: 403});\n }\n if (error instanceof ConnectionSlugConflictError) {\n throw new ClientError(error.message, 'slug-conflict', {status: 409});\n }\n if (error instanceof SentryVerificationInProgressError) {\n // Retryable: a concurrent webhook is mid-exchange. 503 + retry_after lands in\n // the client backoff that already treats >= 500 as retryable.\n throw new ClientError(error.message, 'sentry-verification-in-progress', {\n status: 503,\n details: {retry_after_seconds: error.retryAfterSeconds},\n });\n }\n if (error instanceof SentryIntegrationProviderError) {\n throw new ClientError(error.message, error.reason, {\n details: {retry_after_seconds: error.retryAfterSeconds},\n status: providerStatus(error.reason),\n });\n }\n throw error;\n}\n"],"names":["ConnectionSlugConflictError","ClientError","SentryClaimProofMismatchError","SentryInstallationAlreadyLinkedError","SentryInstallationDeletedError","SentryIntegrationProviderError","SentryVerificationInProgressError","providerStatus","reason","sentryRouteErrorHandler","error","message","status","details","retry_after_seconds","retryAfterSeconds"],"mappings":"AAAA,SACEA,2BAA2B,QAEtB,oCAAoC;AAC3C,SAAQC,WAAW,QAAO,wBAAwB;AAClD,SACEC,6BAA6B,EAC7BC,oCAAoC,EACpCC,8BAA8B,EAC9BC,8BAA8B,EAC9BC,iCAAiC,QAC5B,kBAAkB;AAEzB,SAASC,eAAeC,MAAsC;IAC5D,IAAIA,WAAW,gBAAgB,OAAO;IACtC,IAAIA,WAAW,aAAaA,WAAW,wBAAwB,OAAO;IACtE,OAAO;AACT;AAEA,OAAO,SAASC,wBAAwBC,KAAc;IACpD,IAAIA,iBAAiBP,sCAAsC;QACzD,MAAM,IAAIF,YAAYS,MAAMC,OAAO,EAAE,sCAAsC;YAACC,QAAQ;QAAG;IACzF;IACA,IAAIF,iBAAiBN,gCAAgC;QACnD,MAAM,IAAIH,YAAYS,MAAMC,OAAO,EAAE,+BAA+B;YAACC,QAAQ;QAAG;IAClF;IACA,IAAIF,iBAAiBR,+BAA+B;QAClD,MAAM,IAAID,YAAYS,MAAMC,OAAO,EAAE,+BAA+B;YAACC,QAAQ;QAAG;IAClF;IACA,IAAIF,iBAAiBV,6BAA6B;QAChD,MAAM,IAAIC,YAAYS,MAAMC,OAAO,EAAE,iBAAiB;YAACC,QAAQ;QAAG;IACpE;IACA,IAAIF,iBAAiBJ,mCAAmC;QACtD,8EAA8E;QAC9E,8DAA8D;QAC9D,MAAM,IAAIL,YAAYS,MAAMC,OAAO,EAAE,mCAAmC;YACtEC,QAAQ;YACRC,SAAS;gBAACC,qBAAqBJ,MAAMK,iBAAiB;YAAA;QACxD;IACF;IACA,IAAIL,iBAAiBL,gCAAgC;QACnD,MAAM,IAAIJ,YAAYS,MAAMC,OAAO,EAAED,MAAMF,MAAM,EAAE;YACjDK,SAAS;gBAACC,qBAAqBJ,MAAMK,iBAAiB;YAAA;YACtDH,QAAQL,eAAeG,MAAMF,MAAM;QACrC;IACF;IACA,MAAME;AACR"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IntegrationConnection } from '@shipfox/api-integration-core-dto';
|
|
2
|
+
import { type RouteGroup } from '@shipfox/node-fastify';
|
|
3
|
+
import type { SentryApiClient } from '#api/client.js';
|
|
4
|
+
import { type ConnectSentryInstallationInput } from '#core/install.js';
|
|
5
|
+
import type { PersistVerifiedUnclaimedInstallationParams, SentryInstallation } from '#db/installations.js';
|
|
6
|
+
export interface CreateSentryIntegrationRoutesOptions {
|
|
7
|
+
sentry: SentryApiClient;
|
|
8
|
+
getSentryInstallation: (input: {
|
|
9
|
+
installationUuid: string;
|
|
10
|
+
}) => Promise<SentryInstallation | undefined>;
|
|
11
|
+
getConnectionById: (id: string) => Promise<IntegrationConnection<'sentry'> | undefined>;
|
|
12
|
+
connectSentryInstallation: (input: ConnectSentryInstallationInput) => Promise<IntegrationConnection<'sentry'>>;
|
|
13
|
+
persistVerifiedUnclaimedInstallation: (input: PersistVerifiedUnclaimedInstallationParams) => Promise<SentryInstallation>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createSentryIntegrationRoutes({ sentry, getSentryInstallation, getConnectionById, connectSentryInstallation, persistVerifiedUnclaimedInstallation, }: CreateSentryIntegrationRoutesOptions): RouteGroup;
|
|
16
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,mCAAmC,CAAC;AAO7E,OAAO,EAAc,KAAK,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAC,KAAK,8BAA8B,EAAsB,MAAM,kBAAkB,CAAC;AAC1F,OAAO,KAAK,EACV,0CAA0C,EAC1C,kBAAkB,EACnB,MAAM,sBAAsB,CAAC;AAI9B,MAAM,WAAW,oCAAoC;IACnD,MAAM,EAAE,eAAe,CAAC;IACxB,qBAAqB,EAAE,CAAC,KAAK,EAAE;QAC7B,gBAAgB,EAAE,MAAM,CAAC;KAC1B,KAAK,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAC9C,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;IACxF,yBAAyB,EAAE,CACzB,KAAK,EAAE,8BAA8B,KAClC,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,oCAAoC,EAAE,CACpC,KAAK,EAAE,0CAA0C,KAC9C,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAClC;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,MAAM,EACN,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,EACzB,oCAAoC,GACrC,EAAE,oCAAoC,GAAG,UAAU,CA8DnD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AUTH_USER, requireUserContext, requireWorkspaceAccess } from '@shipfox/api-auth-context';
|
|
2
|
+
import { createSentryInstallBodySchema, createSentryInstallResponseSchema, sentryConnectBodySchema, sentryConnectResponseSchema } from '@shipfox/api-integration-sentry-dto';
|
|
3
|
+
import { defineRoute } from '@shipfox/node-fastify';
|
|
4
|
+
import { config } from '#config.js';
|
|
5
|
+
import { handleSentryConnect } from '#core/install.js';
|
|
6
|
+
import { toIntegrationConnectionDto } from '#presentation/dto/integrations.js';
|
|
7
|
+
import { sentryRouteErrorHandler } from './errors.js';
|
|
8
|
+
export function createSentryIntegrationRoutes({ sentry, getSentryInstallation, getConnectionById, connectSentryInstallation, persistVerifiedUnclaimedInstallation }) {
|
|
9
|
+
const createInstallRoute = defineRoute({
|
|
10
|
+
method: 'POST',
|
|
11
|
+
path: '/install',
|
|
12
|
+
auth: AUTH_USER,
|
|
13
|
+
description: 'Create a Sentry app external-install URL for a workspace.',
|
|
14
|
+
schema: {
|
|
15
|
+
body: createSentryInstallBodySchema,
|
|
16
|
+
response: {
|
|
17
|
+
200: createSentryInstallResponseSchema
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
handler: (request)=>{
|
|
21
|
+
const { workspace_id: workspaceId } = request.body;
|
|
22
|
+
requireWorkspaceAccess({
|
|
23
|
+
request,
|
|
24
|
+
workspaceId
|
|
25
|
+
});
|
|
26
|
+
// Sentry has no state param to embed; the server owns the slug.
|
|
27
|
+
const installUrl = `https://sentry.io/sentry-apps/${config.SENTRY_APP_SLUG}/external-install/`;
|
|
28
|
+
return {
|
|
29
|
+
install_url: installUrl
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const connectRoute = defineRoute({
|
|
34
|
+
method: 'POST',
|
|
35
|
+
path: '/connect',
|
|
36
|
+
auth: AUTH_USER,
|
|
37
|
+
description: 'Link a Sentry installation to a workspace after the install redirect.',
|
|
38
|
+
schema: {
|
|
39
|
+
body: sentryConnectBodySchema,
|
|
40
|
+
response: {
|
|
41
|
+
200: sentryConnectResponseSchema
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
errorHandler: sentryRouteErrorHandler,
|
|
45
|
+
handler: async (request)=>{
|
|
46
|
+
const { workspace_id: workspaceId, code, installation_id: installationUuid } = request.body;
|
|
47
|
+
const actor = requireUserContext(request);
|
|
48
|
+
requireWorkspaceAccess({
|
|
49
|
+
request,
|
|
50
|
+
workspaceId
|
|
51
|
+
});
|
|
52
|
+
const connection = await handleSentryConnect({
|
|
53
|
+
sentry,
|
|
54
|
+
workspaceId,
|
|
55
|
+
code,
|
|
56
|
+
installationUuid,
|
|
57
|
+
installerUserId: actor.userId,
|
|
58
|
+
verifyInstall: config.SENTRY_APP_VERIFY_INSTALL,
|
|
59
|
+
getSentryInstallation,
|
|
60
|
+
getConnectionById,
|
|
61
|
+
connectSentryInstallation,
|
|
62
|
+
persistVerifiedUnclaimedInstallation
|
|
63
|
+
});
|
|
64
|
+
return toIntegrationConnectionDto(connection);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
prefix: '/integrations/sentry',
|
|
69
|
+
routes: [
|
|
70
|
+
createInstallRoute,
|
|
71
|
+
connectRoute
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/install.ts"],"sourcesContent":["import {AUTH_USER, requireUserContext, requireWorkspaceAccess} from '@shipfox/api-auth-context';\nimport type {IntegrationConnection} from '@shipfox/api-integration-core-dto';\nimport {\n createSentryInstallBodySchema,\n createSentryInstallResponseSchema,\n sentryConnectBodySchema,\n sentryConnectResponseSchema,\n} from '@shipfox/api-integration-sentry-dto';\nimport {defineRoute, type RouteGroup} from '@shipfox/node-fastify';\nimport type {SentryApiClient} from '#api/client.js';\nimport {config} from '#config.js';\nimport {type ConnectSentryInstallationInput, handleSentryConnect} from '#core/install.js';\nimport type {\n PersistVerifiedUnclaimedInstallationParams,\n SentryInstallation,\n} from '#db/installations.js';\nimport {toIntegrationConnectionDto} from '#presentation/dto/integrations.js';\nimport {sentryRouteErrorHandler} from './errors.js';\n\nexport interface CreateSentryIntegrationRoutesOptions {\n sentry: SentryApiClient;\n getSentryInstallation: (input: {\n installationUuid: string;\n }) => Promise<SentryInstallation | undefined>;\n getConnectionById: (id: string) => Promise<IntegrationConnection<'sentry'> | undefined>;\n connectSentryInstallation: (\n input: ConnectSentryInstallationInput,\n ) => Promise<IntegrationConnection<'sentry'>>;\n persistVerifiedUnclaimedInstallation: (\n input: PersistVerifiedUnclaimedInstallationParams,\n ) => Promise<SentryInstallation>;\n}\n\nexport function createSentryIntegrationRoutes({\n sentry,\n getSentryInstallation,\n getConnectionById,\n connectSentryInstallation,\n persistVerifiedUnclaimedInstallation,\n}: CreateSentryIntegrationRoutesOptions): RouteGroup {\n const createInstallRoute = defineRoute({\n method: 'POST',\n path: '/install',\n auth: AUTH_USER,\n description: 'Create a Sentry app external-install URL for a workspace.',\n schema: {\n body: createSentryInstallBodySchema,\n response: {\n 200: createSentryInstallResponseSchema,\n },\n },\n handler: (request) => {\n const {workspace_id: workspaceId} = request.body;\n\n requireWorkspaceAccess({request, workspaceId});\n\n // Sentry has no state param to embed; the server owns the slug.\n const installUrl = `https://sentry.io/sentry-apps/${config.SENTRY_APP_SLUG}/external-install/`;\n return {install_url: installUrl};\n },\n });\n\n const connectRoute = defineRoute({\n method: 'POST',\n path: '/connect',\n auth: AUTH_USER,\n description: 'Link a Sentry installation to a workspace after the install redirect.',\n schema: {\n body: sentryConnectBodySchema,\n response: {\n 200: sentryConnectResponseSchema,\n },\n },\n errorHandler: sentryRouteErrorHandler,\n handler: async (request) => {\n const {workspace_id: workspaceId, code, installation_id: installationUuid} = request.body;\n const actor = requireUserContext(request);\n\n requireWorkspaceAccess({request, workspaceId});\n\n const connection = await handleSentryConnect({\n sentry,\n workspaceId,\n code,\n installationUuid,\n installerUserId: actor.userId,\n verifyInstall: config.SENTRY_APP_VERIFY_INSTALL,\n getSentryInstallation,\n getConnectionById,\n connectSentryInstallation,\n persistVerifiedUnclaimedInstallation,\n });\n\n return toIntegrationConnectionDto(connection);\n },\n });\n\n return {\n prefix: '/integrations/sentry',\n routes: [createInstallRoute, connectRoute],\n };\n}\n"],"names":["AUTH_USER","requireUserContext","requireWorkspaceAccess","createSentryInstallBodySchema","createSentryInstallResponseSchema","sentryConnectBodySchema","sentryConnectResponseSchema","defineRoute","config","handleSentryConnect","toIntegrationConnectionDto","sentryRouteErrorHandler","createSentryIntegrationRoutes","sentry","getSentryInstallation","getConnectionById","connectSentryInstallation","persistVerifiedUnclaimedInstallation","createInstallRoute","method","path","auth","description","schema","body","response","handler","request","workspace_id","workspaceId","installUrl","SENTRY_APP_SLUG","install_url","connectRoute","errorHandler","code","installation_id","installationUuid","actor","connection","installerUserId","userId","verifyInstall","SENTRY_APP_VERIFY_INSTALL","prefix","routes"],"mappings":"AAAA,SAAQA,SAAS,EAAEC,kBAAkB,EAAEC,sBAAsB,QAAO,4BAA4B;AAEhG,SACEC,6BAA6B,EAC7BC,iCAAiC,EACjCC,uBAAuB,EACvBC,2BAA2B,QACtB,sCAAsC;AAC7C,SAAQC,WAAW,QAAwB,wBAAwB;AAEnE,SAAQC,MAAM,QAAO,aAAa;AAClC,SAA6CC,mBAAmB,QAAO,mBAAmB;AAK1F,SAAQC,0BAA0B,QAAO,oCAAoC;AAC7E,SAAQC,uBAAuB,QAAO,cAAc;AAgBpD,OAAO,SAASC,8BAA8B,EAC5CC,MAAM,EACNC,qBAAqB,EACrBC,iBAAiB,EACjBC,yBAAyB,EACzBC,oCAAoC,EACC;IACrC,MAAMC,qBAAqBX,YAAY;QACrCY,QAAQ;QACRC,MAAM;QACNC,MAAMrB;QACNsB,aAAa;QACbC,QAAQ;YACNC,MAAMrB;YACNsB,UAAU;gBACR,KAAKrB;YACP;QACF;QACAsB,SAAS,CAACC;YACR,MAAM,EAACC,cAAcC,WAAW,EAAC,GAAGF,QAAQH,IAAI;YAEhDtB,uBAAuB;gBAACyB;gBAASE;YAAW;YAE5C,gEAAgE;YAChE,MAAMC,aAAa,CAAC,8BAA8B,EAAEtB,OAAOuB,eAAe,CAAC,kBAAkB,CAAC;YAC9F,OAAO;gBAACC,aAAaF;YAAU;QACjC;IACF;IAEA,MAAMG,eAAe1B,YAAY;QAC/BY,QAAQ;QACRC,MAAM;QACNC,MAAMrB;QACNsB,aAAa;QACbC,QAAQ;YACNC,MAAMnB;YACNoB,UAAU;gBACR,KAAKnB;YACP;QACF;QACA4B,cAAcvB;QACde,SAAS,OAAOC;YACd,MAAM,EAACC,cAAcC,WAAW,EAAEM,IAAI,EAAEC,iBAAiBC,gBAAgB,EAAC,GAAGV,QAAQH,IAAI;YACzF,MAAMc,QAAQrC,mBAAmB0B;YAEjCzB,uBAAuB;gBAACyB;gBAASE;YAAW;YAE5C,MAAMU,aAAa,MAAM9B,oBAAoB;gBAC3CI;gBACAgB;gBACAM;gBACAE;gBACAG,iBAAiBF,MAAMG,MAAM;gBAC7BC,eAAelC,OAAOmC,yBAAyB;gBAC/C7B;gBACAC;gBACAC;gBACAC;YACF;YAEA,OAAOP,2BAA2B6B;QACpC;IACF;IAEA,OAAO;QACLK,QAAQ;QACRC,QAAQ;YAAC3B;YAAoBe;SAAa;IAC5C;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FastifyReply } from 'fastify';
|
|
2
|
+
import type { SentryWebhookContext } from './webhook-context.js';
|
|
3
|
+
export declare function handleInstallationResource(args: {
|
|
4
|
+
context: SentryWebhookContext;
|
|
5
|
+
reply: FastifyReply;
|
|
6
|
+
deliveryId: string;
|
|
7
|
+
rawBody: string;
|
|
8
|
+
}): Promise<null>;
|
|
9
|
+
//# sourceMappingURL=installation-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installation-handler.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/installation-handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,SAAS,CAAC;AAO1C,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AAQ/D,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB"}
|