@ogcio/building-blocks-sdk 0.2.84 → 0.2.86

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 (52) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/dist/client/clients/messaging/index.d.ts +8 -0
  4. package/dist/client/clients/messaging/index.d.ts.map +1 -1
  5. package/dist/client/clients/messaging/index.js +7 -1
  6. package/dist/client/clients/messaging/index.js.map +1 -1
  7. package/dist/client/clients/messaging/schema.d.ts +154 -0
  8. package/dist/client/clients/messaging/schema.d.ts.map +1 -1
  9. package/dist/client/clients/messaging/support.d.ts +125 -0
  10. package/dist/client/clients/messaging/support.d.ts.map +1 -0
  11. package/dist/client/clients/messaging/support.js +20 -0
  12. package/dist/client/clients/messaging/support.js.map +1 -0
  13. package/dist/client/clients/profile/citizen.d.ts.map +1 -1
  14. package/dist/client/clients/profile/index.d.ts +7 -79
  15. package/dist/client/clients/profile/index.d.ts.map +1 -1
  16. package/dist/client/clients/profile/index.js +13 -20
  17. package/dist/client/clients/profile/index.js.map +1 -1
  18. package/dist/client/clients/profile/organisation.d.ts.map +1 -1
  19. package/dist/client/clients/profile/schema.d.ts +1 -89
  20. package/dist/client/clients/profile/schema.d.ts.map +1 -1
  21. package/dist/client/clients/upload/index.d.ts +23 -0
  22. package/dist/client/clients/upload/index.d.ts.map +1 -1
  23. package/dist/client/clients/upload/index.js +26 -36
  24. package/dist/client/clients/upload/index.js.map +1 -1
  25. package/dist/client/clients/upload/schema.d.ts +321 -0
  26. package/dist/client/clients/upload/schema.d.ts.map +1 -1
  27. package/dist/client/clients/upload/shared.d.ts +47 -0
  28. package/dist/client/clients/upload/shared.d.ts.map +1 -0
  29. package/dist/client/clients/upload/shared.js +72 -0
  30. package/dist/client/clients/upload/shared.js.map +1 -0
  31. package/dist/client/clients/upload/support.d.ts +239 -0
  32. package/dist/client/clients/upload/support.d.ts.map +1 -0
  33. package/dist/client/clients/upload/support.js +73 -0
  34. package/dist/client/clients/upload/support.js.map +1 -0
  35. package/dist/client/utils/client-utils.d.ts +9 -0
  36. package/dist/client/utils/client-utils.d.ts.map +1 -1
  37. package/dist/client/utils/client-utils.js +43 -0
  38. package/dist/client/utils/client-utils.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/client/clients/messaging/index.ts +20 -1
  41. package/src/client/clients/messaging/open-api-definition.json +355 -0
  42. package/src/client/clients/messaging/schema.ts +154 -0
  43. package/src/client/clients/messaging/support.ts +27 -0
  44. package/src/client/clients/profile/index.ts +33 -35
  45. package/src/client/clients/profile/open-api-definition.json +3 -163
  46. package/src/client/clients/profile/schema.ts +1 -89
  47. package/src/client/clients/upload/index.ts +56 -37
  48. package/src/client/clients/upload/open-api-definition.json +621 -41
  49. package/src/client/clients/upload/schema.ts +321 -0
  50. package/src/client/clients/upload/shared.ts +122 -0
  51. package/src/client/clients/upload/support.ts +127 -0
  52. package/src/client/utils/client-utils.ts +59 -0
@@ -143,6 +143,155 @@ export interface paths {
143
143
  patch?: never;
144
144
  trace?: never;
145
145
  };
146
+ "/api/v1/support/files/": {
147
+ parameters: {
148
+ query?: never;
149
+ header?: never;
150
+ path?: never;
151
+ cookie?: never;
152
+ };
153
+ get?: never;
154
+ put?: never;
155
+ post: {
156
+ parameters: {
157
+ query?: never;
158
+ header?: never;
159
+ path?: never;
160
+ cookie?: never;
161
+ };
162
+ requestBody?: {
163
+ content: {
164
+ "multipart/form-data": unknown | unknown;
165
+ };
166
+ };
167
+ responses: {
168
+ /** @description Default Response */
169
+ 201: {
170
+ headers: {
171
+ [name: string]: unknown;
172
+ };
173
+ content: {
174
+ "application/json": {
175
+ data: {
176
+ id: string;
177
+ };
178
+ };
179
+ };
180
+ };
181
+ /** @description Default Response */
182
+ "4XX": {
183
+ headers: {
184
+ [name: string]: unknown;
185
+ };
186
+ content: {
187
+ "application/json": {
188
+ code: string;
189
+ detail: string;
190
+ requestId: string;
191
+ name: string;
192
+ validation?: unknown;
193
+ validationContext?: string;
194
+ };
195
+ };
196
+ };
197
+ /** @description Default Response */
198
+ "5XX": {
199
+ headers: {
200
+ [name: string]: unknown;
201
+ };
202
+ content: {
203
+ "application/json": {
204
+ code: string;
205
+ detail: string;
206
+ requestId: string;
207
+ name: string;
208
+ validation?: unknown;
209
+ validationContext?: string;
210
+ };
211
+ };
212
+ };
213
+ };
214
+ };
215
+ delete?: never;
216
+ options?: never;
217
+ head?: never;
218
+ patch?: never;
219
+ trace?: never;
220
+ };
221
+ "/api/v1/support/files/download-batch": {
222
+ parameters: {
223
+ query?: never;
224
+ header?: never;
225
+ path?: never;
226
+ cookie?: never;
227
+ };
228
+ get?: never;
229
+ put?: never;
230
+ post: {
231
+ parameters: {
232
+ query?: never;
233
+ header?: never;
234
+ path?: never;
235
+ cookie?: never;
236
+ };
237
+ requestBody: {
238
+ content: {
239
+ "application/json": {
240
+ fileIds: string[];
241
+ userId: string;
242
+ };
243
+ };
244
+ };
245
+ responses: {
246
+ /** @description Multipart mixed response containing requested files */
247
+ 200: {
248
+ headers: {
249
+ [name: string]: unknown;
250
+ };
251
+ content: {
252
+ "multipart/mixed": string;
253
+ };
254
+ };
255
+ /** @description Default Response */
256
+ "4XX": {
257
+ headers: {
258
+ [name: string]: unknown;
259
+ };
260
+ content: {
261
+ "application/json": {
262
+ code: string;
263
+ detail: string;
264
+ requestId: string;
265
+ name: string;
266
+ validation?: unknown;
267
+ validationContext?: string;
268
+ };
269
+ };
270
+ };
271
+ /** @description Default Response */
272
+ "5XX": {
273
+ headers: {
274
+ [name: string]: unknown;
275
+ };
276
+ content: {
277
+ "application/json": {
278
+ code: string;
279
+ detail: string;
280
+ requestId: string;
281
+ name: string;
282
+ validation?: unknown;
283
+ validationContext?: string;
284
+ };
285
+ };
286
+ };
287
+ };
288
+ };
289
+ delete?: never;
290
+ options?: never;
291
+ head?: never;
292
+ patch?: never;
293
+ trace?: never;
294
+ };
146
295
  "/api/v1/metadata/": {
147
296
  parameters: {
148
297
  query?: never;
@@ -377,6 +526,93 @@ export interface paths {
377
526
  patch?: never;
378
527
  trace?: never;
379
528
  };
529
+ "/api/v1/support/metadata/": {
530
+ parameters: {
531
+ query?: never;
532
+ header?: never;
533
+ path?: never;
534
+ cookie?: never;
535
+ };
536
+ get: {
537
+ parameters: {
538
+ query?: {
539
+ userId?: string;
540
+ organizationId?: string;
541
+ };
542
+ header?: never;
543
+ path?: never;
544
+ cookie?: never;
545
+ };
546
+ requestBody?: never;
547
+ responses: {
548
+ /** @description Default Response */
549
+ 200: {
550
+ headers: {
551
+ [name: string]: unknown;
552
+ };
553
+ content: {
554
+ "application/json": {
555
+ data: {
556
+ fileName: string;
557
+ id?: string;
558
+ key: string;
559
+ ownerId: string;
560
+ fileSize: number;
561
+ mimeType: string;
562
+ createdAt: string;
563
+ lastScan: string;
564
+ /** @default false */
565
+ deleted: boolean;
566
+ infected: boolean;
567
+ infectionDescription?: string;
568
+ antivirusDbVersion?: string;
569
+ expiresAt?: string;
570
+ }[];
571
+ };
572
+ };
573
+ };
574
+ /** @description Default Response */
575
+ "4XX": {
576
+ headers: {
577
+ [name: string]: unknown;
578
+ };
579
+ content: {
580
+ "application/json": {
581
+ code: string;
582
+ detail: string;
583
+ requestId: string;
584
+ name: string;
585
+ validation?: unknown;
586
+ validationContext?: string;
587
+ };
588
+ };
589
+ };
590
+ /** @description Default Response */
591
+ "5XX": {
592
+ headers: {
593
+ [name: string]: unknown;
594
+ };
595
+ content: {
596
+ "application/json": {
597
+ code: string;
598
+ detail: string;
599
+ requestId: string;
600
+ name: string;
601
+ validation?: unknown;
602
+ validationContext?: string;
603
+ };
604
+ };
605
+ };
606
+ };
607
+ };
608
+ put?: never;
609
+ post?: never;
610
+ delete?: never;
611
+ options?: never;
612
+ head?: never;
613
+ patch?: never;
614
+ trace?: never;
615
+ };
380
616
  "/api/v1/permissions/": {
381
617
  parameters: {
382
618
  query?: never;
@@ -569,6 +805,91 @@ export interface paths {
569
805
  patch?: never;
570
806
  trace?: never;
571
807
  };
808
+ "/api/v1/support/permissions/": {
809
+ parameters: {
810
+ query?: never;
811
+ header?: never;
812
+ path?: never;
813
+ cookie?: never;
814
+ };
815
+ get?: never;
816
+ put?: never;
817
+ post: {
818
+ parameters: {
819
+ query?: never;
820
+ header?: never;
821
+ path?: never;
822
+ cookie?: never;
823
+ };
824
+ requestBody?: {
825
+ content: {
826
+ "application/json": {
827
+ fileId: string;
828
+ userId: string;
829
+ } | {
830
+ fileId: string;
831
+ userIds: string[];
832
+ };
833
+ };
834
+ };
835
+ responses: {
836
+ /** @description Default Response */
837
+ 201: {
838
+ headers: {
839
+ [name: string]: unknown;
840
+ };
841
+ content: {
842
+ "application/json": {
843
+ data: {
844
+ fileId: string;
845
+ userId: string;
846
+ } | {
847
+ fileId: string;
848
+ userIds: string[];
849
+ };
850
+ };
851
+ };
852
+ };
853
+ /** @description Default Response */
854
+ "4XX": {
855
+ headers: {
856
+ [name: string]: unknown;
857
+ };
858
+ content: {
859
+ "application/json": {
860
+ code: string;
861
+ detail: string;
862
+ requestId: string;
863
+ name: string;
864
+ validation?: unknown;
865
+ validationContext?: string;
866
+ };
867
+ };
868
+ };
869
+ /** @description Default Response */
870
+ "5XX": {
871
+ headers: {
872
+ [name: string]: unknown;
873
+ };
874
+ content: {
875
+ "application/json": {
876
+ code: string;
877
+ detail: string;
878
+ requestId: string;
879
+ name: string;
880
+ validation?: unknown;
881
+ validationContext?: string;
882
+ };
883
+ };
884
+ };
885
+ };
886
+ };
887
+ delete?: never;
888
+ options?: never;
889
+ head?: never;
890
+ patch?: never;
891
+ trace?: never;
892
+ };
572
893
  }
573
894
  export type webhooks = Record<string, never>;
574
895
  export interface components {
@@ -0,0 +1,122 @@
1
+ import type createClient from "openapi-fetch";
2
+ import { buildStreamingMultipart } from "../../utils/client-utils.js";
3
+ import type { paths } from "./schema.js";
4
+
5
+ const DEFAULT_TIMEOUT_MS = 120000; // 120 seconds
6
+
7
+ export async function uploadFile(params: {
8
+ file: File;
9
+ expirationDate?: string;
10
+ options?: { timeoutMs?: number };
11
+ client: ReturnType<typeof createClient<paths>>;
12
+ path: "/api/v1/support/files/" | "/api/v1/files/";
13
+ }): Promise<{
14
+ error?: {
15
+ code: string;
16
+ detail: string;
17
+ requestId: string;
18
+ name: string;
19
+ validation?: unknown;
20
+ validationContext?: string;
21
+ };
22
+ data?: { uploadId?: string };
23
+ }> {
24
+ const { file, expirationDate, options, client, path } = params;
25
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
26
+ try {
27
+ const { error, data } = await client.POST(path, {
28
+ body: {
29
+ file,
30
+ expirationDate,
31
+ },
32
+ signal: AbortSignal.timeout(timeoutMs),
33
+ bodySerializer: (body: unknown) => {
34
+ const parsed = body as { file: File; expirationDate?: string };
35
+ const formData = new FormData();
36
+ if (parsed.expirationDate) {
37
+ formData.set("expirationDate", parsed.expirationDate);
38
+ }
39
+ formData.set("file", parsed.file);
40
+ return formData;
41
+ },
42
+ });
43
+
44
+ return { error, data: { uploadId: data?.data.id } };
45
+ } catch (e: unknown) {
46
+ const err = e as Error & { name?: string };
47
+ if (
48
+ err?.name === "AbortError" ||
49
+ err?.constructor?.name === "DOMException"
50
+ ) {
51
+ return {
52
+ error: {
53
+ name: "TimeoutError",
54
+ detail: "Upload aborted after reaching timeout",
55
+ requestId: "",
56
+ code: "TIMEOUT_ERROR",
57
+ },
58
+ };
59
+ }
60
+ throw err;
61
+ }
62
+ }
63
+
64
+ export async function uploadStreamFile(params: {
65
+ file: ReadableStream<Uint8Array> | Blob;
66
+ filename: string;
67
+ mimeType: string;
68
+ expirationDate?: string;
69
+ options?: { timeoutMs?: number };
70
+ client: ReturnType<typeof createClient<paths>>;
71
+ path: "/api/v1/support/files/" | "/api/v1/files/";
72
+ }): Promise<{
73
+ error?: {
74
+ code: string;
75
+ detail: string;
76
+ requestId: string;
77
+ name: string;
78
+ validation?: unknown;
79
+ validationContext?: string;
80
+ };
81
+ data?: { uploadId?: string };
82
+ }> {
83
+ const { file, filename, mimeType, expirationDate, options, client, path } =
84
+ params;
85
+
86
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
87
+ try {
88
+ const stream = file instanceof Blob ? file.stream() : file;
89
+ const { body, contentType } = buildStreamingMultipart(
90
+ stream,
91
+ filename,
92
+ mimeType,
93
+ expirationDate,
94
+ );
95
+
96
+ const { error, data } = await client.POST(path, {
97
+ body: {} as never,
98
+ signal: AbortSignal.timeout(timeoutMs),
99
+ headers: { "content-type": contentType },
100
+ bodySerializer: () => body,
101
+ duplex: "half",
102
+ } as unknown as Parameters<typeof client.POST>[1]);
103
+
104
+ return { error, data: { uploadId: data?.data.id } };
105
+ } catch (e: unknown) {
106
+ const err = e as Error & { name?: string };
107
+ if (
108
+ err?.name === "AbortError" ||
109
+ err?.constructor?.name === "DOMException"
110
+ ) {
111
+ return {
112
+ error: {
113
+ name: "TimeoutError",
114
+ detail: "Upload aborted after reaching timeout",
115
+ requestId: "",
116
+ code: "TIMEOUT_ERROR",
117
+ },
118
+ };
119
+ }
120
+ throw err;
121
+ }
122
+ }
@@ -0,0 +1,127 @@
1
+ import type createClient from "openapi-fetch";
2
+ import type { Logger } from "../../../types/index.js";
3
+ import {
4
+ formatError,
5
+ formatResponse,
6
+ throwIfEmpty,
7
+ } from "../../utils/client-utils.js";
8
+ import type { paths } from "./schema.js";
9
+ import { uploadFile, uploadStreamFile } from "./shared.js";
10
+
11
+ export class UploadSupport {
12
+ constructor(
13
+ private readonly client: ReturnType<typeof createClient<paths>>,
14
+ private readonly serviceName: string,
15
+ private readonly logger: Logger | undefined,
16
+ ) {}
17
+
18
+ async getSharedFilesForUser(
19
+ query: paths["/api/v1/support/metadata/"]["get"]["parameters"]["query"],
20
+ ) {
21
+ const { userId, organizationId } = query || {};
22
+
23
+ return this.client
24
+ .GET("/api/v1/support/metadata/", {
25
+ params: { query: { userId, organizationId } },
26
+ })
27
+ .then(
28
+ (response) => formatResponse(response, this.serviceName, this.logger),
29
+ (reason) => formatError(reason, this.serviceName, this.logger),
30
+ );
31
+ }
32
+
33
+ async getFiles(
34
+ params: paths["/api/v1/support/files/download-batch"]["post"]["requestBody"]["content"]["application/json"],
35
+ ) {
36
+ throwIfEmpty(params.userId);
37
+ try {
38
+ const {
39
+ error,
40
+ data,
41
+ response: { headers, status },
42
+ } = await this.client.POST("/api/v1/support/files/download-batch", {
43
+ body: params,
44
+ parseAs: "stream",
45
+ });
46
+
47
+ return {
48
+ error,
49
+ data,
50
+ headers: Object.fromEntries(headers.entries()),
51
+ status,
52
+ };
53
+ } catch (e) {
54
+ return {
55
+ error: e,
56
+ data: null,
57
+ headers: null,
58
+ status: 500,
59
+ };
60
+ }
61
+ }
62
+
63
+ async uploadFile(
64
+ file: File,
65
+ expirationDate?: string,
66
+ options?: { timeoutMs?: number },
67
+ ): Promise<{
68
+ error?: {
69
+ code: string;
70
+ detail: string;
71
+ requestId: string;
72
+ name: string;
73
+ validation?: unknown;
74
+ validationContext?: string;
75
+ };
76
+ data?: { uploadId?: string };
77
+ }> {
78
+ return uploadFile({
79
+ file,
80
+ expirationDate,
81
+ options,
82
+ client: this.client,
83
+ path: "/api/v1/support/files/",
84
+ });
85
+ }
86
+
87
+ async uploadStreamFile(
88
+ file: ReadableStream<Uint8Array> | Blob,
89
+ filename: string,
90
+ mimeType: string,
91
+ expirationDate?: string,
92
+ options?: { timeoutMs?: number },
93
+ ): Promise<{
94
+ error?: {
95
+ code: string;
96
+ detail: string;
97
+ requestId: string;
98
+ name: string;
99
+ validation?: unknown;
100
+ validationContext?: string;
101
+ };
102
+ data?: { uploadId?: string };
103
+ }> {
104
+ return uploadStreamFile({
105
+ file,
106
+ filename,
107
+ mimeType,
108
+ expirationDate,
109
+ options,
110
+ client: this.client,
111
+ path: "/api/v1/support/files/",
112
+ });
113
+ }
114
+
115
+ shareFile(fileId: string, ...userIds: string[]) {
116
+ throwIfEmpty(fileId);
117
+ throwIfEmpty(userIds);
118
+ return this.client
119
+ .POST("/api/v1/support/permissions/", {
120
+ body: { fileId, userIds },
121
+ })
122
+ .then(
123
+ (response) => formatResponse(response, this.serviceName, this.logger),
124
+ (reason) => formatError(reason, this.serviceName, this.logger),
125
+ );
126
+ }
127
+ }
@@ -163,3 +163,62 @@ export function throwIfEmpty(input: string | string[]): void {
163
163
  throw Error("Parameter cannot be an empty string or array!");
164
164
  }
165
165
  }
166
+
167
+ /**
168
+ * Builds a streaming multipart/form-data body from a ReadableStream without
169
+ * buffering the file content in memory. The returned ReadableStream pipes the
170
+ * file chunks directly into the multipart envelope as they are read.
171
+ */
172
+ export function buildStreamingMultipart(
173
+ stream: ReadableStream<Uint8Array>,
174
+ filename: string,
175
+ mimeType: string,
176
+ expirationDate?: string,
177
+ ): { body: ReadableStream<Uint8Array>; contentType: string } {
178
+ const boundary = `----FormBoundary${crypto.randomUUID().replace(/-/g, "")}`;
179
+ const encoder = new TextEncoder();
180
+ // Sanitize filename to prevent Content-Disposition header injection
181
+ const safeFilename = filename.replace(/["\\\r\n]/g, "_");
182
+
183
+ const parts: (Uint8Array | ReadableStream<Uint8Array>)[] = [];
184
+
185
+ if (expirationDate) {
186
+ parts.push(
187
+ encoder.encode(
188
+ `--${boundary}\r\nContent-Disposition: form-data; name="expirationDate"\r\n\r\n${expirationDate}\r\n`,
189
+ ),
190
+ );
191
+ }
192
+
193
+ parts.push(
194
+ encoder.encode(
195
+ `--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="${safeFilename}"\r\nContent-Type: ${mimeType}\r\n\r\n`,
196
+ ),
197
+ );
198
+ parts.push(stream);
199
+ parts.push(encoder.encode(`\r\n--${boundary}--\r\n`));
200
+
201
+ const body = new ReadableStream<Uint8Array>({
202
+ async start(controller) {
203
+ for (const part of parts) {
204
+ if (part instanceof Uint8Array) {
205
+ controller.enqueue(part);
206
+ } else {
207
+ const reader = part.getReader();
208
+ try {
209
+ while (true) {
210
+ const { done, value } = await reader.read();
211
+ if (done) break;
212
+ controller.enqueue(value);
213
+ }
214
+ } finally {
215
+ reader.releaseLock();
216
+ }
217
+ }
218
+ }
219
+ controller.close();
220
+ },
221
+ });
222
+
223
+ return { body, contentType: `multipart/form-data; boundary=${boundary}` };
224
+ }