iom-sdk 0.1.18 → 0.2.3

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.
@@ -0,0 +1,68 @@
1
+ /**
2
+ * File storage service client.
3
+ *
4
+ * Orchestrates: init → (single-shot PUT | parallel part PUTs) → complete.
5
+ *
6
+ * Design notes:
7
+ * - **`fetch` (not axios) for S3 PUTs.** Axios attaches request interceptors
8
+ * in the parent `Client` that add `Authorization: Bearer …`. That header
9
+ * invalidates an S3 presignature. Using `fetch` (no interceptors) makes
10
+ * accidental JWT leakage to S3 mechanically impossible.
11
+ * - **Blob body, never `arrayBuffer()`.** Passing a `Blob` to `fetch` lets
12
+ * the browser stream the bytes. Calling `await partBlob.arrayBuffer()`
13
+ * would materialize each part into a fresh `ArrayBuffer`, doubling peak
14
+ * memory per active part.
15
+ * - **URLs come from the init response, not a separate `/part-urls` call.**
16
+ * Backend pre-signs all parts up front. Refresh is on-demand for the
17
+ * subset that expires.
18
+ * - **`partSize` comes from the init response** — never hardcoded. When the
19
+ * backend later tiers part size by file size, this SDK is unaffected.
20
+ * - **Per-part retry with exponential backoff + jitter** for transient
21
+ * 5xx/408/429/network. Distinct from S3-403 expiry which uses
22
+ * `refreshUploadUrls` then retries.
23
+ * - **Proactive URL refresh at T-60s.** When the per-batch `expiresAt`
24
+ * approaches, refresh the URLs of any still-pending parts in one call.
25
+ * - **Progress throttled to ~10 Hz**, monotonic (max prev/next). Prevents
26
+ * React re-render storms when 6 parts emit progress concurrently.
27
+ */
28
+ import { AxiosInstance } from 'axios';
29
+ import { ServiceConfig, ErrorHandlingConfig } from '../../config';
30
+ import { CompletedPart, DownloadUrlResponse, FileMetadataResponseDTO, FileStorageCompleteResponseDTO, FileStorageInitDTO, FileStorageInitResponseDTO, PreviewUrlResponse, RequestOptions, UploadFileInput } from '../../types';
31
+ import { Sha256Hasher } from './sha256-worker';
32
+ export declare class FileStorageServiceClient {
33
+ private axios;
34
+ /** Override in tests / mock client. */
35
+ private hasherFactory;
36
+ constructor(_config: ServiceConfig, _errorHandling: ErrorHandlingConfig, axios: AxiosInstance,
37
+ /** Override in tests / mock client. */
38
+ hasherFactory?: () => Sha256Hasher);
39
+ initUpload(body: FileStorageInitDTO, opts?: RequestOptions): Promise<FileStorageInitResponseDTO>;
40
+ /**
41
+ * Refresh presigned URLs for an in-flight upload. Pass `partNumbers` to
42
+ * refresh only specific parts (response `urls` come back in the same
43
+ * order). Pass nothing / empty to refresh all parts.
44
+ *
45
+ * Returns the full init-response shape — `uploadId`, `fileReference`,
46
+ * `urls`, `partSize`, `expiresAt`. The session and part numbers are
47
+ * preserved; only the URLs (and the `expiresAt` TTL) change.
48
+ */
49
+ refreshUploadUrls(uploadId: string, partNumbers?: number[], opts?: RequestOptions): Promise<FileStorageInitResponseDTO>;
50
+ completeUpload(uploadId: string, parts: CompletedPart[], opts?: RequestOptions): Promise<FileStorageCompleteResponseDTO>;
51
+ /**
52
+ * Best-effort abort with a 2s timeout. Never throws — callers (cancel paths,
53
+ * `pagehide`) shouldn't be blocked by a failing cleanup call. The backend
54
+ * relies on the S3 lifecycle rule `AbortIncompleteMultipartUpload` to
55
+ * reclaim storage if this call doesn't reach the server.
56
+ */
57
+ abortUpload(uploadId: string): Promise<void>;
58
+ getMetadata(fileReference: string, opts?: RequestOptions): Promise<FileMetadataResponseDTO>;
59
+ /**
60
+ * Soft-delete a file. Status flips to `DELETED`, bytes stay in the bucket,
61
+ * preview/download return 404. There is intentionally no hard delete.
62
+ */
63
+ softDelete(fileReference: string, opts?: RequestOptions): Promise<void>;
64
+ getPreviewUrl(fileReference: string, opts?: RequestOptions): Promise<PreviewUrlResponse>;
65
+ getDownloadUrl(fileReference: string): DownloadUrlResponse;
66
+ uploadFile(input: UploadFileInput): Promise<FileStorageCompleteResponseDTO>;
67
+ private runMultipart;
68
+ }
@@ -0,0 +1,3 @@
1
+ export { FileStorageServiceClient } from './file-storage-client';
2
+ export { createSha256Hasher } from './sha256-worker';
3
+ export type { Sha256Hasher } from './sha256-worker';
@@ -0,0 +1,13 @@
1
+ export interface Sha256Hasher {
2
+ /** Full-file SHA-256 as lowercase hex (for `InitUploadRequest.sha256`). */
3
+ hashFullFile(blob: Blob, signal?: AbortSignal): Promise<string>;
4
+ /** Per-part SHA-256 as base64 (for `x-amz-checksum-sha256` header). */
5
+ hashPart(blob: Blob, signal?: AbortSignal): Promise<string>;
6
+ /** Idempotent. Frees any worker resources when called. */
7
+ dispose(): void;
8
+ }
9
+ /**
10
+ * Factory — returns a hasher implementation. Today always main-thread;
11
+ * once the worker is wired up, this picks based on `typeof Worker`.
12
+ */
13
+ export declare function createSha256Hasher(): Sha256Hasher;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Hash a Blob to lowercase hex.
3
+ *
4
+ * Reads the blob in 1 MiB chunks. The `AbortSignal` is honored between chunks;
5
+ * mid-chunk aborts wait for the active read to settle (cheap — chunks are 1 MiB).
6
+ */
7
+ export declare function sha256Hex(blob: Blob, options?: {
8
+ signal?: AbortSignal;
9
+ }): Promise<string>;
10
+ /**
11
+ * Hash a Blob to base64 (the encoding S3 expects in `x-amz-checksum-sha256`).
12
+ *
13
+ * `hash-wasm` returns hex; we convert at the end. Cheaper than a separate
14
+ * binary digest because the final digest is only 32 bytes.
15
+ */
16
+ export declare function sha256Base64(blob: Blob, options?: {
17
+ signal?: AbortSignal;
18
+ }): Promise<string>;
19
+ /** Convert a hex string (any case) to base64 without intermediate allocations. */
20
+ export declare function hexToBase64(hex: string): string;
@@ -7,3 +7,4 @@ export * from './registry';
7
7
  export * from './node';
8
8
  export * from './up';
9
9
  export * from './user';
10
+ export * from './fileStorage';
@@ -1,7 +1,7 @@
1
1
  import { AxiosInstance } from 'axios';
2
2
  import { ServiceConfig, ErrorHandlingConfig } from '../../config';
3
3
  import { RegistryServiceClient } from '../registry/registry-client';
4
- import { UUID, UUObjectDTO, UUPropertyDTO, UUPropertyValueDTO, UUStatementDTO, UUFileDTO, UUFileFindRequestDTO, UUAddressDTO, QueryParams, UUStatementsAccessFindDTO, AggregateCreateDTO, AggregateEntity, AggregateFindDTO, PageAggregateEntity, ApiResponse, RequestOptions, GroupCreateDTO, GroupAddRecordsDTO, GroupListParams, GroupRecord, PageImplGroupFullDTO, UUMathFormulaDTO, UUMathFormulaCalcDTO, UUMathFormulaFindDTO, UUMathFormulaCalcFindDTO } from '../../types';
4
+ import { UUID, UUObjectDTO, UUPropertyDTO, UUPropertyValueDTO, UUStatementDTO, UUFileDTO, UUAddressDTO, QueryParams, NodeFindRequestDTO, UUStatementsAccessFindDTO, AggregateCreateDTO, AggregateEntity, AggregateFindDTO, PageAggregateEntity, ApiResponse, RequestOptions, GroupCreateDTO, GroupAddRecordsDTO, GroupListParams, PageImplGroupFullDTO, PageImplGroupRecord, UUMathFormulaDTO, UUMathFormulaCalcDTO, UUMathFormulaCalcFindDTO, NodeFindDTO, PageUUMathFormula } from '../../types';
5
5
  export declare class NodeServiceClient {
6
6
  private errorHandling;
7
7
  private axios;
@@ -20,7 +20,6 @@ export declare class NodeServiceClient {
20
20
  softDeleteProperty(uuid: UUID): Promise<{
21
21
  success: boolean;
22
22
  }>;
23
- getPropertyValues(params?: QueryParams, options?: RequestOptions): Promise<UUPropertyValueDTO[]>;
24
23
  createOrUpdatePropertyValue(value: UUPropertyValueDTO): Promise<UUPropertyValueDTO>;
25
24
  createPropertyValue(value: Omit<UUPropertyValueDTO, 'uuid'>): Promise<UUPropertyValueDTO>;
26
25
  softDeletePropertyValue(uuid: UUID): Promise<{
@@ -44,30 +43,25 @@ export declare class NodeServiceClient {
44
43
  softDeleteStatement(subject: UUID, predicate: string, object: UUID): Promise<{
45
44
  success: boolean;
46
45
  }>;
47
- getFiles(params?: QueryParams, options?: RequestOptions): Promise<UUFileDTO[]>;
48
46
  /**
49
- * Create or update a UUFile record.
50
- * POST /api/UUFile — send binary bytes via `fileContentBase64`. The server
51
- * determines `size` and ignores `contentType` / `fileReference` logic.
47
+ * Create or update a UUFile record (metadata only).
48
+ *
49
+ * Bytes-in-Mongo is gone. For first-party uploads, run
50
+ * `client.fileStorage.uploadFile(...)` first and pass the returned
51
+ * `fileReference` here along with `fileName`, `contentType`, and `size`.
52
+ * For external URL attachments, pass the URL as `fileReference`.
52
53
  */
53
54
  createOrUpdateFile(file: UUFileDTO): Promise<UUFileDTO>;
54
- getFile(uuid: UUID, options?: RequestOptions): Promise<UUFileDTO>;
55
55
  /**
56
56
  * Find UUFile records via POST /api/UUFile/find.
57
- * Set `includeFileContentBase64=true` + `nodeFind.uuid` with
58
- * `softDeleted=false` to receive the file bytes in `fileContentBase64`.
59
- * Otherwise content is always excluded from the response.
57
+ * Returns metadata only bytes are served by the FileStorage service via
58
+ * `client.fileStorage.getPreviewUrl(fileReference)` /
59
+ * `getDownloadUrl(fileReference)`.
60
60
  */
61
- findFiles(body: UUFileFindRequestDTO, options?: RequestOptions): Promise<UUFileDTO[]>;
62
- /**
63
- * Fetch a single file's base64 content by UUID.
64
- * Returns null if the file is not found or has no content.
65
- */
66
- getFileContent(uuid: UUID, options?: RequestOptions): Promise<string | null>;
61
+ findFiles(body: NodeFindRequestDTO, options?: RequestOptions): Promise<UUFileDTO[]>;
67
62
  softDeleteFile(uuid: UUID): Promise<{
68
63
  success: boolean;
69
64
  }>;
70
- getAddresses(params?: QueryParams, options?: RequestOptions): Promise<UUAddressDTO[]>;
71
65
  createOrUpdateAddress(address: UUAddressDTO): Promise<UUAddressDTO>;
72
66
  createAddress(address: Omit<UUAddressDTO, 'uuid'>): Promise<UUAddressDTO>;
73
67
  softDeleteAddress(uuid: UUID): Promise<{
@@ -88,18 +82,6 @@ export declare class NodeServiceClient {
88
82
  contentType?: string;
89
83
  size?: number;
90
84
  }): Promise<ApiResponse<UUFileDTO | null>>;
91
- /**
92
- * Upload a file's binary content directly.
93
- * Complete flow:
94
- * 1) Create UUID for the file
95
- * 2) Encode file bytes as base64 and POST to /api/UUFile
96
- * 3) Create statement to link file to parent object
97
- */
98
- uploadFileDirect(input: {
99
- file: File | Blob;
100
- uuidToAttach: UUID;
101
- label?: string;
102
- }): Promise<ApiResponse<UUFileDTO | null>>;
103
85
  addPropertyToObject(objectUuid: UUID, property: Partial<UUPropertyDTO> & {
104
86
  key: string;
105
87
  }): Promise<ApiResponse<UUPropertyDTO>>;
@@ -125,10 +107,20 @@ export declare class NodeServiceClient {
125
107
  */
126
108
  getGroup(groupUUID: UUID, options?: RequestOptions): Promise<GroupCreateDTO>;
127
109
  /**
128
- * List records in a group
110
+ * List records in a group (paginated)
129
111
  * GET /api/access/groups/{groupUUID}/records
130
112
  */
131
- listGroupRecords(groupUUID: UUID, options?: RequestOptions): Promise<GroupRecord[]>;
113
+ listGroupRecords(groupUUID: UUID, params?: GroupListParams, options?: RequestOptions): Promise<PageImplGroupRecord>;
114
+ /**
115
+ * List groups owned by the authenticated user (non-default only, paginated)
116
+ * GET /api/access/groups/own
117
+ */
118
+ listOwnGroups(params?: GroupListParams, options?: RequestOptions): Promise<PageImplGroupFullDTO>;
119
+ /**
120
+ * List groups explicitly shared with the authenticated user (paginated)
121
+ * GET /api/access/groups/shared
122
+ */
123
+ listSharedGroups(params?: GroupListParams, options?: RequestOptions): Promise<PageImplGroupFullDTO>;
132
124
  /**
133
125
  * Add records to a group
134
126
  * POST /api/access/groups/{groupUUID}/records
@@ -140,10 +132,15 @@ export declare class NodeServiceClient {
140
132
  */
141
133
  createOrUpdateMathFormula(formula: UUMathFormulaDTO): Promise<UUMathFormulaDTO>;
142
134
  /**
143
- * Search math formulas
144
- * POST /api/UUMathFormula/find
135
+ * Search math formulas.
136
+ * POST /api/UUMathFormula/find — returns a Spring `Page<UUMathFormula>`
137
+ * envelope. Access `result.content` for the rows; pagination + audit
138
+ * fields live alongside.
145
139
  */
146
- searchMathFormulas(body: UUMathFormulaFindDTO, options?: RequestOptions): Promise<UUMathFormulaDTO[]>;
140
+ searchMathFormulas(body: NodeFindDTO, params?: {
141
+ page?: number;
142
+ size?: number;
143
+ }, options?: RequestOptions): Promise<PageUUMathFormula>;
147
144
  /**
148
145
  * Soft delete a math formula
149
146
  * DELETE /api/UUMathFormula/{uuid}
@@ -15,19 +15,10 @@ export interface UUIDRecord {
15
15
  export interface UUIDCreationResponse {
16
16
  uuid: string;
17
17
  }
18
- export interface UUIDAuthParams {
19
- uuid: string;
20
- userUUID: string;
21
- resourceId: string;
22
- }
23
18
  export declare class RegistryServiceClient {
24
19
  private axios;
25
20
  constructor(_config: ServiceConfig, _errorHandling: ErrorHandlingConfig, axios: AxiosInstance);
26
- getOwnedUUIDs(): Promise<UUIDRecord[]>;
27
21
  createUUID(): Promise<UUIDCreationResponse>;
28
22
  getUUIDRecord(uuid: UUID): Promise<UUIDRecord>;
29
23
  updateUUIDRecordMeta(uuid: UUID, meta: Record<string, any>): Promise<UUIDRecord>;
30
- authorizeUUIDRecord(params: UUIDAuthParams): Promise<{
31
- success: boolean;
32
- }>;
33
24
  }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * File storage service DTOs.
3
+ *
4
+ * Shape sourced from `docs/filestorage.swagger.json`. Field names mirror the
5
+ * swagger exactly (`mimeType` not `contentType`, `fileReference` not
6
+ * `fileUuid`, `checksumSHA256` not `sha256` on `PartETag`).
7
+ *
8
+ * Flow after a successful upload:
9
+ * 1. `client.fileStorage.uploadFile(...)` → returns `FileStorageCompleteResponseDTO`
10
+ * with `fileReference`.
11
+ * 2. Caller then registers the file with the node-network registry via
12
+ * `client.node.createOrUpdateFile({ fileReference, fileName, contentType,
13
+ * size, ... })` so the UUFile record can be attached to an object/property.
14
+ *
15
+ * The FileStorage service is bytes-only; node-network is records-and-relations.
16
+ */
17
+ /**
18
+ * Request body for `POST /api/FileStorage/init`.
19
+ *
20
+ * `sha256` is hex-encoded (lowercase). All three required fields are
21
+ * server-validated; mismatches surface as 400 `InvalidRequest`.
22
+ */
23
+ export interface FileStorageInitDTO {
24
+ fileName: string;
25
+ mimeType: string;
26
+ /** Bytes; min 1. int64 server-side. */
27
+ size: number;
28
+ /** Hex-encoded full-file SHA-256, lowercase. */
29
+ sha256: string;
30
+ }
31
+ /**
32
+ * Response from `POST /api/FileStorage/init` and `POST /{uploadId}/refresh`.
33
+ *
34
+ * Note: `urls.length === 1` and `partSize === null` together signal the
35
+ * single-shot path. Otherwise this is a multipart upload and the caller
36
+ * PUTs `file.slice((i-1)*partSize, i*partSize)` to `urls[i-1]`.
37
+ *
38
+ * `expiresAt` applies to every URL in `urls` — there is no per-URL expiry.
39
+ */
40
+ export interface FileStorageInitResponseDTO {
41
+ uploadId: string;
42
+ fileReference: string;
43
+ urls: string[];
44
+ /** Bytes per part; null for single-shot. */
45
+ partSize: number | null;
46
+ /** ISO-8601 timestamp — all URLs in `urls` expire at this moment. */
47
+ expiresAt: string;
48
+ /**
49
+ * When `true`, the presigned PUT URLs include `x-amz-checksum-sha256` in
50
+ * their `SignedHeaders` and the SDK must send a base64 per-part SHA-256
51
+ * with every PUT (S3 verifies on the spot). When `false`/missing, the
52
+ * SDK skips the header — a stray header on a `SignedHeaders=host` URL
53
+ * would 403 with `SignatureDoesNotMatch`.
54
+ */
55
+ checksumValidation?: boolean;
56
+ }
57
+ /**
58
+ * Request body for `POST /api/FileStorage/{uploadId}/refresh`.
59
+ *
60
+ * When `partNumbers` is omitted or empty, the server returns fresh URLs for
61
+ * every part in the original init batch. When provided, the response `urls`
62
+ * array contains URLs only for those part numbers, in the same order. Pass
63
+ * the missing parts only to keep refresh responses small for huge multipart
64
+ * uploads.
65
+ */
66
+ export interface FileStorageRefreshDTO {
67
+ partNumbers?: number[];
68
+ }
69
+ /**
70
+ * A completed part with its server-returned ETag.
71
+ *
72
+ * `checksumSHA256` is optional. When the SDK computes per-part SHA-256 it
73
+ * sends the base64-encoded digest here so the server can pass it through to
74
+ * S3's per-part integrity check (`x-amz-checksum-sha256`).
75
+ */
76
+ export interface PartETag {
77
+ partNumber: number;
78
+ etag: string;
79
+ /** Base64-encoded per-part SHA-256. Omit if not computed. */
80
+ checksumSHA256?: string;
81
+ }
82
+ /**
83
+ * Request body for `POST /api/FileStorage/{uploadId}/complete`.
84
+ *
85
+ * Single-shot uploads (where `urls.length === 1`) still send a one-element
86
+ * `parts` array with `partNumber: 1` and the ETag returned from the single
87
+ * PUT. The server uses the array length to dispatch single-shot vs multipart
88
+ * completion internally.
89
+ */
90
+ export interface FileStorageCompleteDTO {
91
+ parts: PartETag[];
92
+ }
93
+ /** Lifecycle states surfaced via `status` on metadata + complete responses. */
94
+ export type FileStatus = 'PENDING' | 'UPLOADING' | 'READY' | 'FAILED' | 'DELETED';
95
+ /**
96
+ * Response from `POST /api/FileStorage/{uploadId}/complete`.
97
+ *
98
+ * `status` is normally `READY`. If size/SHA-256 verification fails the
99
+ * server returns `FAILED` and the bytes are reclaimed.
100
+ */
101
+ export interface FileStorageCompleteResponseDTO {
102
+ fileReference: string;
103
+ fileName: string;
104
+ mimeType: string;
105
+ size: number;
106
+ status: FileStatus;
107
+ }
108
+ import type { AuditUser } from './aggregates';
109
+ /**
110
+ * Response from `GET /api/FileStorage/{fileReference}`.
111
+ *
112
+ * Carries the `mimeType` that was previously on `PreviewUrlResponseDTO`.
113
+ * Fetch this alongside `getPreviewUrl` when the consumer needs to pick the
114
+ * right preview element (image vs PDF vs video).
115
+ */
116
+ export interface FileMetadataResponseDTO {
117
+ fileReference: string;
118
+ fileName: string;
119
+ mimeType: string;
120
+ size: number;
121
+ /** Hex-encoded full-file SHA-256 (lowercase) — what the client sent at init. */
122
+ sha256: string;
123
+ status: FileStatus;
124
+ createdBy: AuditUser;
125
+ /** ISO-8601. */
126
+ createdAt: string;
127
+ }
128
+ /**
129
+ * Response from `GET /api/FileStorage/{fileReference}/preview-url`.
130
+ *
131
+ * The URL has `response-content-disposition=inline` baked in by the server
132
+ * for whitelisted MIME types; for everything else the server bakes in
133
+ * `attachment` to neutralize stored-XSS via MIME spoofing.
134
+ */
135
+ export interface PreviewUrlResponseDTO {
136
+ url: string;
137
+ /** ISO-8601. */
138
+ expiresAt: string;
139
+ }
140
+ export type InitUploadRequest = FileStorageInitDTO;
141
+ export type InitUploadResponse = FileStorageInitResponseDTO;
142
+ export type RefreshUrlsRequest = FileStorageRefreshDTO;
143
+ export type CompletedPart = PartETag;
144
+ export type CompleteUploadRequest = FileStorageCompleteDTO;
145
+ export type CompleteUploadResponse = FileStorageCompleteResponseDTO;
146
+ export type FileMetadata = FileMetadataResponseDTO;
147
+ export type PreviewUrlResponse = PreviewUrlResponseDTO;
148
+ /**
149
+ * URL of `GET /api/FileStorage/{fileReference}/download` — unauthenticated
150
+ * endpoint that 302-redirects to a presigned S3 URL with
151
+ * `Content-Disposition: attachment` baked in. The SDK builds this synchronously;
152
+ * the browser navigates and S3 serves the download.
153
+ */
154
+ export interface DownloadUrlResponse {
155
+ url: string;
156
+ }
157
+ /**
158
+ * Typed errors thrown by `FileStorageServiceClient`. Map RFC 7807 ProblemDetails
159
+ * from the backend + S3-side errors into one of these kinds.
160
+ *
161
+ * - `BadDigest` / `ChecksumMismatch` — content hash mismatch (S3 / backend).
162
+ * - `InvalidRequest` — 400-class validation failure.
163
+ * - `NotFound` — file or uploadId doesn't exist.
164
+ * - `Expired` — presigned URL expired (parse S3 XML `AccessDenied`).
165
+ * - `Forbidden` — terminal 403 (e.g. `SignatureDoesNotMatch`).
166
+ * - `Throttled` — 429; honor `retryAfter`.
167
+ * - `QuotaExceeded` — storage quota.
168
+ * - `CorsOrNetwork` — fetch threw TypeError ("Failed to fetch") — typically
169
+ * a CORS misconfig on the bucket. Distinct from a real network failure
170
+ * so we surface a useful message during deployment.
171
+ * - `Aborted` — `AbortSignal` fired.
172
+ */
173
+ export type FileStorageErrorKind = 'BadDigest' | 'ChecksumMismatch' | 'InvalidRequest' | 'NotFound' | 'Expired' | 'Forbidden' | 'Throttled' | 'QuotaExceeded' | 'CorsOrNetwork' | 'Aborted';
174
+ export declare class FileStorageError extends Error {
175
+ readonly kind: FileStorageErrorKind;
176
+ /** Seconds; populated for `Throttled` from the `Retry-After` header. */
177
+ readonly retryAfter?: number;
178
+ /** Underlying cause (axios error, fetch TypeError, S3 XML body, etc.) — debug only. */
179
+ readonly cause?: unknown;
180
+ constructor(kind: FileStorageErrorKind, message: string, options?: {
181
+ retryAfter?: number;
182
+ cause?: unknown;
183
+ });
184
+ }
185
+ /**
186
+ * Input to `FileStorageServiceClient.uploadFile()`.
187
+ *
188
+ * `concurrency` controls per-file part parallelism (default 6, cap 8). For
189
+ * the global file concurrency cap, see `FileUploadService` in the UI.
190
+ */
191
+ export interface UploadFileInput {
192
+ file: File | Blob;
193
+ fileName?: string;
194
+ contentType?: string;
195
+ onProgress?: (loaded: number, total: number) => void;
196
+ signal?: AbortSignal;
197
+ concurrency?: number;
198
+ }
@@ -68,3 +68,31 @@ export interface GroupRecord {
68
68
  groupUUID?: string;
69
69
  recordUUID?: string;
70
70
  }
71
+ export interface PageImplGroupRecord {
72
+ totalPages: number;
73
+ totalElements: number;
74
+ size: number;
75
+ content: GroupRecord[];
76
+ number: number;
77
+ numberOfElements: number;
78
+ first: boolean;
79
+ last: boolean;
80
+ empty: boolean;
81
+ pageable: {
82
+ paged: boolean;
83
+ pageNumber: number;
84
+ pageSize: number;
85
+ offset: number;
86
+ sort: {
87
+ sorted: boolean;
88
+ empty: boolean;
89
+ unsorted: boolean;
90
+ };
91
+ unpaged: boolean;
92
+ };
93
+ sort: {
94
+ sorted: boolean;
95
+ empty: boolean;
96
+ unsorted: boolean;
97
+ };
98
+ }
@@ -9,3 +9,4 @@ export * from './aggregates';
9
9
  export * from './groups';
10
10
  export * from './math-formulas';
11
11
  export * from './user';
12
+ export * from './file-storage';
@@ -1,10 +1,14 @@
1
1
  /**
2
- * Math Formula and Calculation types (from Swagger documentation)
2
+ * Math Formula and Calculation types.
3
+ *
4
+ * Shape sourced from `docs/node.swagger.json`. Write-side uses the lean
5
+ * `*DTO` shapes; read-side (find responses) returns the full entity with
6
+ * audit fields wrapped in a Spring `Page<T>` envelope.
3
7
  */
4
- import { UUID } from './services';
8
+ import { NodeFindDTO, UUID } from './services';
9
+ import type { AuditUser } from './aggregates';
5
10
  /**
6
- * UUMathFormula Data Transfer Object
7
- * Represents a reusable math formula definition
11
+ * UUMathFormulaDTO request body for `POST /api/UUMathFormula`.
8
12
  */
9
13
  export interface UUMathFormulaDTO {
10
14
  uuid: UUID;
@@ -15,8 +19,8 @@ export interface UUMathFormulaDTO {
15
19
  version?: string;
16
20
  }
17
21
  /**
18
- * UUMathFormulaCalc Data Transfer Object
19
- * Represents a calculation instance that links a formula to property values
22
+ * UUMathFormulaCalcDTO request body for `POST /api/UUMathFormulaCalc`.
23
+ * Links a formula to concrete property-value bindings + output target.
20
24
  */
21
25
  export interface UUMathFormulaCalcDTO {
22
26
  uuid: UUID;
@@ -24,47 +28,79 @@ export interface UUMathFormulaCalcDTO {
24
28
  args: UUMathFormulaCalcArg[];
25
29
  result: UUMathFormulaCalcResult;
26
30
  }
27
- /**
28
- * Argument for a formula calculation - maps a variable name to a property value
29
- */
31
+ /** Maps a variable name in the expression to a property-value UUID. */
30
32
  export interface UUMathFormulaCalcArg {
31
33
  name: string;
32
34
  propertyValueUUID: UUID;
33
35
  }
34
- /**
35
- * Result of a formula calculation - references the output property value
36
- */
36
+ /** References the property-value UUID that will receive the computed result. */
37
37
  export interface UUMathFormulaCalcResult {
38
38
  propertyValueUUID: UUID;
39
39
  }
40
40
  /**
41
- * Search parameters for finding math formulas
41
+ * UUMathFormula entity shape returned by `POST /api/UUMathFormula/find`.
42
+ * Adds audit + soft-delete fields on top of the DTO shape.
42
43
  */
43
- export interface UUMathFormulaFindDTO {
44
- uuid?: UUID;
44
+ export interface UUMathFormula {
45
+ uuid: UUID;
45
46
  name?: string;
46
- groupUUID?: UUID;
47
+ expression?: string;
48
+ description?: string;
49
+ version?: string;
50
+ createdAt?: string;
51
+ createdBy?: AuditUser;
52
+ lastUpdatedAt?: string;
53
+ lastUpdatedBy?: AuditUser;
54
+ softDeletedAt?: string;
55
+ softDeleteBy?: AuditUser;
47
56
  softDeleted?: boolean;
48
- accessFind?: {
49
- readDefaultGroup?: boolean;
50
- readOwnGroups?: boolean;
51
- readPublicGroups?: boolean;
52
- readUserSharedGroups?: boolean;
53
- groupUUIDList?: string[];
54
- };
55
57
  }
56
58
  /**
57
- * Search parameters for finding formula calculations
59
+ * Request body for `POST /api/UUMathFormula/find`. Swagger requires only
60
+ * `{ nodeFind, page, size }` — past flattened fields (`uuid`, `name`, etc.)
61
+ * are no longer accepted at the top level.
62
+ */
63
+ export interface UUMathFormulaFindDTO {
64
+ nodeFind?: NodeFindDTO;
65
+ /** Zero-based page index. */
66
+ page?: number;
67
+ /** Page size. */
68
+ size?: number;
69
+ }
70
+ /**
71
+ * UUMathFormulaCalc find still routes through the generic
72
+ * `NodeFindRequestDTO` (page response is `object` in swagger — kept loose
73
+ * here until the backend tightens the contract).
58
74
  */
59
75
  export interface UUMathFormulaCalcFindDTO {
60
- uuid?: UUID;
61
- groupUUID?: UUID;
62
- softDeleted?: boolean;
63
- accessFind?: {
64
- readDefaultGroup?: boolean;
65
- readOwnGroups?: boolean;
66
- readPublicGroups?: boolean;
67
- readUserSharedGroups?: boolean;
68
- groupUUIDList?: string[];
69
- };
76
+ nodeFind?: NodeFindDTO;
77
+ page?: number;
78
+ size?: number;
79
+ }
80
+ export interface SortObject {
81
+ sorted?: boolean;
82
+ unsorted?: boolean;
83
+ empty?: boolean;
84
+ }
85
+ export interface PageableObject {
86
+ paged?: boolean;
87
+ unpaged?: boolean;
88
+ pageNumber?: number;
89
+ pageSize?: number;
90
+ offset?: number;
91
+ sort?: SortObject;
92
+ }
93
+ /** Spring `Page<UUMathFormula>` envelope. */
94
+ export interface PageUUMathFormula {
95
+ content?: UUMathFormula[];
96
+ totalElements?: number;
97
+ totalPages?: number;
98
+ number?: number;
99
+ size?: number;
100
+ numberOfElements?: number;
101
+ first?: boolean;
102
+ last?: boolean;
103
+ empty?: boolean;
104
+ pageable?: PageableObject;
105
+ sort?: SortObject;
70
106
  }
@@ -108,17 +108,16 @@ export interface UUFileDTO {
108
108
  label?: string;
109
109
  contentType?: string;
110
110
  size?: number;
111
- fileContentBase64?: string;
112
111
  }
113
112
  export interface NodeFindDTO {
114
113
  uuid?: UUID;
115
114
  softDeleted?: boolean;
116
115
  }
117
- export interface UUFileFindRequestDTO {
116
+ export interface NodeFindRequestDTO {
118
117
  nodeFind?: NodeFindDTO;
119
118
  accessFind?: AccessFindDTO;
120
- includeFileContentBase64?: boolean;
121
119
  }
120
+ export type UUFileFindRequestDTO = NodeFindRequestDTO;
122
121
  export interface UUAddressDTO {
123
122
  uuid: UUID;
124
123
  groupUUID?: UUID;
@@ -2,4 +2,3 @@
2
2
  * Utility functions export
3
3
  */
4
4
  export * from './jwt-utils';
5
- export * from './base64';