@abyss-project/probe 2.0.0 → 2.0.1
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/.eslintrc.js +32 -32
- package/.prettierrc +5 -5
- package/README.md +22 -22
- package/package.json +10 -15
- package/src/api/index.ts +6 -6
- package/src/api/probe-scan.api.test.ts +47 -47
- package/src/api/probe-scan.api.ts +203 -203
- package/src/api/probe-scan.application.api.test.ts +35 -35
- package/src/api/probe-scan.application.api.ts +157 -157
- package/src/api/probe-usage.api.ts +47 -47
- package/src/api/probe-usage.application.api.ts +25 -25
- package/src/api/probe-webhook.api.test.ts +17 -17
- package/src/api/probe-webhook.api.ts +119 -119
- package/src/api/probe-webhook.application.api.test.ts +18 -18
- package/src/api/probe-webhook.application.api.ts +141 -141
- package/src/constants/index.ts +1 -1
- package/src/index.ts +205 -205
- package/src/types/enum/api-error.enum.ts +33 -33
- package/src/types/enum/index.ts +2 -2
- package/src/types/enum/probe-scan.enum.ts +44 -44
- package/src/types/index.ts +2 -2
- package/src/types/interface/api/index.ts +5 -5
- package/src/types/interface/api/requests/index.ts +3 -3
- package/src/types/interface/api/requests/probe-scan.request.ts +54 -54
- package/src/types/interface/api/requests/probe-usage.request.ts +7 -7
- package/src/types/interface/api/requests/probe-webhook.request.ts +33 -33
- package/src/types/interface/api/responses/index.ts +3 -3
- package/src/types/interface/api/responses/probe-scan.response.ts +45 -45
- package/src/types/interface/api/responses/probe-usage.response.ts +25 -25
- package/src/types/interface/api/responses/probe-webhook.response.ts +24 -24
- package/src/types/interface/api/type-message/api-error.ts +7 -7
- package/src/types/interface/api/type-message/base-paginate.ts +11 -11
- package/src/types/interface/api/type-message/response.ts +6 -6
- package/src/types/interface/index.ts +2 -2
- package/src/types/interface/models/index.ts +3 -3
- package/src/types/interface/models/probe-scan.dto.ts +67 -67
- package/src/types/interface/models/probe-webhook-delivery.dto.ts +73 -73
- package/src/types/interface/models/probe-webhook.dto.ts +29 -29
- package/src/types/tests/probe.dto.test.ts +156 -156
- package/src/utils/enum.utils.ts +1 -1
- package/src/utils/error.utils.ts +30 -30
- package/src/utils/index.ts +4 -4
- package/src/utils/probe-scan-cost.utils.ts +101 -101
- package/src/utils/probe-webhook-signature.utils.ts +56 -56
- package/tsconfig.check.json +15 -15
- package/tsconfig.json +36 -36
|
@@ -1,119 +1,119 @@
|
|
|
1
|
-
// ──────────────────────────────────────────────
|
|
2
|
-
// AbyssProbe webhook subscription API — CRUD over registered `probe_webhooks`
|
|
3
|
-
// (create / list / delete / update, + paginated delivery history — mirrors
|
|
4
|
-
// apps/api/src/api/controllers/probe-webhook.controller.ts EXACTLY, see that
|
|
5
|
-
// file's header comment). No `probe/` path prefix — `@Controller({
|
|
6
|
-
// prefixPath: '/webhook' })` mounts directly at `webhook`.
|
|
7
|
-
//
|
|
8
|
-
// See probe-webhook.application.api.ts for the application/API-key-auth
|
|
9
|
-
// counterpart of this client (`/application/:applicationId/webhook...`,
|
|
10
|
-
// Phase 3a) — it reuses every request/response type verbatim; only the URL
|
|
11
|
-
// prefix, the extra `applicationId` argument, and the auth header differ.
|
|
12
|
-
// ──────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
import { AbyssProbeCore } from '..';
|
|
15
|
-
import type {
|
|
16
|
-
ICreateProbeWebhookBody,
|
|
17
|
-
IUpdateProbeWebhookBody,
|
|
18
|
-
IProbeWebhookScopeQuery,
|
|
19
|
-
IListProbeWebhookDeliveriesQuery,
|
|
20
|
-
ICreateProbeWebhookResponse,
|
|
21
|
-
IListProbeWebhookResponse,
|
|
22
|
-
IDeleteProbeWebhookResponse,
|
|
23
|
-
IUpdateProbeWebhookResponse,
|
|
24
|
-
IListProbeWebhookDeliveriesResponse,
|
|
25
|
-
} from '../types';
|
|
26
|
-
|
|
27
|
-
const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
|
|
28
|
-
|
|
29
|
-
function authHeader(apiKey?: string): Record<string, string> {
|
|
30
|
-
return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Renames `organizationId` to the wire's `organization_id` (see probe-scan.api.ts). */
|
|
34
|
-
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
35
|
-
const out: Record<string, unknown> = {};
|
|
36
|
-
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
37
|
-
if (value === undefined || value === null) continue;
|
|
38
|
-
const wireKey = key === 'organizationId' ? 'organization_id' : key;
|
|
39
|
-
out[wireKey] = value instanceof Date ? value.toISOString() : value;
|
|
40
|
-
}
|
|
41
|
-
return out;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* `POST /webhook` — register a callbackUrl for the caller's scope. The
|
|
46
|
-
* response's `secret` field (HMAC signing secret) is returned ONLY here —
|
|
47
|
-
* store it immediately, it cannot be re-revealed later.
|
|
48
|
-
*/
|
|
49
|
-
export const createProbeWebhook = async (
|
|
50
|
-
body: ICreateProbeWebhookBody,
|
|
51
|
-
scope: IProbeWebhookScopeQuery = {},
|
|
52
|
-
apiKey?: string,
|
|
53
|
-
): Promise<ICreateProbeWebhookResponse> =>
|
|
54
|
-
(
|
|
55
|
-
await AbyssProbeCore.axios.post<ICreateProbeWebhookResponse>('webhook', body, {
|
|
56
|
-
params: serializeProbeQuery(scope),
|
|
57
|
-
headers: authHeader(apiKey),
|
|
58
|
-
})
|
|
59
|
-
).data;
|
|
60
|
-
|
|
61
|
-
/** `GET /webhook` — flat, scope-filtered list (not paginated — bounded by WEBHOOK_MAX_PER_SCOPE server-side). */
|
|
62
|
-
export const listProbeWebhook = async (
|
|
63
|
-
scope: IProbeWebhookScopeQuery = {},
|
|
64
|
-
apiKey?: string,
|
|
65
|
-
): Promise<IListProbeWebhookResponse> =>
|
|
66
|
-
(
|
|
67
|
-
await AbyssProbeCore.axios.get<IListProbeWebhookResponse>('webhook', {
|
|
68
|
-
params: serializeProbeQuery(scope),
|
|
69
|
-
headers: authHeader(apiKey),
|
|
70
|
-
})
|
|
71
|
-
).data;
|
|
72
|
-
|
|
73
|
-
/** `DELETE /webhook/:webhookId`. */
|
|
74
|
-
export const deleteProbeWebhook = async (
|
|
75
|
-
webhookId: string,
|
|
76
|
-
scope: IProbeWebhookScopeQuery = {},
|
|
77
|
-
apiKey?: string,
|
|
78
|
-
): Promise<IDeleteProbeWebhookResponse> =>
|
|
79
|
-
(
|
|
80
|
-
await AbyssProbeCore.axios.delete<IDeleteProbeWebhookResponse>(`webhook/${webhookId}`, {
|
|
81
|
-
params: serializeProbeQuery(scope),
|
|
82
|
-
headers: authHeader(apiKey),
|
|
83
|
-
})
|
|
84
|
-
).data;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* `PATCH /webhook/:webhookId` (WS5-5) — edit `callbackUrl` and/or `active`.
|
|
88
|
-
* At least one field is required. Scoped like {@link deleteProbeWebhook}
|
|
89
|
-
* (404, never 403, for a webhookId outside the resolved scope). The response
|
|
90
|
-
* includes `secret` — re-displayable now, see {@link IProbeWebhook}.
|
|
91
|
-
*/
|
|
92
|
-
export const updateProbeWebhook = async (
|
|
93
|
-
webhookId: string,
|
|
94
|
-
body: IUpdateProbeWebhookBody,
|
|
95
|
-
scope: IProbeWebhookScopeQuery = {},
|
|
96
|
-
apiKey?: string,
|
|
97
|
-
): Promise<IUpdateProbeWebhookResponse> =>
|
|
98
|
-
(
|
|
99
|
-
await AbyssProbeCore.axios.patch<IUpdateProbeWebhookResponse>(`webhook/${webhookId}`, body, {
|
|
100
|
-
params: serializeProbeQuery(scope),
|
|
101
|
-
headers: authHeader(apiKey),
|
|
102
|
-
})
|
|
103
|
-
).data;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* `GET /webhook/:webhookId/deliveries` (WS5-6) — paginated delivery-attempt
|
|
107
|
-
* history for one registered webhook. Scoped like {@link deleteProbeWebhook}.
|
|
108
|
-
*/
|
|
109
|
-
export const listProbeWebhookDeliveries = async (
|
|
110
|
-
webhookId: string,
|
|
111
|
-
query: IListProbeWebhookDeliveriesQuery = {},
|
|
112
|
-
apiKey?: string,
|
|
113
|
-
): Promise<IListProbeWebhookDeliveriesResponse> =>
|
|
114
|
-
(
|
|
115
|
-
await AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
116
|
-
`webhook/${webhookId}/deliveries`,
|
|
117
|
-
{ params: serializeProbeQuery(query), headers: authHeader(apiKey) },
|
|
118
|
-
)
|
|
119
|
-
).data;
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// AbyssProbe webhook subscription API — CRUD over registered `probe_webhooks`
|
|
3
|
+
// (create / list / delete / update, + paginated delivery history — mirrors
|
|
4
|
+
// apps/api/src/api/controllers/probe-webhook.controller.ts EXACTLY, see that
|
|
5
|
+
// file's header comment). No `probe/` path prefix — `@Controller({
|
|
6
|
+
// prefixPath: '/webhook' })` mounts directly at `webhook`.
|
|
7
|
+
//
|
|
8
|
+
// See probe-webhook.application.api.ts for the application/API-key-auth
|
|
9
|
+
// counterpart of this client (`/application/:applicationId/webhook...`,
|
|
10
|
+
// Phase 3a) — it reuses every request/response type verbatim; only the URL
|
|
11
|
+
// prefix, the extra `applicationId` argument, and the auth header differ.
|
|
12
|
+
// ──────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
import { AbyssProbeCore } from '..';
|
|
15
|
+
import type {
|
|
16
|
+
ICreateProbeWebhookBody,
|
|
17
|
+
IUpdateProbeWebhookBody,
|
|
18
|
+
IProbeWebhookScopeQuery,
|
|
19
|
+
IListProbeWebhookDeliveriesQuery,
|
|
20
|
+
ICreateProbeWebhookResponse,
|
|
21
|
+
IListProbeWebhookResponse,
|
|
22
|
+
IDeleteProbeWebhookResponse,
|
|
23
|
+
IUpdateProbeWebhookResponse,
|
|
24
|
+
IListProbeWebhookDeliveriesResponse,
|
|
25
|
+
} from '../types';
|
|
26
|
+
|
|
27
|
+
const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
|
|
28
|
+
|
|
29
|
+
function authHeader(apiKey?: string): Record<string, string> {
|
|
30
|
+
return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Renames `organizationId` to the wire's `organization_id` (see probe-scan.api.ts). */
|
|
34
|
+
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
35
|
+
const out: Record<string, unknown> = {};
|
|
36
|
+
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
37
|
+
if (value === undefined || value === null) continue;
|
|
38
|
+
const wireKey = key === 'organizationId' ? 'organization_id' : key;
|
|
39
|
+
out[wireKey] = value instanceof Date ? value.toISOString() : value;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* `POST /webhook` — register a callbackUrl for the caller's scope. The
|
|
46
|
+
* response's `secret` field (HMAC signing secret) is returned ONLY here —
|
|
47
|
+
* store it immediately, it cannot be re-revealed later.
|
|
48
|
+
*/
|
|
49
|
+
export const createProbeWebhook = async (
|
|
50
|
+
body: ICreateProbeWebhookBody,
|
|
51
|
+
scope: IProbeWebhookScopeQuery = {},
|
|
52
|
+
apiKey?: string,
|
|
53
|
+
): Promise<ICreateProbeWebhookResponse> =>
|
|
54
|
+
(
|
|
55
|
+
await AbyssProbeCore.axios.post<ICreateProbeWebhookResponse>('webhook', body, {
|
|
56
|
+
params: serializeProbeQuery(scope),
|
|
57
|
+
headers: authHeader(apiKey),
|
|
58
|
+
})
|
|
59
|
+
).data;
|
|
60
|
+
|
|
61
|
+
/** `GET /webhook` — flat, scope-filtered list (not paginated — bounded by WEBHOOK_MAX_PER_SCOPE server-side). */
|
|
62
|
+
export const listProbeWebhook = async (
|
|
63
|
+
scope: IProbeWebhookScopeQuery = {},
|
|
64
|
+
apiKey?: string,
|
|
65
|
+
): Promise<IListProbeWebhookResponse> =>
|
|
66
|
+
(
|
|
67
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookResponse>('webhook', {
|
|
68
|
+
params: serializeProbeQuery(scope),
|
|
69
|
+
headers: authHeader(apiKey),
|
|
70
|
+
})
|
|
71
|
+
).data;
|
|
72
|
+
|
|
73
|
+
/** `DELETE /webhook/:webhookId`. */
|
|
74
|
+
export const deleteProbeWebhook = async (
|
|
75
|
+
webhookId: string,
|
|
76
|
+
scope: IProbeWebhookScopeQuery = {},
|
|
77
|
+
apiKey?: string,
|
|
78
|
+
): Promise<IDeleteProbeWebhookResponse> =>
|
|
79
|
+
(
|
|
80
|
+
await AbyssProbeCore.axios.delete<IDeleteProbeWebhookResponse>(`webhook/${webhookId}`, {
|
|
81
|
+
params: serializeProbeQuery(scope),
|
|
82
|
+
headers: authHeader(apiKey),
|
|
83
|
+
})
|
|
84
|
+
).data;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* `PATCH /webhook/:webhookId` (WS5-5) — edit `callbackUrl` and/or `active`.
|
|
88
|
+
* At least one field is required. Scoped like {@link deleteProbeWebhook}
|
|
89
|
+
* (404, never 403, for a webhookId outside the resolved scope). The response
|
|
90
|
+
* includes `secret` — re-displayable now, see {@link IProbeWebhook}.
|
|
91
|
+
*/
|
|
92
|
+
export const updateProbeWebhook = async (
|
|
93
|
+
webhookId: string,
|
|
94
|
+
body: IUpdateProbeWebhookBody,
|
|
95
|
+
scope: IProbeWebhookScopeQuery = {},
|
|
96
|
+
apiKey?: string,
|
|
97
|
+
): Promise<IUpdateProbeWebhookResponse> =>
|
|
98
|
+
(
|
|
99
|
+
await AbyssProbeCore.axios.patch<IUpdateProbeWebhookResponse>(`webhook/${webhookId}`, body, {
|
|
100
|
+
params: serializeProbeQuery(scope),
|
|
101
|
+
headers: authHeader(apiKey),
|
|
102
|
+
})
|
|
103
|
+
).data;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* `GET /webhook/:webhookId/deliveries` (WS5-6) — paginated delivery-attempt
|
|
107
|
+
* history for one registered webhook. Scoped like {@link deleteProbeWebhook}.
|
|
108
|
+
*/
|
|
109
|
+
export const listProbeWebhookDeliveries = async (
|
|
110
|
+
webhookId: string,
|
|
111
|
+
query: IListProbeWebhookDeliveriesQuery = {},
|
|
112
|
+
apiKey?: string,
|
|
113
|
+
): Promise<IListProbeWebhookDeliveriesResponse> =>
|
|
114
|
+
(
|
|
115
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
116
|
+
`webhook/${webhookId}/deliveries`,
|
|
117
|
+
{ params: serializeProbeQuery(query), headers: authHeader(apiKey) },
|
|
118
|
+
)
|
|
119
|
+
).data;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// Type-level compile test for the probe-webhook APPLICATION api surface.
|
|
2
|
-
// No jest runner in this SDK package; compile guard only (mirrors
|
|
3
|
-
// probe-webhook.api.test.ts).
|
|
4
|
-
// Run: npx tsc --noEmit (from packages/abyss_probe_core), or `npm run build`.
|
|
5
|
-
|
|
6
|
-
import * as api from './probe-webhook.application.api';
|
|
7
|
-
|
|
8
|
-
// All three functions must be exported — deliberately no update/reset-secret
|
|
9
|
-
// (see probe-webhook.api.ts's header comment on the small CRUD surface).
|
|
10
|
-
const _create: typeof api.createProbeWebhookApplication = api.createProbeWebhookApplication;
|
|
11
|
-
const _list: typeof api.listProbeWebhookApplication = api.listProbeWebhookApplication;
|
|
12
|
-
const _delete: typeof api.deleteProbeWebhookApplication = api.deleteProbeWebhookApplication;
|
|
13
|
-
|
|
14
|
-
void _create;
|
|
15
|
-
void _list;
|
|
16
|
-
void _delete;
|
|
17
|
-
|
|
18
|
-
export {};
|
|
1
|
+
// Type-level compile test for the probe-webhook APPLICATION api surface.
|
|
2
|
+
// No jest runner in this SDK package; compile guard only (mirrors
|
|
3
|
+
// probe-webhook.api.test.ts).
|
|
4
|
+
// Run: npx tsc --noEmit (from packages/abyss_probe_core), or `npm run build`.
|
|
5
|
+
|
|
6
|
+
import * as api from './probe-webhook.application.api';
|
|
7
|
+
|
|
8
|
+
// All three functions must be exported — deliberately no update/reset-secret
|
|
9
|
+
// (see probe-webhook.api.ts's header comment on the small CRUD surface).
|
|
10
|
+
const _create: typeof api.createProbeWebhookApplication = api.createProbeWebhookApplication;
|
|
11
|
+
const _list: typeof api.listProbeWebhookApplication = api.listProbeWebhookApplication;
|
|
12
|
+
const _delete: typeof api.deleteProbeWebhookApplication = api.deleteProbeWebhookApplication;
|
|
13
|
+
|
|
14
|
+
void _create;
|
|
15
|
+
void _list;
|
|
16
|
+
void _delete;
|
|
17
|
+
|
|
18
|
+
export {};
|
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
// ──────────────────────────────────────────────
|
|
2
|
-
// AbyssProbe APPLICATION webhook subscription API — CRUD over registered
|
|
3
|
-
// `probe_webhooks` owned by a calling application (create / list / delete /
|
|
4
|
-
// update, + paginated delivery history — same surface as the personal/org
|
|
5
|
-
// client, see probe-webhook.api.ts's header comment). Mirrors
|
|
6
|
-
// apps/api/src/api/controllers/probe-webhook-application.controller.ts
|
|
7
|
-
// EXACTLY — the application counterpart of probe-webhook.api.ts, for
|
|
8
|
-
// inter-service callers (abyss-storage, external integrations)
|
|
9
|
-
// authenticating with a project API key instead of a personal/org session.
|
|
10
|
-
//
|
|
11
|
-
// Reuses every request/response TYPE verbatim (`ICreateProbeWebhookBody`,
|
|
12
|
-
// `ICreateProbeWebhookResponse`, `IListProbeWebhookResponse`,
|
|
13
|
-
// `IDeleteProbeWebhookResponse`, `IUpdateProbeWebhookBody`,
|
|
14
|
-
// `IUpdateProbeWebhookResponse`, `IListProbeWebhookDeliveriesQuery`,
|
|
15
|
-
// `IListProbeWebhookDeliveriesResponse`) — never redefined here. No scope
|
|
16
|
-
// argument/query on any of these calls (unlike the personal/org client's
|
|
17
|
-
// `IProbeWebhookScopeQuery`) — an application caller's scope is entirely its
|
|
18
|
-
// `:applicationId` URL segment, resolved server-side by
|
|
19
|
-
// ProbeApplicationMiddleware; there is nothing to select between.
|
|
20
|
-
//
|
|
21
|
-
// `authHeaderApplication` is kept LOCAL and unexported, same convention as
|
|
22
|
-
// the personal/org client's own `authHeader` — it sends
|
|
23
|
-
// `API_KEY_APPLICATION_HEADER` (`abyss-api-key-application`, imported from
|
|
24
|
-
// this package's root) instead of the personal `abyss-api-key` header.
|
|
25
|
-
// ──────────────────────────────────────────────
|
|
26
|
-
|
|
27
|
-
import { AbyssProbeCore, API_KEY_APPLICATION_HEADER } from '..';
|
|
28
|
-
import type {
|
|
29
|
-
ICreateProbeWebhookBody,
|
|
30
|
-
IUpdateProbeWebhookBody,
|
|
31
|
-
IListProbeWebhookDeliveriesQuery,
|
|
32
|
-
ICreateProbeWebhookResponse,
|
|
33
|
-
IListProbeWebhookResponse,
|
|
34
|
-
IDeleteProbeWebhookResponse,
|
|
35
|
-
IUpdateProbeWebhookResponse,
|
|
36
|
-
IListProbeWebhookDeliveriesResponse,
|
|
37
|
-
} from '../types';
|
|
38
|
-
|
|
39
|
-
function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
|
|
40
|
-
return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Renames nothing (no `organizationId` ever travels on an application call) — drops undefined/null and ISO-stringifies `Date`s, mirroring probe-scan.application.api.ts's own local helper. */
|
|
44
|
-
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
45
|
-
const out: Record<string, unknown> = {};
|
|
46
|
-
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
47
|
-
if (value === undefined || value === null) continue;
|
|
48
|
-
out[key] = value instanceof Date ? value.toISOString() : value;
|
|
49
|
-
}
|
|
50
|
-
return out;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* `POST /application/:applicationId/webhook` — register a callbackUrl owned
|
|
55
|
-
* by the calling application. The response's `secret` field (HMAC signing
|
|
56
|
-
* secret) is returned ONLY here — store it immediately, it cannot be
|
|
57
|
-
* re-revealed later.
|
|
58
|
-
*/
|
|
59
|
-
export const createProbeWebhookApplication = async (
|
|
60
|
-
applicationId: string,
|
|
61
|
-
body: ICreateProbeWebhookBody,
|
|
62
|
-
applicationApiKey?: string,
|
|
63
|
-
): Promise<ICreateProbeWebhookResponse> =>
|
|
64
|
-
(
|
|
65
|
-
await AbyssProbeCore.axios.post<ICreateProbeWebhookResponse>(
|
|
66
|
-
`application/${applicationId}/webhook`,
|
|
67
|
-
body,
|
|
68
|
-
{ headers: authHeaderApplication(applicationApiKey) },
|
|
69
|
-
)
|
|
70
|
-
).data;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* `GET /application/:applicationId/webhook` — flat list of the calling
|
|
74
|
-
* application's own webhooks (not paginated — bounded by
|
|
75
|
-
* WEBHOOK_MAX_PER_SCOPE server-side).
|
|
76
|
-
*/
|
|
77
|
-
export const listProbeWebhookApplication = async (
|
|
78
|
-
applicationId: string,
|
|
79
|
-
applicationApiKey?: string,
|
|
80
|
-
): Promise<IListProbeWebhookResponse> =>
|
|
81
|
-
(
|
|
82
|
-
await AbyssProbeCore.axios.get<IListProbeWebhookResponse>(
|
|
83
|
-
`application/${applicationId}/webhook`,
|
|
84
|
-
{ headers: authHeaderApplication(applicationApiKey) },
|
|
85
|
-
)
|
|
86
|
-
).data;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* `DELETE /application/:applicationId/webhook/:webhookId` — cross-tenant
|
|
90
|
-
* guarded server-side by a direct `applicationId` comparison (404, never
|
|
91
|
-
* 403).
|
|
92
|
-
*/
|
|
93
|
-
export const deleteProbeWebhookApplication = async (
|
|
94
|
-
applicationId: string,
|
|
95
|
-
webhookId: string,
|
|
96
|
-
applicationApiKey?: string,
|
|
97
|
-
): Promise<IDeleteProbeWebhookResponse> =>
|
|
98
|
-
(
|
|
99
|
-
await AbyssProbeCore.axios.delete<IDeleteProbeWebhookResponse>(
|
|
100
|
-
`application/${applicationId}/webhook/${webhookId}`,
|
|
101
|
-
{ headers: authHeaderApplication(applicationApiKey) },
|
|
102
|
-
)
|
|
103
|
-
).data;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* `PATCH /application/:applicationId/webhook/:webhookId` (WS5-5) — edit
|
|
107
|
-
* `callbackUrl` and/or `active` on a webhook owned by the calling
|
|
108
|
-
* application. Cross-tenant guarded server-side (404, never 403). The
|
|
109
|
-
* response includes `secret` — re-displayable now, see {@link IProbeWebhook}.
|
|
110
|
-
*/
|
|
111
|
-
export const updateProbeWebhookApplication = async (
|
|
112
|
-
applicationId: string,
|
|
113
|
-
webhookId: string,
|
|
114
|
-
body: IUpdateProbeWebhookBody,
|
|
115
|
-
applicationApiKey?: string,
|
|
116
|
-
): Promise<IUpdateProbeWebhookResponse> =>
|
|
117
|
-
(
|
|
118
|
-
await AbyssProbeCore.axios.patch<IUpdateProbeWebhookResponse>(
|
|
119
|
-
`application/${applicationId}/webhook/${webhookId}`,
|
|
120
|
-
body,
|
|
121
|
-
{ headers: authHeaderApplication(applicationApiKey) },
|
|
122
|
-
)
|
|
123
|
-
).data;
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* `GET /application/:applicationId/webhook/:webhookId/deliveries` (WS5-6) —
|
|
127
|
-
* paginated delivery-attempt history for one webhook owned by the calling
|
|
128
|
-
* application. Cross-tenant guarded server-side (404, never 403).
|
|
129
|
-
*/
|
|
130
|
-
export const listProbeWebhookDeliveriesApplication = async (
|
|
131
|
-
applicationId: string,
|
|
132
|
-
webhookId: string,
|
|
133
|
-
query: Omit<IListProbeWebhookDeliveriesQuery, 'organizationId'> = {},
|
|
134
|
-
applicationApiKey?: string,
|
|
135
|
-
): Promise<IListProbeWebhookDeliveriesResponse> =>
|
|
136
|
-
(
|
|
137
|
-
await AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
138
|
-
`application/${applicationId}/webhook/${webhookId}/deliveries`,
|
|
139
|
-
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
140
|
-
)
|
|
141
|
-
).data;
|
|
1
|
+
// ──────────────────────────────────────────────
|
|
2
|
+
// AbyssProbe APPLICATION webhook subscription API — CRUD over registered
|
|
3
|
+
// `probe_webhooks` owned by a calling application (create / list / delete /
|
|
4
|
+
// update, + paginated delivery history — same surface as the personal/org
|
|
5
|
+
// client, see probe-webhook.api.ts's header comment). Mirrors
|
|
6
|
+
// apps/api/src/api/controllers/probe-webhook-application.controller.ts
|
|
7
|
+
// EXACTLY — the application counterpart of probe-webhook.api.ts, for
|
|
8
|
+
// inter-service callers (abyss-storage, external integrations)
|
|
9
|
+
// authenticating with a project API key instead of a personal/org session.
|
|
10
|
+
//
|
|
11
|
+
// Reuses every request/response TYPE verbatim (`ICreateProbeWebhookBody`,
|
|
12
|
+
// `ICreateProbeWebhookResponse`, `IListProbeWebhookResponse`,
|
|
13
|
+
// `IDeleteProbeWebhookResponse`, `IUpdateProbeWebhookBody`,
|
|
14
|
+
// `IUpdateProbeWebhookResponse`, `IListProbeWebhookDeliveriesQuery`,
|
|
15
|
+
// `IListProbeWebhookDeliveriesResponse`) — never redefined here. No scope
|
|
16
|
+
// argument/query on any of these calls (unlike the personal/org client's
|
|
17
|
+
// `IProbeWebhookScopeQuery`) — an application caller's scope is entirely its
|
|
18
|
+
// `:applicationId` URL segment, resolved server-side by
|
|
19
|
+
// ProbeApplicationMiddleware; there is nothing to select between.
|
|
20
|
+
//
|
|
21
|
+
// `authHeaderApplication` is kept LOCAL and unexported, same convention as
|
|
22
|
+
// the personal/org client's own `authHeader` — it sends
|
|
23
|
+
// `API_KEY_APPLICATION_HEADER` (`abyss-api-key-application`, imported from
|
|
24
|
+
// this package's root) instead of the personal `abyss-api-key` header.
|
|
25
|
+
// ──────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
import { AbyssProbeCore, API_KEY_APPLICATION_HEADER } from '..';
|
|
28
|
+
import type {
|
|
29
|
+
ICreateProbeWebhookBody,
|
|
30
|
+
IUpdateProbeWebhookBody,
|
|
31
|
+
IListProbeWebhookDeliveriesQuery,
|
|
32
|
+
ICreateProbeWebhookResponse,
|
|
33
|
+
IListProbeWebhookResponse,
|
|
34
|
+
IDeleteProbeWebhookResponse,
|
|
35
|
+
IUpdateProbeWebhookResponse,
|
|
36
|
+
IListProbeWebhookDeliveriesResponse,
|
|
37
|
+
} from '../types';
|
|
38
|
+
|
|
39
|
+
function authHeaderApplication(applicationApiKey?: string): Record<string, string> {
|
|
40
|
+
return applicationApiKey ? { [API_KEY_APPLICATION_HEADER]: applicationApiKey } : {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Renames nothing (no `organizationId` ever travels on an application call) — drops undefined/null and ISO-stringifies `Date`s, mirroring probe-scan.application.api.ts's own local helper. */
|
|
44
|
+
function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
|
|
45
|
+
const out: Record<string, unknown> = {};
|
|
46
|
+
for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
|
|
47
|
+
if (value === undefined || value === null) continue;
|
|
48
|
+
out[key] = value instanceof Date ? value.toISOString() : value;
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* `POST /application/:applicationId/webhook` — register a callbackUrl owned
|
|
55
|
+
* by the calling application. The response's `secret` field (HMAC signing
|
|
56
|
+
* secret) is returned ONLY here — store it immediately, it cannot be
|
|
57
|
+
* re-revealed later.
|
|
58
|
+
*/
|
|
59
|
+
export const createProbeWebhookApplication = async (
|
|
60
|
+
applicationId: string,
|
|
61
|
+
body: ICreateProbeWebhookBody,
|
|
62
|
+
applicationApiKey?: string,
|
|
63
|
+
): Promise<ICreateProbeWebhookResponse> =>
|
|
64
|
+
(
|
|
65
|
+
await AbyssProbeCore.axios.post<ICreateProbeWebhookResponse>(
|
|
66
|
+
`application/${applicationId}/webhook`,
|
|
67
|
+
body,
|
|
68
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
69
|
+
)
|
|
70
|
+
).data;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `GET /application/:applicationId/webhook` — flat list of the calling
|
|
74
|
+
* application's own webhooks (not paginated — bounded by
|
|
75
|
+
* WEBHOOK_MAX_PER_SCOPE server-side).
|
|
76
|
+
*/
|
|
77
|
+
export const listProbeWebhookApplication = async (
|
|
78
|
+
applicationId: string,
|
|
79
|
+
applicationApiKey?: string,
|
|
80
|
+
): Promise<IListProbeWebhookResponse> =>
|
|
81
|
+
(
|
|
82
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookResponse>(
|
|
83
|
+
`application/${applicationId}/webhook`,
|
|
84
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
85
|
+
)
|
|
86
|
+
).data;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* `DELETE /application/:applicationId/webhook/:webhookId` — cross-tenant
|
|
90
|
+
* guarded server-side by a direct `applicationId` comparison (404, never
|
|
91
|
+
* 403).
|
|
92
|
+
*/
|
|
93
|
+
export const deleteProbeWebhookApplication = async (
|
|
94
|
+
applicationId: string,
|
|
95
|
+
webhookId: string,
|
|
96
|
+
applicationApiKey?: string,
|
|
97
|
+
): Promise<IDeleteProbeWebhookResponse> =>
|
|
98
|
+
(
|
|
99
|
+
await AbyssProbeCore.axios.delete<IDeleteProbeWebhookResponse>(
|
|
100
|
+
`application/${applicationId}/webhook/${webhookId}`,
|
|
101
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
102
|
+
)
|
|
103
|
+
).data;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* `PATCH /application/:applicationId/webhook/:webhookId` (WS5-5) — edit
|
|
107
|
+
* `callbackUrl` and/or `active` on a webhook owned by the calling
|
|
108
|
+
* application. Cross-tenant guarded server-side (404, never 403). The
|
|
109
|
+
* response includes `secret` — re-displayable now, see {@link IProbeWebhook}.
|
|
110
|
+
*/
|
|
111
|
+
export const updateProbeWebhookApplication = async (
|
|
112
|
+
applicationId: string,
|
|
113
|
+
webhookId: string,
|
|
114
|
+
body: IUpdateProbeWebhookBody,
|
|
115
|
+
applicationApiKey?: string,
|
|
116
|
+
): Promise<IUpdateProbeWebhookResponse> =>
|
|
117
|
+
(
|
|
118
|
+
await AbyssProbeCore.axios.patch<IUpdateProbeWebhookResponse>(
|
|
119
|
+
`application/${applicationId}/webhook/${webhookId}`,
|
|
120
|
+
body,
|
|
121
|
+
{ headers: authHeaderApplication(applicationApiKey) },
|
|
122
|
+
)
|
|
123
|
+
).data;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* `GET /application/:applicationId/webhook/:webhookId/deliveries` (WS5-6) —
|
|
127
|
+
* paginated delivery-attempt history for one webhook owned by the calling
|
|
128
|
+
* application. Cross-tenant guarded server-side (404, never 403).
|
|
129
|
+
*/
|
|
130
|
+
export const listProbeWebhookDeliveriesApplication = async (
|
|
131
|
+
applicationId: string,
|
|
132
|
+
webhookId: string,
|
|
133
|
+
query: Omit<IListProbeWebhookDeliveriesQuery, 'organizationId'> = {},
|
|
134
|
+
applicationApiKey?: string,
|
|
135
|
+
): Promise<IListProbeWebhookDeliveriesResponse> =>
|
|
136
|
+
(
|
|
137
|
+
await AbyssProbeCore.axios.get<IListProbeWebhookDeliveriesResponse>(
|
|
138
|
+
`application/${applicationId}/webhook/${webhookId}/deliveries`,
|
|
139
|
+
{ params: serializeProbeQuery(query), headers: authHeaderApplication(applicationApiKey) },
|
|
140
|
+
)
|
|
141
|
+
).data;
|
package/src/constants/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|