@redacto.io/consent-sdk-react-native 2.2.0 → 3.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,8 +47,8 @@ pnpm add expo-audio
47
47
 
48
48
  The SDK never talks to Redacto with your CMS API key directly — your backend acts as a token broker. Obtain your **CMS-API-Key** from the Redacto Dashboard, store it in your backend's environment, and expose two endpoints to your mobile app:
49
49
 
50
- 1. **Generate access token** — `POST /public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/generate-access-token`
51
- 2. **Refresh access token** — `POST /consent/public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/refresh-token`
50
+ 1. **Generate access token** — `POST /public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/generate`
51
+ 2. **Refresh access token** — `POST /consent/public/organisations/{org_uuid}/workspaces/{workspace_uuid}/tokens/refresh`
52
52
 
53
53
  Both endpoints expect the `X-CMS-API-Key` header. Example (Express):
54
54
 
@@ -66,7 +66,7 @@ app.post("/api/consent/token", async (req, res) => {
66
66
  const { organisation_uuid, workspace_uuid, base_url } = req.query;
67
67
 
68
68
  const response = await axios.post(
69
- `${base_url}/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/generate-access-token`,
69
+ `${base_url}/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/generate`,
70
70
  { email },
71
71
  { headers: { "X-CMS-API-Key": CMS_API_KEY } }
72
72
  );
@@ -78,7 +78,7 @@ app.post("/api/consent/refresh-token", async (req, res) => {
78
78
  const { refresh_token, organisation_uuid, workspace_uuid, base_url } = req.body;
79
79
 
80
80
  const response = await axios.post(
81
- `${base_url}/consent/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/refresh-token`,
81
+ `${base_url}/consent/public/organisations/${organisation_uuid}/workspaces/${workspace_uuid}/tokens/refresh`,
82
82
  { refresh_token },
83
83
  { headers: { "X-CMS-API-Key": CMS_API_KEY } }
84
84
  );
@@ -172,7 +172,7 @@ The Privacy Center is a separate entry point (`@redacto.io/consent-sdk-react-nat
172
172
 
173
173
  ### Certified UI
174
174
 
175
- `RedactoPrivacyCenter` renders the full Privacy Center experience with built-in navigation, auth, theming, and i18n.
175
+ `RedactoPrivacyCenter` renders the full Privacy Center experience with built-in navigation, auth, theming, i18n, and an internal `QueryClientProvider`. You do **not** need to wrap it in your own React Query provider.
176
176
 
177
177
  ```tsx
178
178
  import { RedactoPrivacyCenter } from "@redacto.io/consent-sdk-react-native/privacy-center";
@@ -201,7 +201,7 @@ import { RedactoPrivacyCenter } from "@redacto.io/consent-sdk-react-native/priva
201
201
  | `refreshToken` | `string` | ✓ | - | JWT refresh token |
202
202
  | `onError` | `(error: Error) => boolean` | ✓ | - | Error handler; return `true` if handled |
203
203
  | `theme` | `"light" \| "dark"` | | `"light"` | Theme variant |
204
- | `initialPage` | `"consent-manager" \| "form" \| "activity" \| "case-details"` | | `"consent-manager"` | Page to render first |
204
+ | `initialPage` | `"consent-manager" \| "form" \| "activity" \| "receipts" \| "case-details"` | | `"consent-manager"` | Page to render first |
205
205
  | `onBack` | `"back" \| "signout"` | | - | Navbar back / signout control behaviour |
206
206
 
207
207
  ### Composable Components
@@ -220,7 +220,17 @@ If you want to compose your own shell, import the screen-level building blocks i
220
220
  | `BottomTabBar` | Bottom tab navigation |
221
221
  | `Footer` | Footer block |
222
222
 
223
- These rely on the context providers (`AuthProvider`, `BaseUrlProvider`, `NavigationProvider`, `ThemeProvider`) — wrap them yourself if you compose the pages directly.
223
+ These rely on the context providers (`AuthProvider`, `BaseUrlProvider`, `NavigationProvider`, `ThemeProvider`, and `QueryClientProvider` for React Query hooks) — wrap them yourself if you compose the pages directly.
224
+
225
+ ### Receipt downloads
226
+
227
+ The **My Receipt** screen downloads PDFs via `expo-file-system` and opens the native share sheet via `expo-sharing`. Install both peers when using Privacy Center:
228
+
229
+ ```sh
230
+ pnpm add expo-file-system expo-sharing
231
+ ```
232
+
233
+ On Expo SDK 52+, the SDK uses the `expo-file-system/legacy` entry automatically; older Expo versions fall back to the main `expo-file-system` export.
224
234
 
225
235
  ### UI Primitives
226
236
 
@@ -166,6 +166,27 @@ type ConsentHistoryStatusSummary = {
166
166
  active_purposes: number;
167
167
  inactive_purposes: number;
168
168
  };
169
+ type PurposeItem = {
170
+ purpose_uuid: string;
171
+ name: string;
172
+ description: string | null;
173
+ status: ConsentStatusEnum | string;
174
+ given_date: string | null;
175
+ valid_till: string | null;
176
+ method: string;
177
+ data_elements: ConsentDataElement[];
178
+ link_reason: string | null;
179
+ };
180
+ type ConsentGroup = {
181
+ product_uuid: string;
182
+ product_name: string;
183
+ product_description: string | null;
184
+ nominator: NominatorInfo | null;
185
+ total_purposes: number;
186
+ active_purposes: number;
187
+ purposes: PurposeItem[];
188
+ has_more_purposes: boolean;
189
+ };
169
190
  type ProductConsentHistoryGroup = {
170
191
  product_uuid: string;
171
192
  product_name: string;
@@ -186,12 +207,16 @@ type Pagination = {
186
207
  type UserConsentDetail = {
187
208
  data?: UserConsent[];
188
209
  product_purpose_groups?: ProductConsentHistoryGroup[];
189
- pagination: Pagination;
210
+ pagination?: Pagination;
190
211
  direct_product_groups?: ProductConsentHistoryGroup[];
191
212
  user_status?: 'ACTIVE' | 'TRANSFERRED' | null;
192
213
  nominated_purposes?: NominatedPurposesGroup[];
193
214
  nominators?: NominatorInfo[];
194
215
  status_summary?: ConsentHistoryStatusSummary | null;
216
+ direct?: ConsentGroup[];
217
+ nominated?: ConsentGroup[];
218
+ direct_pagination?: Pagination;
219
+ nominated_pagination?: Pagination;
195
220
  };
196
221
  declare enum ConsentStatusEnum {
197
222
  ACTIVE = "ACTIVE",
@@ -302,7 +327,7 @@ type CaseDetailsTab = Readonly<{
302
327
  label: string;
303
328
  }>;
304
329
 
305
- type InternalPage = 'consent-manager' | 'form' | 'activity' | 'case-details';
330
+ type InternalPage = 'consent-manager' | 'form' | 'activity' | 'receipts' | 'case-details';
306
331
  interface NavigationContextType {
307
332
  currentPage: InternalPage;
308
333
  navigateTo: (page: InternalPage) => void;
@@ -427,7 +452,16 @@ declare function createConsentClient(baseUrl: string): {
427
452
  /**
428
453
  * Get user consents (privacy center)
429
454
  */
430
- getUserConsents(baseRequest: BaseRequest, contact: string, offset?: number, limit?: number, search?: string, status?: string, product_uuid?: string, language?: string, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
455
+ getUserConsents(baseRequest: BaseRequest, params: {
456
+ offset?: number;
457
+ limit?: number;
458
+ nominated_offset?: number;
459
+ nominated_limit?: number;
460
+ status?: string;
461
+ product_uuid?: string;
462
+ search?: string;
463
+ language?: string;
464
+ }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
431
465
  /**
432
466
  * Manage consent (privacy center) - revoke, regrant, or renew
433
467
  */
@@ -436,6 +470,26 @@ declare function createConsentClient(baseUrl: string): {
436
470
  * Get activities (privacy center)
437
471
  */
438
472
  getActivities(baseRequest: BaseRequest, offset?: number, limit?: number, language?: string, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
473
+ /**
474
+ * Get receipts (privacy center)
475
+ */
476
+ getReceipts(baseRequest: BaseRequest, params: {
477
+ skip?: number;
478
+ limit?: number;
479
+ event_type?: string;
480
+ status?: string;
481
+ created_after?: string;
482
+ created_before?: string;
483
+ notice_uuid?: string;
484
+ language?: string;
485
+ }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
486
+ /**
487
+ * Download a single receipt as a PDF (privacy center).
488
+ * The endpoint returns raw `application/pdf` bytes (not the JSON envelope),
489
+ * so this bypasses `privacyCenterApiFetch` and returns a base64 string that
490
+ * the RN UI writes to a temp file to open/share. 404 => not found.
491
+ */
492
+ getReceiptPdf(baseRequest: BaseRequest, receiptUuid: string, authToken?: string): Promise<string>;
439
493
  /**
440
494
  * Get case history (privacy center)
441
495
  */
@@ -505,7 +559,21 @@ declare const fetchProducts: (organizationId: string, workspaceId: string, skip?
505
559
  name: string;
506
560
  description?: string;
507
561
  }> | null>;
508
- declare const fetchUserConsents: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, search?: string, status?: string, product_uuid?: string, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<UserConsentDetail | null>;
562
+ type FetchUserConsentsParams = {
563
+ organizationId: string;
564
+ workspaceId: string;
565
+ offset?: number;
566
+ limit?: number;
567
+ nominatedOffset?: number;
568
+ nominatedLimit?: number;
569
+ search?: string;
570
+ status?: string;
571
+ product_uuid?: string;
572
+ language?: string;
573
+ authContext?: AuthContext;
574
+ consentClient?: BaseUrlContextValue['consentClient'];
575
+ };
576
+ declare const fetchUserConsents: (params: FetchUserConsentsParams) => Promise<UserConsentDetail | null>;
509
577
  declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, }: {
510
578
  organizationId: string;
511
579
  workspaceId: string;
@@ -166,6 +166,27 @@ type ConsentHistoryStatusSummary = {
166
166
  active_purposes: number;
167
167
  inactive_purposes: number;
168
168
  };
169
+ type PurposeItem = {
170
+ purpose_uuid: string;
171
+ name: string;
172
+ description: string | null;
173
+ status: ConsentStatusEnum | string;
174
+ given_date: string | null;
175
+ valid_till: string | null;
176
+ method: string;
177
+ data_elements: ConsentDataElement[];
178
+ link_reason: string | null;
179
+ };
180
+ type ConsentGroup = {
181
+ product_uuid: string;
182
+ product_name: string;
183
+ product_description: string | null;
184
+ nominator: NominatorInfo | null;
185
+ total_purposes: number;
186
+ active_purposes: number;
187
+ purposes: PurposeItem[];
188
+ has_more_purposes: boolean;
189
+ };
169
190
  type ProductConsentHistoryGroup = {
170
191
  product_uuid: string;
171
192
  product_name: string;
@@ -186,12 +207,16 @@ type Pagination = {
186
207
  type UserConsentDetail = {
187
208
  data?: UserConsent[];
188
209
  product_purpose_groups?: ProductConsentHistoryGroup[];
189
- pagination: Pagination;
210
+ pagination?: Pagination;
190
211
  direct_product_groups?: ProductConsentHistoryGroup[];
191
212
  user_status?: 'ACTIVE' | 'TRANSFERRED' | null;
192
213
  nominated_purposes?: NominatedPurposesGroup[];
193
214
  nominators?: NominatorInfo[];
194
215
  status_summary?: ConsentHistoryStatusSummary | null;
216
+ direct?: ConsentGroup[];
217
+ nominated?: ConsentGroup[];
218
+ direct_pagination?: Pagination;
219
+ nominated_pagination?: Pagination;
195
220
  };
196
221
  declare enum ConsentStatusEnum {
197
222
  ACTIVE = "ACTIVE",
@@ -302,7 +327,7 @@ type CaseDetailsTab = Readonly<{
302
327
  label: string;
303
328
  }>;
304
329
 
305
- type InternalPage = 'consent-manager' | 'form' | 'activity' | 'case-details';
330
+ type InternalPage = 'consent-manager' | 'form' | 'activity' | 'receipts' | 'case-details';
306
331
  interface NavigationContextType {
307
332
  currentPage: InternalPage;
308
333
  navigateTo: (page: InternalPage) => void;
@@ -427,7 +452,16 @@ declare function createConsentClient(baseUrl: string): {
427
452
  /**
428
453
  * Get user consents (privacy center)
429
454
  */
430
- getUserConsents(baseRequest: BaseRequest, contact: string, offset?: number, limit?: number, search?: string, status?: string, product_uuid?: string, language?: string, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
455
+ getUserConsents(baseRequest: BaseRequest, params: {
456
+ offset?: number;
457
+ limit?: number;
458
+ nominated_offset?: number;
459
+ nominated_limit?: number;
460
+ status?: string;
461
+ product_uuid?: string;
462
+ search?: string;
463
+ language?: string;
464
+ }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
431
465
  /**
432
466
  * Manage consent (privacy center) - revoke, regrant, or renew
433
467
  */
@@ -436,6 +470,26 @@ declare function createConsentClient(baseUrl: string): {
436
470
  * Get activities (privacy center)
437
471
  */
438
472
  getActivities(baseRequest: BaseRequest, offset?: number, limit?: number, language?: string, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
473
+ /**
474
+ * Get receipts (privacy center)
475
+ */
476
+ getReceipts(baseRequest: BaseRequest, params: {
477
+ skip?: number;
478
+ limit?: number;
479
+ event_type?: string;
480
+ status?: string;
481
+ created_after?: string;
482
+ created_before?: string;
483
+ notice_uuid?: string;
484
+ language?: string;
485
+ }, authToken?: string, options?: Omit<ApiFetchOptions, "getAuthToken">): Promise<unknown>;
486
+ /**
487
+ * Download a single receipt as a PDF (privacy center).
488
+ * The endpoint returns raw `application/pdf` bytes (not the JSON envelope),
489
+ * so this bypasses `privacyCenterApiFetch` and returns a base64 string that
490
+ * the RN UI writes to a temp file to open/share. 404 => not found.
491
+ */
492
+ getReceiptPdf(baseRequest: BaseRequest, receiptUuid: string, authToken?: string): Promise<string>;
439
493
  /**
440
494
  * Get case history (privacy center)
441
495
  */
@@ -505,7 +559,21 @@ declare const fetchProducts: (organizationId: string, workspaceId: string, skip?
505
559
  name: string;
506
560
  description?: string;
507
561
  }> | null>;
508
- declare const fetchUserConsents: (organizationId: string, workspaceId: string, contact: string, offset?: number, limit?: number, search?: string, status?: string, product_uuid?: string, authContext?: AuthContext, consentClient?: BaseUrlContextValue["consentClient"], language?: string) => Promise<UserConsentDetail | null>;
562
+ type FetchUserConsentsParams = {
563
+ organizationId: string;
564
+ workspaceId: string;
565
+ offset?: number;
566
+ limit?: number;
567
+ nominatedOffset?: number;
568
+ nominatedLimit?: number;
569
+ search?: string;
570
+ status?: string;
571
+ product_uuid?: string;
572
+ language?: string;
573
+ authContext?: AuthContext;
574
+ consentClient?: BaseUrlContextValue['consentClient'];
575
+ };
576
+ declare const fetchUserConsents: (params: FetchUserConsentsParams) => Promise<UserConsentDetail | null>;
509
577
  declare const manageConsent: ({ organizationId, workspaceId, purposeId, contact, action, authContext, consentClient, nominatorContact, dataElementUuids, }: {
510
578
  organizationId: string;
511
579
  workspaceId: string;