@tantainnovative/ndpr-toolkit 3.5.5 → 3.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +48 -2
- package/dist/adapters.d.mts +137 -3
- package/dist/adapters.d.ts +137 -3
- package/dist/adapters.js +1 -1
- package/dist/adapters.mjs +1 -1
- package/dist/chunk-LTPSN2SU.mjs +1 -0
- package/dist/chunk-PL4XNCQA.mjs +1 -0
- package/dist/chunk-ROTLSZMV.js +1 -0
- package/dist/chunk-RV2VMWZJ.mjs +1 -0
- package/dist/chunk-RXZFYBUJ.js +1 -0
- package/dist/chunk-SJRIOZ4K.mjs +1 -0
- package/dist/chunk-V3RYHNHN.js +1 -0
- package/dist/chunk-W7RBGZCC.js +1 -0
- package/dist/presets-consent.d.mts +139 -0
- package/dist/presets-consent.d.ts +139 -0
- package/dist/presets-consent.js +2 -0
- package/dist/presets-consent.mjs +2 -0
- package/dist/presets-dsr.d.mts +133 -0
- package/dist/presets-dsr.d.ts +133 -0
- package/dist/presets-dsr.js +2 -0
- package/dist/presets-dsr.mjs +2 -0
- package/dist/presets-policy.d.mts +203 -0
- package/dist/presets-policy.d.ts +203 -0
- package/dist/presets-policy.js +2 -0
- package/dist/presets-policy.mjs +2 -0
- package/dist/presets.d.mts +73 -0
- package/dist/presets.d.ts +73 -0
- package/dist/presets.js +1 -1
- package/dist/presets.mjs +1 -1
- package/dist/server.d.mts +137 -3
- package/dist/server.d.ts +137 -3
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +25 -1
- package/dist/chunk-6NXXQYQL.js +0 -1
- package/dist/chunk-NBZUZYTB.mjs +0 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/** A user-defined section added to the policy outside the generated ones. */
|
|
4
|
+
declare interface CustomSection {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
content: string;
|
|
8
|
+
order: number;
|
|
9
|
+
required: false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** A logical category of personal data the organisation may collect. */
|
|
13
|
+
declare interface DataCategory {
|
|
14
|
+
/** Machine-readable identifier. */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Human-readable label shown in the wizard. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Grouping for display and compliance checks. */
|
|
19
|
+
group: 'identity' | 'financial' | 'behavioral' | 'sensitive' | 'children';
|
|
20
|
+
/** Specific data points within this category. */
|
|
21
|
+
dataPoints: string[];
|
|
22
|
+
/** Whether this category is currently selected by the user. */
|
|
23
|
+
selected: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Policy engine types for the adaptive privacy policy generator.
|
|
28
|
+
* These types power the wizard-driven policy builder, compliance checker,
|
|
29
|
+
* and export functionality — all aligned with the NDPA 2023.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** Industry verticals with sector-specific compliance requirements. */
|
|
33
|
+
declare type Industry = 'fintech' | 'healthcare' | 'ecommerce' | 'saas' | 'education' | 'government' | 'other';
|
|
34
|
+
|
|
35
|
+
export declare const NDPRPrivacyPolicy: React__default.FC<NDPRPrivacyPolicyProps>;
|
|
36
|
+
|
|
37
|
+
export declare interface NDPRPrivacyPolicyProps {
|
|
38
|
+
adapter?: StorageAdapter<PolicyDraft>;
|
|
39
|
+
onComplete?: (policy: PrivacyPolicy) => void;
|
|
40
|
+
classNames?: Record<string, string>;
|
|
41
|
+
unstyled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Represents organization information for a privacy policy
|
|
46
|
+
*/
|
|
47
|
+
declare interface OrganizationInfo {
|
|
48
|
+
/** Name of the organization */
|
|
49
|
+
name: string;
|
|
50
|
+
/** Website URL of the organization */
|
|
51
|
+
website: string;
|
|
52
|
+
/** Contact email for privacy inquiries */
|
|
53
|
+
privacyEmail: string;
|
|
54
|
+
/** Physical address of the organization */
|
|
55
|
+
address?: string;
|
|
56
|
+
/** Phone number for privacy inquiries */
|
|
57
|
+
privacyPhone?: string;
|
|
58
|
+
/** Name of the Data Protection Officer */
|
|
59
|
+
dpoName?: string;
|
|
60
|
+
/** Email of the Data Protection Officer */
|
|
61
|
+
dpoEmail?: string;
|
|
62
|
+
/** Industry or sector of the organization */
|
|
63
|
+
industry?: string;
|
|
64
|
+
/** NDPC registration number (if registered) */
|
|
65
|
+
ndpcRegistrationNumber?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Organisation size tiers — affects complexity of generated language. */
|
|
69
|
+
declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
|
|
70
|
+
|
|
71
|
+
/** Represents an in-progress policy being built in the wizard. */
|
|
72
|
+
declare interface PolicyDraft {
|
|
73
|
+
/** Unique identifier for the draft. */
|
|
74
|
+
id: string;
|
|
75
|
+
/** The template context driving section generation. */
|
|
76
|
+
templateContext: TemplateContext;
|
|
77
|
+
/** Custom sections added by the user. */
|
|
78
|
+
customSections: CustomSection[];
|
|
79
|
+
/** Per-section content overrides keyed by section id. */
|
|
80
|
+
sectionOverrides: Record<string, string>;
|
|
81
|
+
/** Ordered list of section ids defining the final order. */
|
|
82
|
+
sectionOrder: string[];
|
|
83
|
+
/** Current wizard step (0-indexed). */
|
|
84
|
+
currentStep: number;
|
|
85
|
+
/** Timestamp of the last save. */
|
|
86
|
+
lastSavedAt: number;
|
|
87
|
+
/** The draft is always in "draft" status until finalised. */
|
|
88
|
+
status: 'draft';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Privacy policy types aligned with NDPA 2023
|
|
93
|
+
* Privacy policies must clearly inform data subjects of their rights under the NDPA
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Represents a section in a privacy policy
|
|
97
|
+
*/
|
|
98
|
+
declare interface PolicySection {
|
|
99
|
+
/** Unique identifier for the section */
|
|
100
|
+
id: string;
|
|
101
|
+
/** Title of the section */
|
|
102
|
+
title: string;
|
|
103
|
+
/** Description of the section */
|
|
104
|
+
description?: string;
|
|
105
|
+
/** Order of the section in the policy */
|
|
106
|
+
order?: number;
|
|
107
|
+
/** Whether the section is required by NDPA */
|
|
108
|
+
required: boolean;
|
|
109
|
+
/** Template text for the section */
|
|
110
|
+
template: string;
|
|
111
|
+
/**
|
|
112
|
+
* Default content for the section (legacy field)
|
|
113
|
+
* @deprecated Use template instead
|
|
114
|
+
*/
|
|
115
|
+
defaultContent?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Custom content for the section (overrides default content)
|
|
118
|
+
* @deprecated Use template instead
|
|
119
|
+
*/
|
|
120
|
+
customContent?: string;
|
|
121
|
+
/** Whether the section is included in the policy */
|
|
122
|
+
included: boolean;
|
|
123
|
+
/** Variables that can be used in the section content */
|
|
124
|
+
variables?: string[];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Represents a generated privacy policy
|
|
129
|
+
*/
|
|
130
|
+
declare interface PrivacyPolicy {
|
|
131
|
+
/** Unique identifier for the policy */
|
|
132
|
+
id: string;
|
|
133
|
+
/** Title of the policy */
|
|
134
|
+
title: string;
|
|
135
|
+
/** Template used to generate the policy */
|
|
136
|
+
templateId: string;
|
|
137
|
+
/** Organization information */
|
|
138
|
+
organizationInfo: OrganizationInfo;
|
|
139
|
+
/** Sections of the policy */
|
|
140
|
+
sections: PolicySection[];
|
|
141
|
+
/** Values for the variables used in the policy */
|
|
142
|
+
variableValues: Record<string, string>;
|
|
143
|
+
/** Effective date of the policy */
|
|
144
|
+
effectiveDate: number;
|
|
145
|
+
/** Last updated date of the policy */
|
|
146
|
+
lastUpdated: number;
|
|
147
|
+
/** Version of the policy */
|
|
148
|
+
version: string;
|
|
149
|
+
/**
|
|
150
|
+
* Applicable legal frameworks
|
|
151
|
+
*/
|
|
152
|
+
applicableFrameworks?: ('ndpa' | 'ndpr' | 'gdpr' | 'ccpa')[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Lawful processing purposes recognised under the NDPA. */
|
|
156
|
+
declare type ProcessingPurpose = 'service_delivery' | 'marketing' | 'analytics' | 'research' | 'legal_compliance' | 'fraud_prevention';
|
|
157
|
+
|
|
158
|
+
declare interface StorageAdapter<T = unknown> {
|
|
159
|
+
/** Load persisted data. Called once on hook mount. */
|
|
160
|
+
load(): T | null | Promise<T | null>;
|
|
161
|
+
/** Persist data. Called on every state change. */
|
|
162
|
+
save(data: T): void | Promise<void>;
|
|
163
|
+
/** Clear persisted data. Called on reset. */
|
|
164
|
+
remove(): void | Promise<void>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Full context used to generate an adaptive privacy policy. */
|
|
168
|
+
declare interface TemplateContext {
|
|
169
|
+
/** Organisation details, extended with industry and size. */
|
|
170
|
+
org: OrganizationInfo & {
|
|
171
|
+
industry: Industry;
|
|
172
|
+
orgSize: OrgSize;
|
|
173
|
+
country: string;
|
|
174
|
+
};
|
|
175
|
+
/** Data categories the organisation collects. */
|
|
176
|
+
dataCategories: DataCategory[];
|
|
177
|
+
/** Processing purposes relevant to the organisation. */
|
|
178
|
+
purposes: ProcessingPurpose[];
|
|
179
|
+
/** Whether the organisation processes children's data. */
|
|
180
|
+
hasChildrenData: boolean;
|
|
181
|
+
/** Whether the organisation processes sensitive/special-category data. */
|
|
182
|
+
hasSensitiveData: boolean;
|
|
183
|
+
/** Whether the organisation processes financial data. */
|
|
184
|
+
hasFinancialData: boolean;
|
|
185
|
+
/** Whether data is transferred outside Nigeria. */
|
|
186
|
+
hasCrossBorderTransfer: boolean;
|
|
187
|
+
/** Whether automated decision-making or profiling is used. */
|
|
188
|
+
hasAutomatedDecisions: boolean;
|
|
189
|
+
/** Third-party processors that receive personal data. */
|
|
190
|
+
thirdPartyProcessors: ThirdPartyProcessor[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** A third-party entity that processes data on behalf of the organisation. */
|
|
194
|
+
declare interface ThirdPartyProcessor {
|
|
195
|
+
/** Name of the third party. */
|
|
196
|
+
name: string;
|
|
197
|
+
/** Purpose of sharing data with this processor. */
|
|
198
|
+
purpose: string;
|
|
199
|
+
/** Country where the processor is located. */
|
|
200
|
+
country: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export { }
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';var chunkW7RBGZCC_js=require('./chunk-W7RBGZCC.js');require('./chunk-I2LMQWK3.js'),require('./chunk-UI536RU2.js'),require('./chunk-N3MQQUQP.js'),require('./chunk-Q64735OC.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js'),require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunkW7RBGZCC_js.a}});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
export{a as NDPRPrivacyPolicy}from'./chunk-RV2VMWZJ.mjs';import'./chunk-BNHQFZHL.mjs';import'./chunk-O6CUBNXK.mjs';import'./chunk-AOHKVFAS.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import'./chunk-ZJYULEER.mjs';
|
package/dist/presets.d.mts
CHANGED
|
@@ -561,6 +561,35 @@ export declare const NDPRComplianceDashboard: React__default.FC<NDPRDashboardPre
|
|
|
561
561
|
|
|
562
562
|
export declare const NDPRConsent: React__default.FC<NDPRConsentProps>;
|
|
563
563
|
|
|
564
|
+
/**
|
|
565
|
+
* UX copy overrides for the NDPRConsent preset. Pass any subset to
|
|
566
|
+
* replace the default text without dropping to the lower-level
|
|
567
|
+
* `<ConsentBanner>` API. Strings you omit fall back to the toolkit
|
|
568
|
+
* defaults (which already cite NDPA Section 26).
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* <NDPRConsent copy={{
|
|
572
|
+
* title: 'Cookie preferences',
|
|
573
|
+
* description: 'Acme uses cookies to keep you signed in and improve our store.',
|
|
574
|
+
* acceptAll: 'Allow all',
|
|
575
|
+
* rejectAll: 'Only essentials',
|
|
576
|
+
* }} />
|
|
577
|
+
*/
|
|
578
|
+
declare interface NDPRConsentCopy {
|
|
579
|
+
/** Banner heading. Default: "We Value Your Privacy" */
|
|
580
|
+
title?: string;
|
|
581
|
+
/** Body paragraph under the heading. Default cites NDPA Section 26. */
|
|
582
|
+
description?: string;
|
|
583
|
+
/** Primary CTA — accepts all categories. Default: "Accept All" */
|
|
584
|
+
acceptAll?: string;
|
|
585
|
+
/** Secondary CTA — rejects all non-essential categories. Default: "Reject All" */
|
|
586
|
+
rejectAll?: string;
|
|
587
|
+
/** Tertiary CTA — opens the per-category controls. Default: "Customize" */
|
|
588
|
+
customize?: string;
|
|
589
|
+
/** Submit button on the per-category panel. Default: "Save Preferences" */
|
|
590
|
+
save?: string;
|
|
591
|
+
}
|
|
592
|
+
|
|
564
593
|
export declare interface NDPRConsentProps {
|
|
565
594
|
extraOptions?: ConsentOption[];
|
|
566
595
|
options?: ConsentOption[];
|
|
@@ -569,6 +598,11 @@ export declare interface NDPRConsentProps {
|
|
|
569
598
|
classNames?: ConsentBannerClassNames;
|
|
570
599
|
unstyled?: boolean;
|
|
571
600
|
onSave?: (settings: ConsentSettings) => void;
|
|
601
|
+
/**
|
|
602
|
+
* UX copy overrides — see {@link NDPRConsentCopy}. Lets you brand the
|
|
603
|
+
* banner without dropping to the lower-level `<ConsentBanner>` API.
|
|
604
|
+
*/
|
|
605
|
+
copy?: NDPRConsentCopy;
|
|
572
606
|
}
|
|
573
607
|
|
|
574
608
|
export declare const NDPRCrossBorder: React__default.FC<NDPRCrossBorderProps>;
|
|
@@ -659,6 +693,45 @@ export declare interface NDPRSubjectRightsProps {
|
|
|
659
693
|
classNames?: DSRRequestFormClassNames;
|
|
660
694
|
unstyled?: boolean;
|
|
661
695
|
onSubmit?: (data: DSRFormSubmission) => void;
|
|
696
|
+
/**
|
|
697
|
+
* Public-form mode. Use when the form should submit to your existing
|
|
698
|
+
* backend workflow instead of being state-managed by an adapter.
|
|
699
|
+
*
|
|
700
|
+
* When `submitTo` is set:
|
|
701
|
+
* - the form does NOT require an `adapter`
|
|
702
|
+
* - on submit, the toolkit POSTs the JSON-serialised `DSRFormSubmission`
|
|
703
|
+
* to this URL (with `Content-Type: application/json`)
|
|
704
|
+
* - your `onSubmit` callback still fires (after the POST resolves)
|
|
705
|
+
* - submit failures are surfaced via `onSubmitError`
|
|
706
|
+
*
|
|
707
|
+
* For more control over headers, credentials, or retry behaviour, build
|
|
708
|
+
* an `apiAdapter` (which now supports CSRF, retry, and error hooks in
|
|
709
|
+
* 3.6.0) and pass that as `adapter` instead. `submitTo` is the
|
|
710
|
+
* fire-and-forget shortcut for public forms.
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* <NDPRSubjectRights submitTo="/api/dsr" />
|
|
714
|
+
*/
|
|
715
|
+
submitTo?: string;
|
|
716
|
+
/**
|
|
717
|
+
* Fetch options for the `submitTo` POST. Useful for adding `credentials`
|
|
718
|
+
* (cookies/auth), `X-CSRF-Token`, or any other header your backend
|
|
719
|
+
* requires. Ignored unless `submitTo` is set.
|
|
720
|
+
*
|
|
721
|
+
* @default { credentials: 'same-origin' }
|
|
722
|
+
*/
|
|
723
|
+
submitOptions?: {
|
|
724
|
+
headers?: Record<string, string> | (() => Record<string, string>);
|
|
725
|
+
credentials?: RequestCredentials;
|
|
726
|
+
};
|
|
727
|
+
/**
|
|
728
|
+
* Called when a `submitTo` POST fails (network error or non-2xx
|
|
729
|
+
* response). Receives the underlying error or Response.
|
|
730
|
+
*/
|
|
731
|
+
onSubmitError?: (ctx: {
|
|
732
|
+
error?: unknown;
|
|
733
|
+
response?: Response;
|
|
734
|
+
}) => void;
|
|
662
735
|
}
|
|
663
736
|
|
|
664
737
|
/**
|
package/dist/presets.d.ts
CHANGED
|
@@ -561,6 +561,35 @@ export declare const NDPRComplianceDashboard: React__default.FC<NDPRDashboardPre
|
|
|
561
561
|
|
|
562
562
|
export declare const NDPRConsent: React__default.FC<NDPRConsentProps>;
|
|
563
563
|
|
|
564
|
+
/**
|
|
565
|
+
* UX copy overrides for the NDPRConsent preset. Pass any subset to
|
|
566
|
+
* replace the default text without dropping to the lower-level
|
|
567
|
+
* `<ConsentBanner>` API. Strings you omit fall back to the toolkit
|
|
568
|
+
* defaults (which already cite NDPA Section 26).
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* <NDPRConsent copy={{
|
|
572
|
+
* title: 'Cookie preferences',
|
|
573
|
+
* description: 'Acme uses cookies to keep you signed in and improve our store.',
|
|
574
|
+
* acceptAll: 'Allow all',
|
|
575
|
+
* rejectAll: 'Only essentials',
|
|
576
|
+
* }} />
|
|
577
|
+
*/
|
|
578
|
+
declare interface NDPRConsentCopy {
|
|
579
|
+
/** Banner heading. Default: "We Value Your Privacy" */
|
|
580
|
+
title?: string;
|
|
581
|
+
/** Body paragraph under the heading. Default cites NDPA Section 26. */
|
|
582
|
+
description?: string;
|
|
583
|
+
/** Primary CTA — accepts all categories. Default: "Accept All" */
|
|
584
|
+
acceptAll?: string;
|
|
585
|
+
/** Secondary CTA — rejects all non-essential categories. Default: "Reject All" */
|
|
586
|
+
rejectAll?: string;
|
|
587
|
+
/** Tertiary CTA — opens the per-category controls. Default: "Customize" */
|
|
588
|
+
customize?: string;
|
|
589
|
+
/** Submit button on the per-category panel. Default: "Save Preferences" */
|
|
590
|
+
save?: string;
|
|
591
|
+
}
|
|
592
|
+
|
|
564
593
|
export declare interface NDPRConsentProps {
|
|
565
594
|
extraOptions?: ConsentOption[];
|
|
566
595
|
options?: ConsentOption[];
|
|
@@ -569,6 +598,11 @@ export declare interface NDPRConsentProps {
|
|
|
569
598
|
classNames?: ConsentBannerClassNames;
|
|
570
599
|
unstyled?: boolean;
|
|
571
600
|
onSave?: (settings: ConsentSettings) => void;
|
|
601
|
+
/**
|
|
602
|
+
* UX copy overrides — see {@link NDPRConsentCopy}. Lets you brand the
|
|
603
|
+
* banner without dropping to the lower-level `<ConsentBanner>` API.
|
|
604
|
+
*/
|
|
605
|
+
copy?: NDPRConsentCopy;
|
|
572
606
|
}
|
|
573
607
|
|
|
574
608
|
export declare const NDPRCrossBorder: React__default.FC<NDPRCrossBorderProps>;
|
|
@@ -659,6 +693,45 @@ export declare interface NDPRSubjectRightsProps {
|
|
|
659
693
|
classNames?: DSRRequestFormClassNames;
|
|
660
694
|
unstyled?: boolean;
|
|
661
695
|
onSubmit?: (data: DSRFormSubmission) => void;
|
|
696
|
+
/**
|
|
697
|
+
* Public-form mode. Use when the form should submit to your existing
|
|
698
|
+
* backend workflow instead of being state-managed by an adapter.
|
|
699
|
+
*
|
|
700
|
+
* When `submitTo` is set:
|
|
701
|
+
* - the form does NOT require an `adapter`
|
|
702
|
+
* - on submit, the toolkit POSTs the JSON-serialised `DSRFormSubmission`
|
|
703
|
+
* to this URL (with `Content-Type: application/json`)
|
|
704
|
+
* - your `onSubmit` callback still fires (after the POST resolves)
|
|
705
|
+
* - submit failures are surfaced via `onSubmitError`
|
|
706
|
+
*
|
|
707
|
+
* For more control over headers, credentials, or retry behaviour, build
|
|
708
|
+
* an `apiAdapter` (which now supports CSRF, retry, and error hooks in
|
|
709
|
+
* 3.6.0) and pass that as `adapter` instead. `submitTo` is the
|
|
710
|
+
* fire-and-forget shortcut for public forms.
|
|
711
|
+
*
|
|
712
|
+
* @example
|
|
713
|
+
* <NDPRSubjectRights submitTo="/api/dsr" />
|
|
714
|
+
*/
|
|
715
|
+
submitTo?: string;
|
|
716
|
+
/**
|
|
717
|
+
* Fetch options for the `submitTo` POST. Useful for adding `credentials`
|
|
718
|
+
* (cookies/auth), `X-CSRF-Token`, or any other header your backend
|
|
719
|
+
* requires. Ignored unless `submitTo` is set.
|
|
720
|
+
*
|
|
721
|
+
* @default { credentials: 'same-origin' }
|
|
722
|
+
*/
|
|
723
|
+
submitOptions?: {
|
|
724
|
+
headers?: Record<string, string> | (() => Record<string, string>);
|
|
725
|
+
credentials?: RequestCredentials;
|
|
726
|
+
};
|
|
727
|
+
/**
|
|
728
|
+
* Called when a `submitTo` POST fails (network error or non-2xx
|
|
729
|
+
* response). Receives the underlying error or Response.
|
|
730
|
+
*/
|
|
731
|
+
onSubmitError?: (ctx: {
|
|
732
|
+
error?: unknown;
|
|
733
|
+
response?: Response;
|
|
734
|
+
}) => void;
|
|
662
735
|
}
|
|
663
736
|
|
|
664
737
|
/**
|
package/dist/presets.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var chunkI2LMQWK3_js=require('./chunk-I2LMQWK3.js'),chunkNUWVPRNI_js=require('./chunk-NUWVPRNI.js'),chunkPZRQWPWD_js=require('./chunk-PZRQWPWD.js'),chunkI3Y4LOSL_js=require('./chunk-I3Y4LOSL.js'),chunk5GVMKUMP_js=require('./chunk-5GVMKUMP.js');require('./chunk-UI536RU2.js'),require('./chunk-N3MQQUQP.js');var chunkQPRYXVH2_js=require('./chunk-QPRYXVH2.js');require('./chunk-Q64735OC.js'),require('./chunk-WZYCBW2R.js'),require('./chunk-YFBDJ4FH.js'),require('./chunk-4CVBQC66.js');var chunk732C2EVN_js=require('./chunk-732C2EVN.js');require('./chunk-L2VO3MEJ.js');var chunkW47OSMT6_js=require('./chunk-W47OSMT6.js'),chunkWDDCKYWA_js=require('./chunk-WDDCKYWA.js'),chunkS6COXIZA_js=require('./chunk-S6COXIZA.js');require('./chunk-UXUMYP4L.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),jsxRuntime=require('react/jsx-runtime'),react=require('react');var q=[{id:"essential",label:"Essential Cookies",description:"Required for basic site functionality. Cannot be disabled.",required:true,purpose:"Site operation"},{id:"analytics",label:"Analytics",description:"Help us understand how visitors use our site to improve the experience.",required:false,purpose:"Usage analytics"},{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign effectiveness.",required:false,purpose:"Targeted advertising"},{id:"preferences",label:"Preferences",description:"Remember your settings and preferences for a personalised experience.",required:false,purpose:"Personalisation"}],I=({extraOptions:d=[],options:t,adapter:p,position:l="bottom",classNames:s,unstyled:c,onSave:a})=>{let u=t!=null?t:[...q,...d];return jsxRuntime.jsx(chunk732C2EVN_js.a,{options:u,onSave:f=>{p&&p.save(f),a==null||a(f);},position:l,classNames:s,unstyled:c,manageStorage:!p})};var L=[{id:"access",name:"Access My Data",description:"Request a copy of your personal data held by us",ndpaSection:"Section 34(1)(a)\u2013(b)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"rectification",name:"Correct My Data",description:"Request corrections to inaccurate personal data",ndpaSection:"Section 34(1)(c)",estimatedCompletionTime:30,requiresAdditionalInfo:true,additionalFields:[{id:"correction_details",label:"What data needs to be corrected?",type:"textarea",required:true,placeholder:"Please describe the inaccurate data and what the correct information should be"}]},{id:"erasure",name:"Delete My Data",description:"Request deletion of your personal data",ndpaSection:"Section 34(1)(d), Section 34(2)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"portability",name:"Export My Data",description:"Receive your data in a portable format",ndpaSection:"Section 38",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"restrict",name:"Restrict Processing",description:"Request restriction of data processing",ndpaSection:"Section 34(1)(e)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"object",name:"Object to Processing",description:"Object to processing of your personal data",ndpaSection:"Section 36",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"withdraw_consent",name:"Withdraw My Consent",description:"Withdraw consent previously given for processing",ndpaSection:"Section 35",estimatedCompletionTime:30,requiresAdditionalInfo:false}],k=({requestTypes:d=L,adapter:t,classNames:p,unstyled:l,onSubmit:s=()=>{}})=>jsxRuntime.jsx(chunkW47OSMT6_js.a,{requestTypes:d,onSubmit:a=>{t&&t.save(a),s(a);},classNames:p,unstyled:l});var _=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],U=({categories:d=_,adapter:t,classNames:p,unstyled:l,onSubmit:s=()=>{}})=>jsxRuntime.jsx(chunkS6COXIZA_js.a,{categories:d,onSubmit:a=>{t&&t.save(a),s(a);},classNames:p,unstyled:l});var E=d=>jsxRuntime.jsx(chunkI2LMQWK3_js.a,chunkRFPLZDIO_js.a({},d));var Y=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],z=({sections:d=Y,adapter:t,classNames:p,unstyled:l,onComplete:s=()=>{}})=>{let[c,a]=react.useState({}),[u,P]=react.useState(0),f=(i,T)=>{a(B=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},B),{[i]:T}));},e=()=>{u<d.length-1?P(i=>i+1):(t&&t.save(c),s(c));},r=()=>{u>0&&P(i=>i-1);},o=Math.round((u+1)/d.length*100);return jsxRuntime.jsx(chunkWDDCKYWA_js.a,{sections:d,answers:c,onAnswerChange:f,currentSectionIndex:u,onNextSection:e,onPrevSection:r,progress:o,classNames:p,unstyled:l})};var V=({initialActivities:d=[],adapter:t,classNames:p,unstyled:l})=>{let[s,c]=react.useState(()=>{if(t){let e=t.load();if(e&&!(e instanceof Promise))return e}return d}),a=e=>{t&&t.save(e);};return jsxRuntime.jsx(chunkPZRQWPWD_js.a,{activities:s,onAddActivity:e=>{let r=Date.now(),o=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`activity-${r}`,createdAt:r,updatedAt:r}),i=[...s,o];c(i),a(i);},onUpdateActivity:(e,r)=>{let o=s.map(i=>i.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},i),r),{updatedAt:Date.now()}):i);c(o),a(o);},onArchiveActivity:e=>{let r=s.map(o=>o.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{status:"inactive",updatedAt:Date.now()}):o);c(r),a(r);},classNames:p,unstyled:l})};var G=({initialTransfers:d=[],adapter:t,classNames:p,unstyled:l})=>{let[s,c]=react.useState(()=>{if(t){let e=t.load();if(e&&!(e instanceof Promise))return e}return d}),a=e=>{t&&t.save(e);};return jsxRuntime.jsx(chunkI3Y4LOSL_js.a,{transfers:s,onAddTransfer:e=>{let r=Date.now(),o=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`transfer-${r}`,createdAt:r,updatedAt:r}),i=[...s,o];c(i),a(i);},onUpdateTransfer:(e,r)=>{let o=s.map(i=>i.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},i),r),{updatedAt:Date.now()}):i);c(o),a(o);},onRemoveTransfer:e=>{let r=s.filter(o=>o.id!==e);c(r),a(r);},classNames:p,unstyled:l})};var Z={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},ee=({initialData:d,adapter:t,classNames:p,unstyled:l})=>{let[s,c]=react.useState(d!=null?d:Z);react.useEffect(()=>{if(!t)return;let e=false;return chunkRFPLZDIO_js.d(null,null,function*(){let o=yield t.load();!e&&o&&c(o);}),()=>{e=true;}},[t]);let a=e=>{t&&t.save(e);};return jsxRuntime.jsx(chunk5GVMKUMP_js.a,{ropa:s,onAddRecord:e=>{let r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},s),{records:[...s.records,e],lastUpdated:Date.now()});c(r),a(r);},onUpdateRecord:(e,r)=>{let o=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},s),{records:s.records.map(i=>i.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},i),r),{updatedAt:Date.now()}):i),lastUpdated:Date.now()});c(o),a(o);},onArchiveRecord:e=>{let r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},s),{records:s.records.map(o=>o.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{status:"archived",updatedAt:Date.now()}):o),lastUpdated:Date.now()});c(r),a(r);},classNames:p,unstyled:l})};var re=p=>{var l=p,{input:d}=l,t=chunkRFPLZDIO_js.c(l,["input"]);let s=chunkQPRYXVH2_js.a(d);return jsxRuntime.jsx(chunkNUWVPRNI_js.a,chunkRFPLZDIO_js.a({report:s},t))};exports.NDPRBreachReport=U;exports.NDPRComplianceDashboard=re;exports.NDPRConsent=I;exports.NDPRCrossBorder=G;exports.NDPRDPIA=z;exports.NDPRLawfulBasis=V;exports.NDPRPrivacyPolicy=E;exports.NDPRROPA=ee;exports.NDPRSubjectRights=k;
|
|
2
|
+
'use strict';var chunkW7RBGZCC_js=require('./chunk-W7RBGZCC.js');require('./chunk-I2LMQWK3.js');var chunkV3RYHNHN_js=require('./chunk-V3RYHNHN.js'),chunkRXZFYBUJ_js=require('./chunk-RXZFYBUJ.js'),chunkNUWVPRNI_js=require('./chunk-NUWVPRNI.js'),chunkPZRQWPWD_js=require('./chunk-PZRQWPWD.js'),chunkI3Y4LOSL_js=require('./chunk-I3Y4LOSL.js'),chunk5GVMKUMP_js=require('./chunk-5GVMKUMP.js');require('./chunk-UI536RU2.js'),require('./chunk-N3MQQUQP.js');var chunkQPRYXVH2_js=require('./chunk-QPRYXVH2.js');require('./chunk-Q64735OC.js'),require('./chunk-WZYCBW2R.js'),require('./chunk-YFBDJ4FH.js'),require('./chunk-4CVBQC66.js'),require('./chunk-732C2EVN.js'),require('./chunk-L2VO3MEJ.js'),require('./chunk-W47OSMT6.js');var chunkWDDCKYWA_js=require('./chunk-WDDCKYWA.js'),chunkS6COXIZA_js=require('./chunk-S6COXIZA.js');require('./chunk-UXUMYP4L.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),jsxRuntime=require('react/jsx-runtime'),react=require('react');var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsxRuntime.jsx(chunkS6COXIZA_js.a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=react.useState({}),[m,f]=react.useState(0),P=(a,C)=>{d(S=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsxRuntime.jsx(chunkWDDCKYWA_js.a,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkPZRQWPWD_js.a,{activities:o,onAddActivity:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkI3Y4LOSL_js.a,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(c!=null?c:j);react.useEffect(()=>{if(!s)return;let e=false;return chunkRFPLZDIO_js.d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunk5GVMKUMP_js.a,{ropa:o,onAddRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d(t);},onUpdateRecord:(e,t)=>{let r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d(r);},onArchiveRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c}=p,s=chunkRFPLZDIO_js.c(p,["input"]);let o=chunkQPRYXVH2_js.a(c);return jsxRuntime.jsx(chunkNUWVPRNI_js.a,chunkRFPLZDIO_js.a({report:o},s))};Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunkW7RBGZCC_js.a}});Object.defineProperty(exports,"NDPRConsent",{enumerable:true,get:function(){return chunkV3RYHNHN_js.a}});Object.defineProperty(exports,"NDPRSubjectRights",{enumerable:true,get:function(){return chunkRXZFYBUJ_js.a}});exports.NDPRBreachReport=I;exports.NDPRComplianceDashboard=G;exports.NDPRCrossBorder=W;exports.NDPRDPIA=_;exports.NDPRLawfulBasis=F;exports.NDPRROPA=V;
|
package/dist/presets.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {a as a$3}from'./chunk-BNHQFZHL.mjs';import {a as a$a}from'./chunk-ZIZL37BG.mjs';import {a as a$6}from'./chunk-COD3RMTL.mjs';import {a as a$7}from'./chunk-GTYXVAJX.mjs';import {a as a$8}from'./chunk-EXEXUAF6.mjs';import'./chunk-O6CUBNXK.mjs';import'./chunk-AOHKVFAS.mjs';import {a as a$9}from'./chunk-EFIBHKQE.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-LWIKDDSU.mjs';import'./chunk-7BJXI2HI.mjs';import'./chunk-XP5PL6K7.mjs';import {a}from'./chunk-BFAX7JQA.mjs';import'./chunk-YTU4FNM2.mjs';import {a as a$1}from'./chunk-XJO4DH3L.mjs';import {a as a$5}from'./chunk-ZQZJNKVB.mjs';import {a as a$2}from'./chunk-ZHFLBL63.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {a as a$4,b,d,c}from'./chunk-ZJYULEER.mjs';import {jsx}from'react/jsx-runtime';import {useState,useEffect}from'react';var q=[{id:"essential",label:"Essential Cookies",description:"Required for basic site functionality. Cannot be disabled.",required:true,purpose:"Site operation"},{id:"analytics",label:"Analytics",description:"Help us understand how visitors use our site to improve the experience.",required:false,purpose:"Usage analytics"},{id:"marketing",label:"Marketing",description:"Used to deliver relevant advertisements and track campaign effectiveness.",required:false,purpose:"Targeted advertising"},{id:"preferences",label:"Preferences",description:"Remember your settings and preferences for a personalised experience.",required:false,purpose:"Personalisation"}],I=({extraOptions:d=[],options:t,adapter:p,position:l="bottom",classNames:s,unstyled:c,onSave:a$1})=>{let u=t!=null?t:[...q,...d];return jsx(a,{options:u,onSave:f=>{p&&p.save(f),a$1==null||a$1(f);},position:l,classNames:s,unstyled:c,manageStorage:!p})};var L=[{id:"access",name:"Access My Data",description:"Request a copy of your personal data held by us",ndpaSection:"Section 34(1)(a)\u2013(b)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"rectification",name:"Correct My Data",description:"Request corrections to inaccurate personal data",ndpaSection:"Section 34(1)(c)",estimatedCompletionTime:30,requiresAdditionalInfo:true,additionalFields:[{id:"correction_details",label:"What data needs to be corrected?",type:"textarea",required:true,placeholder:"Please describe the inaccurate data and what the correct information should be"}]},{id:"erasure",name:"Delete My Data",description:"Request deletion of your personal data",ndpaSection:"Section 34(1)(d), Section 34(2)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"portability",name:"Export My Data",description:"Receive your data in a portable format",ndpaSection:"Section 38",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"restrict",name:"Restrict Processing",description:"Request restriction of data processing",ndpaSection:"Section 34(1)(e)",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"object",name:"Object to Processing",description:"Object to processing of your personal data",ndpaSection:"Section 36",estimatedCompletionTime:30,requiresAdditionalInfo:false},{id:"withdraw_consent",name:"Withdraw My Consent",description:"Withdraw consent previously given for processing",ndpaSection:"Section 35",estimatedCompletionTime:30,requiresAdditionalInfo:false}],k=({requestTypes:d=L,adapter:t,classNames:p,unstyled:l,onSubmit:s=()=>{}})=>jsx(a$1,{requestTypes:d,onSubmit:a=>{t&&t.save(a),s(a);},classNames:p,unstyled:l});var _=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],U=({categories:d=_,adapter:t,classNames:p,unstyled:l,onSubmit:s=()=>{}})=>jsx(a$2,{categories:d,onSubmit:a=>{t&&t.save(a),s(a);},classNames:p,unstyled:l});var E=d=>jsx(a$3,a$4({},d));var Y=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],z=({sections:d=Y,adapter:t,classNames:p,unstyled:l,onComplete:s=()=>{}})=>{let[c,a]=useState({}),[u,P]=useState(0),f=(i,T)=>{a(B=>b(a$4({},B),{[i]:T}));},e=()=>{u<d.length-1?P(i=>i+1):(t&&t.save(c),s(c));},r=()=>{u>0&&P(i=>i-1);},o=Math.round((u+1)/d.length*100);return jsx(a$5,{sections:d,answers:c,onAnswerChange:f,currentSectionIndex:u,onNextSection:e,onPrevSection:r,progress:o,classNames:p,unstyled:l})};var V=({initialActivities:d=[],adapter:t,classNames:p,unstyled:l})=>{let[s,c]=useState(()=>{if(t){let e=t.load();if(e&&!(e instanceof Promise))return e}return d}),a=e=>{t&&t.save(e);};return jsx(a$6,{activities:s,onAddActivity:e=>{let r=Date.now(),o=b(a$4({},e),{id:`activity-${r}`,createdAt:r,updatedAt:r}),i=[...s,o];c(i),a(i);},onUpdateActivity:(e,r)=>{let o=s.map(i=>i.id===e?b(a$4(a$4({},i),r),{updatedAt:Date.now()}):i);c(o),a(o);},onArchiveActivity:e=>{let r=s.map(o=>o.id===e?b(a$4({},o),{status:"inactive",updatedAt:Date.now()}):o);c(r),a(r);},classNames:p,unstyled:l})};var G=({initialTransfers:d=[],adapter:t,classNames:p,unstyled:l})=>{let[s,c]=useState(()=>{if(t){let e=t.load();if(e&&!(e instanceof Promise))return e}return d}),a=e=>{t&&t.save(e);};return jsx(a$7,{transfers:s,onAddTransfer:e=>{let r=Date.now(),o=b(a$4({},e),{id:`transfer-${r}`,createdAt:r,updatedAt:r}),i=[...s,o];c(i),a(i);},onUpdateTransfer:(e,r)=>{let o=s.map(i=>i.id===e?b(a$4(a$4({},i),r),{updatedAt:Date.now()}):i);c(o),a(o);},onRemoveTransfer:e=>{let r=s.filter(o=>o.id!==e);c(r),a(r);},classNames:p,unstyled:l})};var Z={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},ee=({initialData:d$1,adapter:t,classNames:p,unstyled:l})=>{let[s,c]=useState(d$1!=null?d$1:Z);useEffect(()=>{if(!t)return;let e=false;return d(null,null,function*(){let o=yield t.load();!e&&o&&c(o);}),()=>{e=true;}},[t]);let a=e=>{t&&t.save(e);};return jsx(a$8,{ropa:s,onAddRecord:e=>{let r=b(a$4({},s),{records:[...s.records,e],lastUpdated:Date.now()});c(r),a(r);},onUpdateRecord:(e,r)=>{let o=b(a$4({},s),{records:s.records.map(i=>i.id===e?b(a$4(a$4({},i),r),{updatedAt:Date.now()}):i),lastUpdated:Date.now()});c(o),a(o);},onArchiveRecord:e=>{let r=b(a$4({},s),{records:s.records.map(o=>o.id===e?b(a$4({},o),{status:"archived",updatedAt:Date.now()}):o),lastUpdated:Date.now()});c(r),a(r);},classNames:p,unstyled:l})};var re=p=>{var l=p,{input:d}=l,t=c(l,["input"]);let s=a$9(d);return jsx(a$a,a$4({report:s},t))};export{U as NDPRBreachReport,re as NDPRComplianceDashboard,I as NDPRConsent,G as NDPRCrossBorder,z as NDPRDPIA,V as NDPRLawfulBasis,E as NDPRPrivacyPolicy,ee as NDPRROPA,k as NDPRSubjectRights};
|
|
2
|
+
export{a as NDPRPrivacyPolicy}from'./chunk-RV2VMWZJ.mjs';import'./chunk-BNHQFZHL.mjs';export{a as NDPRConsent}from'./chunk-LTPSN2SU.mjs';export{a as NDPRSubjectRights}from'./chunk-SJRIOZ4K.mjs';import {a as a$7}from'./chunk-ZIZL37BG.mjs';import {a as a$2}from'./chunk-COD3RMTL.mjs';import {a as a$4}from'./chunk-GTYXVAJX.mjs';import {a as a$5}from'./chunk-EXEXUAF6.mjs';import'./chunk-O6CUBNXK.mjs';import'./chunk-AOHKVFAS.mjs';import {a as a$6}from'./chunk-EFIBHKQE.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-LWIKDDSU.mjs';import'./chunk-7BJXI2HI.mjs';import'./chunk-XP5PL6K7.mjs';import'./chunk-BFAX7JQA.mjs';import'./chunk-YTU4FNM2.mjs';import'./chunk-XJO4DH3L.mjs';import {a as a$1}from'./chunk-ZQZJNKVB.mjs';import {a}from'./chunk-ZHFLBL63.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {b,a as a$3,d,c}from'./chunk-ZJYULEER.mjs';import {jsx}from'react/jsx-runtime';import {useState,useEffect}from'react';var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsx(a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=useState({}),[m,f]=useState(0),P=(a,C)=>{d(S=>b(a$3({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsx(a$1,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$2,{activities:o,onAddActivity:e=>{let t=Date.now(),r=b(a$3({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?b(a$3({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$4,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=b(a$3({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(c!=null?c:j);useEffect(()=>{if(!s)return;let e=false;return d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d$1=e=>{s&&s.save(e);};return jsx(a$5,{ropa:o,onAddRecord:e=>{let t=b(a$3({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d$1(t);},onUpdateRecord:(e,t)=>{let r=b(a$3({},o),{records:o.records.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d$1(r);},onArchiveRecord:e=>{let t=b(a$3({},o),{records:o.records.map(r=>r.id===e?b(a$3({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d$1(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c$1}=p,s=c(p,["input"]);let o=a$6(c$1);return jsx(a$7,a$3({report:o},s))};export{I as NDPRBreachReport,G as NDPRComplianceDashboard,W as NDPRCrossBorder,_ as NDPRDPIA,F as NDPRLawfulBasis,V as NDPRROPA};
|
package/dist/server.d.mts
CHANGED
|
@@ -3,10 +3,144 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export declare type AdequacyStatus = 'adequate' | 'inadequate' | 'pending_review' | 'unknown';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Production-ready API storage adapter.
|
|
8
|
+
*
|
|
9
|
+
* Backward-compatible with the 3.5.x signature — `apiAdapter('/api/x')`
|
|
10
|
+
* still works exactly as before. New options are all opt-in.
|
|
11
|
+
*
|
|
12
|
+
* @example basic
|
|
13
|
+
* const adapter = apiAdapter<ConsentSettings>('/api/consent');
|
|
14
|
+
*
|
|
15
|
+
* @example with credentials and CSRF
|
|
16
|
+
* const adapter = apiAdapter<ConsentSettings>('/api/consent', {
|
|
17
|
+
* credentials: 'include',
|
|
18
|
+
* headers: () => ({
|
|
19
|
+
* 'X-CSRF-Token': document.querySelector<HTMLMetaElement>(
|
|
20
|
+
* 'meta[name="csrf-token"]'
|
|
21
|
+
* )?.content ?? '',
|
|
22
|
+
* }),
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* @example with retry + telemetry
|
|
26
|
+
* const adapter = apiAdapter<ConsentSettings>('/api/consent', {
|
|
27
|
+
* retry: { attempts: 2, baseDelayMs: 300 },
|
|
28
|
+
* onError: (ctx) => Sentry.captureException(ctx.error, { extra: ctx }),
|
|
29
|
+
* onSuccess: (ctx) => analytics.track('consent_saved', { method: ctx.method }),
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* @example with response unwrap
|
|
33
|
+
* const adapter = apiAdapter<ConsentSettings>('/api/consent', {
|
|
34
|
+
* // API returns { data: ConsentSettings, ok: true }
|
|
35
|
+
* unwrap: (raw) => (raw as { data: ConsentSettings }).data,
|
|
36
|
+
* });
|
|
37
|
+
*/
|
|
38
|
+
export declare function apiAdapter<T = unknown>(endpoint: string, options?: ApiAdapterOptions<T>): StorageAdapter<T>;
|
|
39
|
+
|
|
40
|
+
declare interface ApiAdapterErrorContext<T = unknown> {
|
|
41
|
+
/** Which adapter operation triggered this — `load`, `save`, or `remove`. */
|
|
42
|
+
method: ApiAdapterMethod;
|
|
43
|
+
/** The endpoint URL that failed. */
|
|
44
|
+
endpoint: string;
|
|
45
|
+
/** Underlying error (for network failures / parse errors). */
|
|
46
|
+
error?: unknown;
|
|
47
|
+
/** Response object, if a response was received. */
|
|
48
|
+
response?: Response;
|
|
49
|
+
/** HTTP status code, if available. */
|
|
50
|
+
status?: number;
|
|
51
|
+
/** For `save`, the payload that failed to send. */
|
|
52
|
+
payload?: T;
|
|
53
|
+
/** Which retry attempt this is (0 = first try). Capped at `retry.attempts`. */
|
|
54
|
+
attempt: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
declare type ApiAdapterMethod = 'load' | 'save' | 'remove';
|
|
58
|
+
|
|
59
|
+
declare interface ApiAdapterOptions<T = unknown> {
|
|
60
|
+
/**
|
|
61
|
+
* Extra HTTP headers to send with every request. Useful for `Authorization`,
|
|
62
|
+
* `X-CSRF-Token`, `X-Requested-With`, etc.
|
|
63
|
+
*
|
|
64
|
+
* Can also be a function that returns headers, which lets you read a CSRF
|
|
65
|
+
* token from the DOM/cookie at request time rather than at adapter
|
|
66
|
+
* construction time.
|
|
67
|
+
*/
|
|
68
|
+
headers?: Record<string, string> | (() => Record<string, string>);
|
|
69
|
+
/**
|
|
70
|
+
* Forwarded to fetch's `credentials` option. Defaults to `'same-origin'`
|
|
71
|
+
* (the browser default). Set to `'include'` for cross-origin endpoints
|
|
72
|
+
* that need cookies / auth.
|
|
73
|
+
*/
|
|
74
|
+
credentials?: RequestCredentials;
|
|
75
|
+
/**
|
|
76
|
+
* HTTP method override for the load operation. Defaults to `'GET'`.
|
|
77
|
+
*/
|
|
78
|
+
loadMethod?: 'GET' | 'POST';
|
|
79
|
+
/**
|
|
80
|
+
* HTTP method override for the save operation. Defaults to `'POST'`. Some
|
|
81
|
+
* REST APIs prefer `'PUT'` for upsert semantics.
|
|
82
|
+
*/
|
|
83
|
+
saveMethod?: 'POST' | 'PUT' | 'PATCH';
|
|
84
|
+
/**
|
|
85
|
+
* Transform the raw JSON response into the expected `T`. Useful for APIs
|
|
86
|
+
* that wrap responses in `{ data: ... }` or similar envelopes. Called
|
|
87
|
+
* after `res.json()`. If omitted, the parsed JSON is used as-is.
|
|
88
|
+
*/
|
|
89
|
+
unwrap?: (raw: unknown) => T | null;
|
|
90
|
+
/**
|
|
91
|
+
* Retry policy for failed requests. Defaults to no retries (preserves the
|
|
92
|
+
* pre-3.6.0 behaviour). When configured, applies to all three operations.
|
|
93
|
+
*/
|
|
94
|
+
retry?: ApiAdapterRetryConfig;
|
|
95
|
+
/**
|
|
96
|
+
* Called when a request fails (after all retries exhausted). The adapter
|
|
97
|
+
* still returns a graceful null/void result so the consuming hook
|
|
98
|
+
* doesn't crash — this hook is for telemetry, toasts, or audit logging.
|
|
99
|
+
*/
|
|
100
|
+
onError?: (ctx: ApiAdapterErrorContext<T>) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Called when a request succeeds. Useful for cache invalidation,
|
|
103
|
+
* analytics, or syncing other state.
|
|
104
|
+
*/
|
|
105
|
+
onSuccess?: (ctx: ApiAdapterSuccessContext<T>) => void;
|
|
106
|
+
/**
|
|
107
|
+
* Per-request fetch options to merge into every request. Use this for
|
|
108
|
+
* things `fetch` itself supports that aren't directly modelled above —
|
|
109
|
+
* `signal`, `mode`, `cache`, `redirect`, etc.
|
|
110
|
+
*/
|
|
111
|
+
fetchInit?: Omit<RequestInit, 'method' | 'headers' | 'body' | 'credentials'>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare interface ApiAdapterRetryConfig {
|
|
115
|
+
/**
|
|
116
|
+
* Number of additional attempts after the initial request. Defaults to 0
|
|
117
|
+
* (no retries). e.g. `attempts: 2` means up to 3 total requests.
|
|
118
|
+
*/
|
|
119
|
+
attempts?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Base delay in ms between attempts. Defaults to 250ms. The actual delay
|
|
122
|
+
* uses exponential backoff: `baseDelayMs * 2^attempt`.
|
|
123
|
+
*/
|
|
124
|
+
baseDelayMs?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Predicate that decides whether to retry given the failure context. By
|
|
127
|
+
* default we retry on network errors and 5xx responses, but not on 4xx
|
|
128
|
+
* (those are client errors that won't fix themselves).
|
|
129
|
+
*/
|
|
130
|
+
shouldRetry?: (ctx: ApiAdapterErrorContext<unknown>) => boolean;
|
|
131
|
+
}
|
|
7
132
|
|
|
8
|
-
declare interface
|
|
9
|
-
|
|
133
|
+
declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
134
|
+
/** Which adapter operation succeeded — `load`, `save`, or `remove`. */
|
|
135
|
+
method: ApiAdapterMethod;
|
|
136
|
+
/** The endpoint URL. */
|
|
137
|
+
endpoint: string;
|
|
138
|
+
/** Response object. */
|
|
139
|
+
response: Response;
|
|
140
|
+
/** For `load` operations, the parsed (and optionally unwrapped) data. */
|
|
141
|
+
data?: T;
|
|
142
|
+
/** For `save` operations, the payload that was sent. */
|
|
143
|
+
payload?: T;
|
|
10
144
|
}
|
|
11
145
|
|
|
12
146
|
/**
|