@abyss-project/probe 2.0.0 → 3.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.
Files changed (90) hide show
  1. package/.eslintrc.js +32 -32
  2. package/.prettierrc +5 -5
  3. package/README.md +22 -22
  4. package/dist/api/index.d.ts +2 -1
  5. package/dist/api/index.js +2 -1
  6. package/dist/api/index.js.map +1 -1
  7. package/dist/api/probe-delivery-subscription.api.d.ts +11 -0
  8. package/dist/api/probe-delivery-subscription.api.js +42 -0
  9. package/dist/api/probe-delivery-subscription.api.js.map +1 -0
  10. package/dist/api/probe-delivery-subscription.application.api.d.ts +11 -0
  11. package/dist/api/probe-delivery-subscription.application.api.js +38 -0
  12. package/dist/api/probe-delivery-subscription.application.api.js.map +1 -0
  13. package/dist/api/probe-webhook.application.api.d.ts +1 -1
  14. package/dist/api/probe-webhook.application.api.js.map +1 -1
  15. package/dist/index.d.ts +29 -7
  16. package/dist/index.js +29 -7
  17. package/dist/index.js.map +1 -1
  18. package/dist/types/enum/api-error.enum.d.ts +2 -1
  19. package/dist/types/enum/api-error.enum.js +1 -0
  20. package/dist/types/enum/api-error.enum.js.map +1 -1
  21. package/dist/types/enum/probe-scan.enum.js.map +1 -1
  22. package/dist/types/interface/api/requests/index.d.ts +1 -0
  23. package/dist/types/interface/api/requests/index.js +1 -0
  24. package/dist/types/interface/api/requests/index.js.map +1 -1
  25. package/dist/types/interface/api/requests/probe-delivery-subscription.request.d.ts +23 -0
  26. package/dist/types/interface/api/requests/probe-delivery-subscription.request.js +3 -0
  27. package/dist/types/interface/api/requests/probe-delivery-subscription.request.js.map +1 -0
  28. package/dist/types/interface/api/requests/probe-webhook.request.d.ts +1 -4
  29. package/dist/types/interface/api/responses/index.d.ts +1 -0
  30. package/dist/types/interface/api/responses/index.js +1 -0
  31. package/dist/types/interface/api/responses/index.js.map +1 -1
  32. package/dist/types/interface/api/responses/probe-delivery-subscription.response.d.ts +10 -0
  33. package/dist/types/interface/api/responses/probe-delivery-subscription.response.js +3 -0
  34. package/dist/types/interface/api/responses/probe-delivery-subscription.response.js.map +1 -0
  35. package/dist/types/tests/probe.dto.test.js +22 -0
  36. package/dist/types/tests/probe.dto.test.js.map +1 -1
  37. package/dist/utils/probe-webhook-signature.utils.js.map +1 -1
  38. package/package.json +19 -15
  39. package/src/api/index.ts +2 -1
  40. package/src/api/probe-delivery-subscription.api.ts +183 -0
  41. package/src/api/probe-delivery-subscription.application.api.ts +186 -0
  42. package/src/api/probe-scan.api.test.ts +47 -47
  43. package/src/api/probe-scan.api.ts +203 -203
  44. package/src/api/probe-scan.application.api.test.ts +35 -35
  45. package/src/api/probe-scan.application.api.ts +157 -157
  46. package/src/api/probe-usage.api.ts +47 -47
  47. package/src/api/probe-usage.application.api.ts +25 -25
  48. package/src/api/probe-webhook.application.api.test.ts +18 -18
  49. package/src/api/probe-webhook.application.api.ts +10 -23
  50. package/src/constants/index.ts +1 -1
  51. package/src/index.ts +73 -16
  52. package/src/types/enum/api-error.enum.ts +2 -0
  53. package/src/types/enum/index.ts +2 -2
  54. package/src/types/enum/probe-scan.enum.ts +3 -2
  55. package/src/types/index.ts +2 -2
  56. package/src/types/interface/api/index.ts +5 -5
  57. package/src/types/interface/api/requests/index.ts +1 -0
  58. package/src/types/interface/api/requests/probe-delivery-subscription.request.ts +42 -0
  59. package/src/types/interface/api/requests/probe-scan.request.ts +54 -54
  60. package/src/types/interface/api/requests/probe-usage.request.ts +7 -7
  61. package/src/types/interface/api/requests/probe-webhook.request.ts +9 -11
  62. package/src/types/interface/api/responses/index.ts +1 -0
  63. package/src/types/interface/api/responses/probe-delivery-subscription.response.ts +27 -0
  64. package/src/types/interface/api/responses/probe-scan.response.ts +45 -45
  65. package/src/types/interface/api/responses/probe-usage.response.ts +25 -25
  66. package/src/types/interface/api/responses/probe-webhook.response.ts +24 -24
  67. package/src/types/interface/api/type-message/api-error.ts +7 -7
  68. package/src/types/interface/api/type-message/base-paginate.ts +11 -11
  69. package/src/types/interface/api/type-message/response.ts +6 -6
  70. package/src/types/interface/index.ts +2 -2
  71. package/src/types/interface/models/index.ts +3 -3
  72. package/src/types/interface/models/probe-scan.dto.ts +67 -67
  73. package/src/types/interface/models/probe-webhook-delivery.dto.ts +11 -14
  74. package/src/types/interface/models/probe-webhook.dto.ts +29 -29
  75. package/src/types/tests/probe.dto.test.ts +40 -4
  76. package/src/utils/enum.utils.ts +1 -1
  77. package/src/utils/error.utils.ts +30 -30
  78. package/src/utils/index.ts +4 -4
  79. package/src/utils/probe-scan-cost.utils.ts +101 -101
  80. package/src/utils/probe-webhook-signature.utils.ts +4 -3
  81. package/tsconfig.check.json +15 -15
  82. package/tsconfig.json +36 -36
  83. package/dist/api/probe-webhook.api.d.ts +0 -6
  84. package/dist/api/probe-webhook.api.js +0 -41
  85. package/dist/api/probe-webhook.api.js.map +0 -1
  86. package/dist/api/probe-webhook.api.test.d.ts +0 -1
  87. package/dist/api/probe-webhook.api.test.js +0 -43
  88. package/dist/api/probe-webhook.api.test.js.map +0 -1
  89. package/src/api/probe-webhook.api.test.ts +0 -17
  90. package/src/api/probe-webhook.api.ts +0 -119
@@ -1,203 +1,203 @@
1
- // ──────────────────────────────────────────────
2
- // AbyssProbe scan API — POST /scan (sync + async), GET /scan/:scanId (poll),
3
- // GET /scan (history/search). Mirrors
4
- // apps/api/src/api/controllers/probe-scan.controller.ts EXACTLY (see that
5
- // file for the full contract this client targets). AbyssProbe's controllers
6
- // add no extra path segment (`@Controller({ prefixPath: '/scan' })`), so
7
- // these calls hit `scan`/`scan/:id` directly — no `probe/` prefix.
8
- //
9
- // Multipart bodies are built with the global `FormData` + `Blob` — the same
10
- // code in a browser and on Node, mirroring this package's own
11
- // extraction.api.ts. axios serializes a spec-compliant FormData on both and
12
- // sets the multipart boundary itself, so no content-type header is ever set by
13
- // hand. AbyssProbe is called from the abyss-main UI (a browser) as well as
14
- // from Node services (abyss-storage, external integrators).
15
- //
16
- // A Node caller holding a file ON DISK passes `await fs.openAsBlob(path)`,
17
- // which requires Node >= 19.8 — hence `engines.node` in package.json.
18
- // `FormData` and `Blob` alone would only need Node 18, but openAsBlob is this
19
- // client's documented way to send a file, and promising 18.x only to fail at
20
- // runtime is worse than refusing the install. A caller that already holds its
21
- // bytes passes a `Buffer`/`Uint8Array` and has no such constraint (see
22
- // {@link ProbeScanFileInput}).
23
- //
24
- // `authHeader`/`serializeProbeQuery` are kept LOCAL and unexported (not a
25
- // shared utils file) — same convention as every other extract/*.api.ts file
26
- // in this package (each redefines its own tiny per-call apiKey helper; see
27
- // extraction.api.ts / extraction-settings.api.ts / extraction-plan-preset.api.ts).
28
- //
29
- // See probe-scan.application.api.ts for the application/API-key-auth
30
- // counterpart of this client (`/application/:applicationId/scan...`, Phase
31
- // 3a) — it reuses this file's `buildScanForm` and every request/response
32
- // type verbatim; only the URL prefix, the extra `applicationId` argument,
33
- // and the auth header differ.
34
- // ──────────────────────────────────────────────
35
-
36
- import { AbyssProbeCore } from '..';
37
- import { ProbeScanMode } from '../types';
38
- import type {
39
- IScanOptions,
40
- IListScansQuery,
41
- IScanResponse,
42
- IScanSyncResponse,
43
- IScanAsyncResponse,
44
- IGetScanResponse,
45
- IPaginateScanResponse,
46
- } from '../types';
47
-
48
- const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
49
-
50
- function authHeader(apiKey?: string): Record<string, string> {
51
- return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
52
- }
53
-
54
- /**
55
- * Turn a request/query options object into axios `params`: drops
56
- * undefined/null, ISO-stringifies `Date`s, and renames `organizationId` to
57
- * the wire's `organization_id` (the one snake_case key AbyssProbe's own
58
- * controllers actually expect — see probe-scope.helper.ts#readOrganizationId
59
- * — every other field name is already camelCase on both sides).
60
- */
61
- function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
62
- const out: Record<string, unknown> = {};
63
- for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
64
- if (value === undefined || value === null) continue;
65
- const wireKey = key === 'organizationId' ? 'organization_id' : key;
66
- out[wireKey] = value instanceof Date ? value.toISOString() : value;
67
- }
68
- return out;
69
- }
70
-
71
- /**
72
- * Anything `sdk.probe.scan` accepts as the file to submit.
73
- *
74
- * `Blob` covers the browser's `File` (a `Blob` subclass) and, on Node, a
75
- * FILE-BACKED blob from `await fs.openAsBlob(path)` (Node >= 19.8): its bytes
76
- * are read from disk as the request body is written, so scanning a file at the
77
- * 2 GiB ceiling never holds the file in memory. `Uint8Array` (and therefore
78
- * `Buffer`) is for a caller that already holds the bytes.
79
- *
80
- * A Node `Readable` is NOT accepted. The body is a spec `FormData`, whose
81
- * parts must have a known length, so a stream could only be honoured by
82
- * buffering it whole — precisely what a 2 GiB scan must not do. A caller
83
- * holding a path passes `await fs.openAsBlob(path)` instead.
84
- */
85
- export type ProbeScanFileInput = Blob | Uint8Array;
86
-
87
- /**
88
- * The file as one multipart part.
89
- *
90
- * A `Blob` is used as-is, keeping whatever streaming its implementation gives
91
- * (a file-backed `openAsBlob` reads from disk lazily); raw bytes are wrapped
92
- * in a `Blob` carrying `mimeType`. `Buffer` is never named here — this code
93
- * also runs in a browser bundle, where the global does not exist — and
94
- * `Buffer` is a `Uint8Array` subclass, so the check below already covers it.
95
- *
96
- * Anything else is refused with an actionable message. Until 2.12.0 the same
97
- * call died on Node with `ReferenceError: require is not defined`, thrown by a
98
- * `form-data` loader before any request was made (#519): it named neither the
99
- * cause nor the fix.
100
- */
101
- function toScanFilePart(file: ProbeScanFileInput, mimeType?: string): Blob {
102
- if (file instanceof Blob) return file;
103
- if (file instanceof Uint8Array) return new Blob([new Uint8Array(file)], { type: mimeType ?? '' });
104
-
105
- const isStream = typeof (file as { pipe?: unknown } | null | undefined)?.pipe === 'function';
106
- throw new TypeError(
107
- `A probe scan file must be a Blob (a browser File, or fs.openAsBlob(path) on Node), ` +
108
- `a Buffer or a Uint8Array — received ${isStream ? 'a stream' : typeof file}. ` +
109
- `On Node, pass \`await fs.openAsBlob(path)\`: a file-backed Blob is streamed from ` +
110
- `disk, so the file is never buffered in memory.`,
111
- );
112
- }
113
-
114
- /**
115
- * Exported (not just this file's own `scan` internals) so
116
- * probe-scan.application.api.ts reuses this EXACT multipart-building logic
117
- * rather than duplicating it — the file-upload contract is identical for a
118
- * personal/org caller and an application caller; only the URL/auth differ
119
- * (see that file's header comment).
120
- *
121
- * Returns the form alone: axios sets the multipart content type, boundary
122
- * included, so there is no header for the caller to merge in.
123
- */
124
- export function buildScanForm(file: ProbeScanFileInput, options: IScanOptions): FormData {
125
- const form = new FormData();
126
- form.append('file', toScanFilePart(file, options.mimeType), options.filename ?? 'file');
127
- if (options.context) form.append('context', JSON.stringify(options.context));
128
- if (options.callbackUrl) form.append('callbackUrl', options.callbackUrl);
129
- return form;
130
- }
131
-
132
- /**
133
- * `POST /scan` — SYNC by default, ASYNC when `options.mode = ProbeScanMode.ASYNC`
134
- * (same endpoint, query-param-selected — see the controller's doc comment).
135
- * `mode` and `organizationId` travel as query params; `context`
136
- * (JSON-encoded) and `callbackUrl` travel as multipart text fields alongside
137
- * the file.
138
- *
139
- * Returns the SYNC (200, verdict inline) or ASYNC (202, `{ scanId, status:
140
- * 'queued' }`) shape depending on `options.mode` — see {@link IScanResponse}.
141
- * Prefer {@link scanSync} / {@link scanAsync} for a precisely-typed return
142
- * instead of the union.
143
- */
144
- export const scan = async (
145
- file: ProbeScanFileInput,
146
- options: IScanOptions = {},
147
- apiKey?: string,
148
- ): Promise<IScanResponse> => {
149
- const form = buildScanForm(file, options);
150
- return (
151
- await AbyssProbeCore.axios.post<IScanResponse>('scan', form, {
152
- params: serializeProbeQuery({ mode: options.mode, organizationId: options.organizationId }),
153
- headers: authHeader(apiKey),
154
- maxBodyLength: Infinity,
155
- maxContentLength: Infinity,
156
- })
157
- ).data;
158
- };
159
-
160
- /** {@link scan}, forced to `mode: sync` — HTTP 200, verdict returned inline. */
161
- export const scanSync = async (
162
- file: ProbeScanFileInput,
163
- options: Omit<IScanOptions, 'mode' | 'callbackUrl'> = {},
164
- apiKey?: string,
165
- ): Promise<IScanSyncResponse> =>
166
- scan(file, { ...options, mode: ProbeScanMode.SYNC }, apiKey) as Promise<IScanSyncResponse>;
167
-
168
- /** {@link scan}, forced to `mode: async` — HTTP 202, job queued. */
169
- export const scanAsync = async (
170
- file: ProbeScanFileInput,
171
- options: Omit<IScanOptions, 'mode'> = {},
172
- apiKey?: string,
173
- ): Promise<IScanAsyncResponse> =>
174
- scan(file, { ...options, mode: ProbeScanMode.ASYNC }, apiKey) as Promise<IScanAsyncResponse>;
175
-
176
- /**
177
- * `GET /scan/:scanId` — poll the queued -> scanning -> done/error
178
- * progression of an ASYNC scan (also answers for a SYNC scan's row). Cross-
179
- * tenant guarded server-side (404, never 403) — needs no scope query param,
180
- * the scanId alone determines it.
181
- */
182
- export const getScan = async (scanId: string, apiKey?: string): Promise<IGetScanResponse> =>
183
- (
184
- await AbyssProbeCore.axios.get<IGetScanResponse>(`scan/${scanId}`, {
185
- headers: authHeader(apiKey),
186
- })
187
- ).data;
188
-
189
- /**
190
- * `GET /scan` — paginated scan history/search for the caller's scope
191
- * (personal by default, `organizationId` for an organization scope), newest
192
- * first. See {@link IListScansQuery} for the available filters.
193
- */
194
- export const listScans = async (
195
- query: IListScansQuery = {},
196
- apiKey?: string,
197
- ): Promise<IPaginateScanResponse> =>
198
- (
199
- await AbyssProbeCore.axios.get<IPaginateScanResponse>('scan', {
200
- params: serializeProbeQuery(query),
201
- headers: authHeader(apiKey),
202
- })
203
- ).data;
1
+ // ──────────────────────────────────────────────
2
+ // AbyssProbe scan API — POST /scan (sync + async), GET /scan/:scanId (poll),
3
+ // GET /scan (history/search). Mirrors
4
+ // apps/api/src/api/controllers/probe-scan.controller.ts EXACTLY (see that
5
+ // file for the full contract this client targets). AbyssProbe's controllers
6
+ // add no extra path segment (`@Controller({ prefixPath: '/scan' })`), so
7
+ // these calls hit `scan`/`scan/:id` directly — no `probe/` prefix.
8
+ //
9
+ // Multipart bodies are built with the global `FormData` + `Blob` — the same
10
+ // code in a browser and on Node, mirroring this package's own
11
+ // extraction.api.ts. axios serializes a spec-compliant FormData on both and
12
+ // sets the multipart boundary itself, so no content-type header is ever set by
13
+ // hand. AbyssProbe is called from the abyss-main UI (a browser) as well as
14
+ // from Node services (abyss-storage, external integrators).
15
+ //
16
+ // A Node caller holding a file ON DISK passes `await fs.openAsBlob(path)`,
17
+ // which requires Node >= 19.8 — hence `engines.node` in package.json.
18
+ // `FormData` and `Blob` alone would only need Node 18, but openAsBlob is this
19
+ // client's documented way to send a file, and promising 18.x only to fail at
20
+ // runtime is worse than refusing the install. A caller that already holds its
21
+ // bytes passes a `Buffer`/`Uint8Array` and has no such constraint (see
22
+ // {@link ProbeScanFileInput}).
23
+ //
24
+ // `authHeader`/`serializeProbeQuery` are kept LOCAL and unexported (not a
25
+ // shared utils file) — same convention as every other extract/*.api.ts file
26
+ // in this package (each redefines its own tiny per-call apiKey helper; see
27
+ // extraction.api.ts / extraction-settings.api.ts / extraction-plan-preset.api.ts).
28
+ //
29
+ // See probe-scan.application.api.ts for the application/API-key-auth
30
+ // counterpart of this client (`/application/:applicationId/scan...`, Phase
31
+ // 3a) — it reuses this file's `buildScanForm` and every request/response
32
+ // type verbatim; only the URL prefix, the extra `applicationId` argument,
33
+ // and the auth header differ.
34
+ // ──────────────────────────────────────────────
35
+
36
+ import { AbyssProbeCore } from '..';
37
+ import { ProbeScanMode } from '../types';
38
+ import type {
39
+ IScanOptions,
40
+ IListScansQuery,
41
+ IScanResponse,
42
+ IScanSyncResponse,
43
+ IScanAsyncResponse,
44
+ IGetScanResponse,
45
+ IPaginateScanResponse,
46
+ } from '../types';
47
+
48
+ const DEFAULT_API_KEY_HEADER = 'abyss-api-key';
49
+
50
+ function authHeader(apiKey?: string): Record<string, string> {
51
+ return apiKey ? { [DEFAULT_API_KEY_HEADER]: apiKey } : {};
52
+ }
53
+
54
+ /**
55
+ * Turn a request/query options object into axios `params`: drops
56
+ * undefined/null, ISO-stringifies `Date`s, and renames `organizationId` to
57
+ * the wire's `organization_id` (the one snake_case key AbyssProbe's own
58
+ * controllers actually expect — see probe-scope.helper.ts#readOrganizationId
59
+ * — every other field name is already camelCase on both sides).
60
+ */
61
+ function serializeProbeQuery<T extends object>(query: T): Record<string, unknown> {
62
+ const out: Record<string, unknown> = {};
63
+ for (const [key, value] of Object.entries(query as Record<string, unknown>)) {
64
+ if (value === undefined || value === null) continue;
65
+ const wireKey = key === 'organizationId' ? 'organization_id' : key;
66
+ out[wireKey] = value instanceof Date ? value.toISOString() : value;
67
+ }
68
+ return out;
69
+ }
70
+
71
+ /**
72
+ * Anything `sdk.probe.scan` accepts as the file to submit.
73
+ *
74
+ * `Blob` covers the browser's `File` (a `Blob` subclass) and, on Node, a
75
+ * FILE-BACKED blob from `await fs.openAsBlob(path)` (Node >= 19.8): its bytes
76
+ * are read from disk as the request body is written, so scanning a file at the
77
+ * 2 GiB ceiling never holds the file in memory. `Uint8Array` (and therefore
78
+ * `Buffer`) is for a caller that already holds the bytes.
79
+ *
80
+ * A Node `Readable` is NOT accepted. The body is a spec `FormData`, whose
81
+ * parts must have a known length, so a stream could only be honoured by
82
+ * buffering it whole — precisely what a 2 GiB scan must not do. A caller
83
+ * holding a path passes `await fs.openAsBlob(path)` instead.
84
+ */
85
+ export type ProbeScanFileInput = Blob | Uint8Array;
86
+
87
+ /**
88
+ * The file as one multipart part.
89
+ *
90
+ * A `Blob` is used as-is, keeping whatever streaming its implementation gives
91
+ * (a file-backed `openAsBlob` reads from disk lazily); raw bytes are wrapped
92
+ * in a `Blob` carrying `mimeType`. `Buffer` is never named here — this code
93
+ * also runs in a browser bundle, where the global does not exist — and
94
+ * `Buffer` is a `Uint8Array` subclass, so the check below already covers it.
95
+ *
96
+ * Anything else is refused with an actionable message. Until 2.12.0 the same
97
+ * call died on Node with `ReferenceError: require is not defined`, thrown by a
98
+ * `form-data` loader before any request was made (#519): it named neither the
99
+ * cause nor the fix.
100
+ */
101
+ function toScanFilePart(file: ProbeScanFileInput, mimeType?: string): Blob {
102
+ if (file instanceof Blob) return file;
103
+ if (file instanceof Uint8Array) return new Blob([new Uint8Array(file)], { type: mimeType ?? '' });
104
+
105
+ const isStream = typeof (file as { pipe?: unknown } | null | undefined)?.pipe === 'function';
106
+ throw new TypeError(
107
+ `A probe scan file must be a Blob (a browser File, or fs.openAsBlob(path) on Node), ` +
108
+ `a Buffer or a Uint8Array — received ${isStream ? 'a stream' : typeof file}. ` +
109
+ `On Node, pass \`await fs.openAsBlob(path)\`: a file-backed Blob is streamed from ` +
110
+ `disk, so the file is never buffered in memory.`,
111
+ );
112
+ }
113
+
114
+ /**
115
+ * Exported (not just this file's own `scan` internals) so
116
+ * probe-scan.application.api.ts reuses this EXACT multipart-building logic
117
+ * rather than duplicating it — the file-upload contract is identical for a
118
+ * personal/org caller and an application caller; only the URL/auth differ
119
+ * (see that file's header comment).
120
+ *
121
+ * Returns the form alone: axios sets the multipart content type, boundary
122
+ * included, so there is no header for the caller to merge in.
123
+ */
124
+ export function buildScanForm(file: ProbeScanFileInput, options: IScanOptions): FormData {
125
+ const form = new FormData();
126
+ form.append('file', toScanFilePart(file, options.mimeType), options.filename ?? 'file');
127
+ if (options.context) form.append('context', JSON.stringify(options.context));
128
+ if (options.callbackUrl) form.append('callbackUrl', options.callbackUrl);
129
+ return form;
130
+ }
131
+
132
+ /**
133
+ * `POST /scan` — SYNC by default, ASYNC when `options.mode = ProbeScanMode.ASYNC`
134
+ * (same endpoint, query-param-selected — see the controller's doc comment).
135
+ * `mode` and `organizationId` travel as query params; `context`
136
+ * (JSON-encoded) and `callbackUrl` travel as multipart text fields alongside
137
+ * the file.
138
+ *
139
+ * Returns the SYNC (200, verdict inline) or ASYNC (202, `{ scanId, status:
140
+ * 'queued' }`) shape depending on `options.mode` — see {@link IScanResponse}.
141
+ * Prefer {@link scanSync} / {@link scanAsync} for a precisely-typed return
142
+ * instead of the union.
143
+ */
144
+ export const scan = async (
145
+ file: ProbeScanFileInput,
146
+ options: IScanOptions = {},
147
+ apiKey?: string,
148
+ ): Promise<IScanResponse> => {
149
+ const form = buildScanForm(file, options);
150
+ return (
151
+ await AbyssProbeCore.axios.post<IScanResponse>('scan', form, {
152
+ params: serializeProbeQuery({ mode: options.mode, organizationId: options.organizationId }),
153
+ headers: authHeader(apiKey),
154
+ maxBodyLength: Infinity,
155
+ maxContentLength: Infinity,
156
+ })
157
+ ).data;
158
+ };
159
+
160
+ /** {@link scan}, forced to `mode: sync` — HTTP 200, verdict returned inline. */
161
+ export const scanSync = async (
162
+ file: ProbeScanFileInput,
163
+ options: Omit<IScanOptions, 'mode' | 'callbackUrl'> = {},
164
+ apiKey?: string,
165
+ ): Promise<IScanSyncResponse> =>
166
+ scan(file, { ...options, mode: ProbeScanMode.SYNC }, apiKey) as Promise<IScanSyncResponse>;
167
+
168
+ /** {@link scan}, forced to `mode: async` — HTTP 202, job queued. */
169
+ export const scanAsync = async (
170
+ file: ProbeScanFileInput,
171
+ options: Omit<IScanOptions, 'mode'> = {},
172
+ apiKey?: string,
173
+ ): Promise<IScanAsyncResponse> =>
174
+ scan(file, { ...options, mode: ProbeScanMode.ASYNC }, apiKey) as Promise<IScanAsyncResponse>;
175
+
176
+ /**
177
+ * `GET /scan/:scanId` — poll the queued -> scanning -> done/error
178
+ * progression of an ASYNC scan (also answers for a SYNC scan's row). Cross-
179
+ * tenant guarded server-side (404, never 403) — needs no scope query param,
180
+ * the scanId alone determines it.
181
+ */
182
+ export const getScan = async (scanId: string, apiKey?: string): Promise<IGetScanResponse> =>
183
+ (
184
+ await AbyssProbeCore.axios.get<IGetScanResponse>(`scan/${scanId}`, {
185
+ headers: authHeader(apiKey),
186
+ })
187
+ ).data;
188
+
189
+ /**
190
+ * `GET /scan` — paginated scan history/search for the caller's scope
191
+ * (personal by default, `organizationId` for an organization scope), newest
192
+ * first. See {@link IListScansQuery} for the available filters.
193
+ */
194
+ export const listScans = async (
195
+ query: IListScansQuery = {},
196
+ apiKey?: string,
197
+ ): Promise<IPaginateScanResponse> =>
198
+ (
199
+ await AbyssProbeCore.axios.get<IPaginateScanResponse>('scan', {
200
+ params: serializeProbeQuery(query),
201
+ headers: authHeader(apiKey),
202
+ })
203
+ ).data;
@@ -1,35 +1,35 @@
1
- // Type-level compile test for the probe-scan APPLICATION api surface.
2
- // No jest runner in this SDK package; compile guard only (mirrors
3
- // probe-scan.api.test.ts).
4
- // Run: npx tsc --noEmit (from packages/abyss_probe_core), or `npm run build`.
5
-
6
- import * as api from './probe-scan.application.api';
7
-
8
- // All five functions must be exported with these exact signatures.
9
- const _scan: typeof api.scanApplication = api.scanApplication;
10
- const _scanSync: typeof api.scanSyncApplication = api.scanSyncApplication;
11
- const _scanAsync: typeof api.scanAsyncApplication = api.scanAsyncApplication;
12
- const _getScan: typeof api.getScanApplication = api.getScanApplication;
13
- const _listScans: typeof api.listScansApplication = api.listScansApplication;
14
-
15
- void _scan;
16
- void _scanSync;
17
- void _scanAsync;
18
- void _getScan;
19
- void _listScans;
20
-
21
- // The application client takes the SAME file input as the personal one (it
22
- // reuses buildScanForm verbatim) — abyss-storage, its main caller, hands over
23
- // `await fs.openAsBlob(path)`. A stream is refused at compile time (#519); see
24
- // probe-scan.api.test.ts for the full input matrix.
25
- declare const blob: Blob;
26
- declare const stream: NodeJS.ReadableStream;
27
-
28
- const _fromBlob: Parameters<typeof api.scanSyncApplication>[1] = blob;
29
- // @ts-expect-error a Readable stream is not an accepted scan input since 2.12.0
30
- const _fromStream: Parameters<typeof api.scanSyncApplication>[1] = stream;
31
-
32
- void _fromBlob;
33
- void _fromStream;
34
-
35
- export {};
1
+ // Type-level compile test for the probe-scan APPLICATION api surface.
2
+ // No jest runner in this SDK package; compile guard only (mirrors
3
+ // probe-scan.api.test.ts).
4
+ // Run: npx tsc --noEmit (from packages/abyss_probe_core), or `npm run build`.
5
+
6
+ import * as api from './probe-scan.application.api';
7
+
8
+ // All five functions must be exported with these exact signatures.
9
+ const _scan: typeof api.scanApplication = api.scanApplication;
10
+ const _scanSync: typeof api.scanSyncApplication = api.scanSyncApplication;
11
+ const _scanAsync: typeof api.scanAsyncApplication = api.scanAsyncApplication;
12
+ const _getScan: typeof api.getScanApplication = api.getScanApplication;
13
+ const _listScans: typeof api.listScansApplication = api.listScansApplication;
14
+
15
+ void _scan;
16
+ void _scanSync;
17
+ void _scanAsync;
18
+ void _getScan;
19
+ void _listScans;
20
+
21
+ // The application client takes the SAME file input as the personal one (it
22
+ // reuses buildScanForm verbatim) — abyss-storage, its main caller, hands over
23
+ // `await fs.openAsBlob(path)`. A stream is refused at compile time (#519); see
24
+ // probe-scan.api.test.ts for the full input matrix.
25
+ declare const blob: Blob;
26
+ declare const stream: NodeJS.ReadableStream;
27
+
28
+ const _fromBlob: Parameters<typeof api.scanSyncApplication>[1] = blob;
29
+ // @ts-expect-error a Readable stream is not an accepted scan input since 2.12.0
30
+ const _fromStream: Parameters<typeof api.scanSyncApplication>[1] = stream;
31
+
32
+ void _fromBlob;
33
+ void _fromStream;
34
+
35
+ export {};