@capgo/capacitor-persona 8.1.1 → 8.2.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.
@@ -1,15 +1,16 @@
1
1
  require 'json'
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+ git_url = package['repository']['url'].sub(/\Agit\+/, '')
4
5
 
5
6
  Pod::Spec.new do |s|
6
7
  s.name = 'CapgoCapacitorPersona'
7
8
  s.version = package['version']
8
9
  s.summary = package['description']
9
10
  s.license = package['license']
10
- s.homepage = package['repository']['url']
11
+ s.homepage = package['homepage']
11
12
  s.author = package['author']
12
- s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source = { :git => git_url, :tag => s.version.to_s }
13
14
  s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
15
  s.ios.deployment_target = '15.0'
15
16
  s.dependency 'Capacitor'
package/README.md CHANGED
@@ -1,20 +1,52 @@
1
1
  # @capgo/capacitor-persona
2
- <a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
2
+
3
+ <a href="https://capgo.app/?ref=plugin_persona"><img src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-persona" alt="Capgo - Build Capacitor apps with AI, ship updates instantly" /></a>
3
4
 
4
5
  <div align="center">
5
- <h2><a href="https://capgo.app/?ref=plugin_persona"> ➡️ Get Instant updates for your App with Capgo</a></h2>
6
- <h2><a href="https://capgo.app/consulting/?ref=plugin_persona"> Missing a feature? We’ll build the plugin for you 💪</a></h2>
6
+ <p><b>Capgo</b>: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and roll back in one click.</p>
7
+ <h2><a href="https://capgo.app/register/?ref=plugin_persona">➡️ Get started for free</a></h2>
8
+ <p>14-day unlimited free trial. No credit card required</p>
9
+ <p><a href="https://capgo.app/consulting/?ref=plugin_persona">Missing a feature? We'll build the plugin for you 💪</a></p>
7
10
  </div>
8
11
 
9
- Capacitor plugin for launching Persona Inquiry flows in iOS and Android apps.
12
+ > 🤖 **Building with an AI coding agent?** Install [Capgo skills](https://capgo.app/skills/?ref=plugin_persona) so Claude Code, Codex, Cursor, Copilot, or Gemini CLI know how to install and use `@capgo/capacitor-persona` in your Capacitor app: `npx skills add Cap-go/capgo-skills`. Then ask your agent: *"Add @capgo/capacitor-persona to my Capacitor app and wire it up."* [Agent setup guides](https://capgo.app/agents/?ref=plugin_persona) · [Hosted MCP](https://capgo.app/docs/ai/mcp/?ref=plugin_persona)
13
+
14
+ <p align="center">
15
+ <img src="https://capgo.app/icons/plugins/persona.svg" alt="Persona plugin icon" width="300" />
16
+ </p>
17
+
18
+ Launch [Persona Inquiry](https://docs.withpersona.com/docs/inquiry-overview) flows from Capacitor apps on iOS and Android. Use template IDs or resume existing inquiries, prefill fields, and listen for completion, cancel, and error events in JavaScript.
19
+
20
+ ## What it covers
21
+
22
+ - Start a Persona Inquiry from a template ID, template version, or existing inquiry ID
23
+ - Prefill inquiry fields and set sandbox or production environment
24
+ - Receive `inquiryComplete`, `inquiryCanceled`, and `inquiryError` events in the WebView layer
25
+ - Native Persona SDK integration on iOS (`PersonaInquirySDK2`) and Android (`com.withpersona.sdk2:inquiry`)
10
26
 
11
27
  ## Install
12
28
 
29
+ You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
30
+
31
+ ```bash
32
+ npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins
33
+ ```
34
+
35
+ Then use the following prompt:
36
+
37
+ ```text
38
+ Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-persona` plugin in my project.
39
+ ```
40
+
41
+ If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
42
+
13
43
  ```bash
14
- bun add @capgo/capacitor-persona
15
- bunx cap sync
44
+ npm install @capgo/capacitor-persona
45
+ npx cap sync
16
46
  ```
17
47
 
48
+ Docs: [capgo.app/docs/plugins/persona/](https://capgo.app/docs/plugins/persona/)
49
+
18
50
  ## Usage
19
51
 
20
52
  ```ts
@@ -44,11 +76,41 @@ await Persona.startInquiry({
44
76
  });
45
77
  ```
46
78
 
47
- ## Integration Notes
79
+ Use Persona webhooks on your backend for authoritative verification status. SDK callbacks are best for UX, not compliance decisions.
80
+
81
+ ## iOS setup
82
+
83
+ 1. Run `npx cap sync ios`.
84
+ 2. Ensure iOS deployment target is **15.0** or newer (matches the plugin podspec).
85
+ 3. Add usage descriptions to `ios/App/App/Info.plist` (Persona may use camera, location, and Bluetooth during verification):
86
+
87
+ ```xml
88
+ <key>NSCameraUsageDescription</key>
89
+ <string>We use the camera to verify your identity.</string>
90
+ <key>NSLocationWhenInUseUsageDescription</key>
91
+ <string>We use your location during identity verification.</string>
92
+ <key>NSBluetoothAlwaysUsageDescription</key>
93
+ <string>We use Bluetooth during identity verification when required.</string>
94
+ ```
95
+
96
+ 4. CocoaPods: the plugin podspec pulls `PersonaInquirySDK2` **2.41.2**. Swift Package Manager projects resolve `inquiry-ios-2` via the plugin `Package.swift`.
97
+
98
+ ## Android setup
48
99
 
49
- - iOS requires Persona usage descriptions in `Info.plist`, including `NSCameraUsageDescription`, `NSLocationWhenInUseUsageDescription`, and `NSBluetoothAlwaysUsageDescription`.
50
- - Android uses Persona's Maven repository (`https://sdk.withpersona.com/android/releases`) and bundles `com.withpersona.sdk2:inquiry`.
51
- - For critical business logic, rely on Persona webhooks instead of SDK callbacks.
100
+ 1. Run `npx cap sync android`.
101
+ 2. In the app root `android/build.gradle`, add Persona's Maven repository so Gradle can resolve the inquiry SDK:
102
+
103
+ ```gradle
104
+ allprojects {
105
+ repositories {
106
+ google()
107
+ mavenCentral()
108
+ maven { url 'https://sdk.withpersona.com/android/releases' }
109
+ }
110
+ }
111
+ ```
112
+
113
+ 3. The plugin library targets **minSdk 24** and depends on `com.withpersona.sdk2:inquiry` (default **2.32.1**, overridable with `personaInquiryVersion` in Gradle).
52
114
 
53
115
  ## API
54
116
 
@@ -150,28 +212,6 @@ Remove all registered listeners for this plugin instance.
150
212
  ### Interfaces
151
213
 
152
214
 
153
- #### StartInquiryOptions
154
-
155
- Input payload used to launch an Inquiry.
156
-
157
- Provide at least one of:
158
- - `templateId`
159
- - `templateVersion`
160
- - `inquiryId`
161
-
162
- | Prop | Type | Description | Default |
163
- | --------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------------------------- |
164
- | **`inquiryId`** | <code>string</code> | Existing Inquiry ID created on your backend. | |
165
- | **`sessionToken`** | <code>string</code> | Session token required when resuming an existing Inquiry. | |
166
- | **`templateId`** | <code>string</code> | Inquiry template ID from Persona Dashboard (recommended). | |
167
- | **`templateVersion`** | <code>string</code> | Inquiry template version ID from Persona Dashboard. | |
168
- | **`referenceId`** | <code>string</code> | Your internal user reference. | |
169
- | **`accountId`** | <code>string</code> | Persona account ID. | |
170
- | **`environment`** | <code><a href="#personaenvironment">PersonaEnvironment</a></code> | Persona environment. | <code>'production'</code> |
171
- | **`locale`** | <code>string</code> | Locale override, for example `en`, `fr`, `es`. | |
172
- | **`fields`** | <code><a href="#record">Record</a>&lt;string, <a href="#personafieldvalue">PersonaFieldValue</a>&gt;</code> | Optional fields pre-written into the Inquiry. | |
173
-
174
-
175
215
  #### PluginListenerHandle
176
216
 
177
217
  | Prop | Type |
@@ -214,6 +254,20 @@ Payload emitted when an Inquiry errors.
214
254
  ### Type Aliases
215
255
 
216
256
 
257
+ #### StartInquiryOptions
258
+
259
+ Input payload used to launch an Inquiry.
260
+
261
+ Provide exactly one of `inquiryId`, `templateId`, or `templateVersion`.
262
+
263
+ <code><a href="#startinquirysharedoptions">StartInquirySharedOptions</a> & ( | { /** * Existing Inquiry ID created on your backend. */ inquiryId: string; templateId?: never; templateVersion?: never; } | { /** * Inquiry template ID from Persona Dashboard (recommended). */ templateId: string; inquiryId?: never; templateVersion?: never; } | { /** * Inquiry template version ID from Persona Dashboard. */ templateVersion: string; inquiryId?: never; templateId?: never; } )</code>
264
+
265
+
266
+ #### StartInquirySharedOptions
267
+
268
+ <code>{ /** * Session token required when resuming an existing Inquiry. */ sessionToken?: string; /** * Your internal user reference. */ referenceId?: string; /** * Persona account ID. */ accountId?: string; /** * Persona environment. * * @default 'production' */ environment?: <a href="#personaenvironment">PersonaEnvironment</a>; /** * Locale override, for example `en`, `fr`, `es`. * * Not supported on iOS when `templateVersion` is used. */ locale?: string; /** * Optional fields pre-written into the Inquiry. */ fields?: <a href="#record">Record</a>&lt;string, <a href="#personafieldvalue">PersonaFieldValue</a>&gt;; }</code>
269
+
270
+
217
271
  #### PersonaEnvironment
218
272
 
219
273
  Environment where Persona should run.
@@ -4,7 +4,7 @@ ext {
4
4
  androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.10.1'
5
5
  androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
6
6
  androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
7
- personaInquiryVersion = project.hasProperty('personaInquiryVersion') ? rootProject.ext.personaInquiryVersion : '2.32.1'
7
+ personaInquiryVersion = project.findProperty('personaInquiryVersion') ?: '2.32.1'
8
8
  }
9
9
 
10
10
  buildscript {
@@ -59,6 +59,9 @@ public class PersonaPlugin extends Plugin {
59
59
  Fields fields = toFields(call.getObject("fields"));
60
60
 
61
61
  if (inquiryId != null) {
62
+ if (environment != null) {
63
+ throw new IllegalArgumentException("The environment option cannot be used when resuming an inquiry by inquiryId.");
64
+ }
62
65
  InquiryBuilder builder = Inquiry.fromInquiry(inquiryId);
63
66
  if (sessionToken != null) {
64
67
  builder.sessionToken(sessionToken);
@@ -129,6 +132,9 @@ public class PersonaPlugin extends Plugin {
129
132
  } else {
130
133
  double asDouble = number.doubleValue();
131
134
  if (Math.floor(asDouble) == asDouble) {
135
+ if (asDouble < Integer.MIN_VALUE || asDouble > Integer.MAX_VALUE) {
136
+ throw new IllegalArgumentException("Integer Persona field '" + key + "' is outside the supported range.");
137
+ }
132
138
  builder.field(key, number.intValue());
133
139
  } else {
134
140
  builder.field(key, number.floatValue());
@@ -223,11 +229,11 @@ public class PersonaPlugin extends Plugin {
223
229
  }
224
230
  if (field instanceof InquiryField.DateField) {
225
231
  java.util.Date date = ((InquiryField.DateField) field).getValue();
226
- return date != null ? date.getTime() : JSONObject.NULL;
232
+ return date != null ? date.getTime() / 1000.0 : JSONObject.NULL;
227
233
  }
228
234
  if (field instanceof InquiryField.DatetimeField) {
229
235
  java.util.Date date = ((InquiryField.DatetimeField) field).getValue();
230
- return date != null ? date.getTime() : JSONObject.NULL;
236
+ return date != null ? date.getTime() / 1000.0 : JSONObject.NULL;
231
237
  }
232
238
  if (field instanceof InquiryField.ChoicesField) {
233
239
  return ((InquiryField.ChoicesField) field).getValue();
package/dist/docs.json CHANGED
@@ -109,88 +109,6 @@
109
109
  "properties": []
110
110
  },
111
111
  "interfaces": [
112
- {
113
- "name": "StartInquiryOptions",
114
- "slug": "startinquiryoptions",
115
- "docs": "Input payload used to launch an Inquiry.\n\nProvide at least one of:\n- `templateId`\n- `templateVersion`\n- `inquiryId`",
116
- "tags": [],
117
- "methods": [],
118
- "properties": [
119
- {
120
- "name": "inquiryId",
121
- "tags": [],
122
- "docs": "Existing Inquiry ID created on your backend.",
123
- "complexTypes": [],
124
- "type": "string | undefined"
125
- },
126
- {
127
- "name": "sessionToken",
128
- "tags": [],
129
- "docs": "Session token required when resuming an existing Inquiry.",
130
- "complexTypes": [],
131
- "type": "string | undefined"
132
- },
133
- {
134
- "name": "templateId",
135
- "tags": [],
136
- "docs": "Inquiry template ID from Persona Dashboard (recommended).",
137
- "complexTypes": [],
138
- "type": "string | undefined"
139
- },
140
- {
141
- "name": "templateVersion",
142
- "tags": [],
143
- "docs": "Inquiry template version ID from Persona Dashboard.",
144
- "complexTypes": [],
145
- "type": "string | undefined"
146
- },
147
- {
148
- "name": "referenceId",
149
- "tags": [],
150
- "docs": "Your internal user reference.",
151
- "complexTypes": [],
152
- "type": "string | undefined"
153
- },
154
- {
155
- "name": "accountId",
156
- "tags": [],
157
- "docs": "Persona account ID.",
158
- "complexTypes": [],
159
- "type": "string | undefined"
160
- },
161
- {
162
- "name": "environment",
163
- "tags": [
164
- {
165
- "text": "'production'",
166
- "name": "default"
167
- }
168
- ],
169
- "docs": "Persona environment.",
170
- "complexTypes": [
171
- "PersonaEnvironment"
172
- ],
173
- "type": "PersonaEnvironment"
174
- },
175
- {
176
- "name": "locale",
177
- "tags": [],
178
- "docs": "Locale override, for example `en`, `fr`, `es`.",
179
- "complexTypes": [],
180
- "type": "string | undefined"
181
- },
182
- {
183
- "name": "fields",
184
- "tags": [],
185
- "docs": "Optional fields pre-written into the Inquiry.",
186
- "complexTypes": [
187
- "Record",
188
- "PersonaFieldValue"
189
- ],
190
- "type": "Record<string, PersonaFieldValue>"
191
- }
192
- ]
193
- },
194
112
  {
195
113
  "name": "PluginListenerHandle",
196
114
  "slug": "pluginlistenerhandle",
@@ -296,6 +214,34 @@
296
214
  ],
297
215
  "enums": [],
298
216
  "typeAliases": [
217
+ {
218
+ "name": "StartInquiryOptions",
219
+ "slug": "startinquiryoptions",
220
+ "docs": "Input payload used to launch an Inquiry.\n\nProvide exactly one of `inquiryId`, `templateId`, or `templateVersion`.",
221
+ "types": [
222
+ {
223
+ "text": "StartInquirySharedOptions &\n (\n | {\n /**\n * Existing Inquiry ID created on your backend.\n */\n inquiryId: string;\n templateId?: never;\n templateVersion?: never;\n }\n | {\n /**\n * Inquiry template ID from Persona Dashboard (recommended).\n */\n templateId: string;\n inquiryId?: never;\n templateVersion?: never;\n }\n | {\n /**\n * Inquiry template version ID from Persona Dashboard.\n */\n templateVersion: string;\n inquiryId?: never;\n templateId?: never;\n }\n )",
224
+ "complexTypes": [
225
+ "StartInquirySharedOptions"
226
+ ]
227
+ }
228
+ ]
229
+ },
230
+ {
231
+ "name": "StartInquirySharedOptions",
232
+ "slug": "startinquirysharedoptions",
233
+ "docs": "",
234
+ "types": [
235
+ {
236
+ "text": "{\n /**\n * Session token required when resuming an existing Inquiry.\n */\n sessionToken?: string;\n\n /**\n * Your internal user reference.\n */\n referenceId?: string;\n\n /**\n * Persona account ID.\n */\n accountId?: string;\n\n /**\n * Persona environment.\n *\n * @default 'production'\n */\n environment?: PersonaEnvironment;\n\n /**\n * Locale override, for example `en`, `fr`, `es`.\n *\n * Not supported on iOS when `templateVersion` is used.\n */\n locale?: string;\n\n /**\n * Optional fields pre-written into the Inquiry.\n */\n fields?: Record<string, PersonaFieldValue>;\n}",
237
+ "complexTypes": [
238
+ "PersonaEnvironment",
239
+ "Record",
240
+ "PersonaFieldValue"
241
+ ]
242
+ }
243
+ ]
244
+ },
299
245
  {
300
246
  "name": "PersonaEnvironment",
301
247
  "slug": "personaenvironment",
@@ -11,31 +11,11 @@ export type PersonaFieldValue = string | number | boolean | string[];
11
11
  * Serialized field value returned in Inquiry result callbacks.
12
12
  */
13
13
  export type PersonaResultFieldValue = string | number | boolean | string[] | null;
14
- /**
15
- * Input payload used to launch an Inquiry.
16
- *
17
- * Provide at least one of:
18
- * - `templateId`
19
- * - `templateVersion`
20
- * - `inquiryId`
21
- */
22
- export interface StartInquiryOptions {
23
- /**
24
- * Existing Inquiry ID created on your backend.
25
- */
26
- inquiryId?: string;
14
+ type StartInquirySharedOptions = {
27
15
  /**
28
16
  * Session token required when resuming an existing Inquiry.
29
17
  */
30
18
  sessionToken?: string;
31
- /**
32
- * Inquiry template ID from Persona Dashboard (recommended).
33
- */
34
- templateId?: string;
35
- /**
36
- * Inquiry template version ID from Persona Dashboard.
37
- */
38
- templateVersion?: string;
39
19
  /**
40
20
  * Your internal user reference.
41
21
  */
@@ -52,13 +32,42 @@ export interface StartInquiryOptions {
52
32
  environment?: PersonaEnvironment;
53
33
  /**
54
34
  * Locale override, for example `en`, `fr`, `es`.
35
+ *
36
+ * Not supported on iOS when `templateVersion` is used.
55
37
  */
56
38
  locale?: string;
57
39
  /**
58
40
  * Optional fields pre-written into the Inquiry.
59
41
  */
60
42
  fields?: Record<string, PersonaFieldValue>;
61
- }
43
+ };
44
+ /**
45
+ * Input payload used to launch an Inquiry.
46
+ *
47
+ * Provide exactly one of `inquiryId`, `templateId`, or `templateVersion`.
48
+ */
49
+ export type StartInquiryOptions = StartInquirySharedOptions & ({
50
+ /**
51
+ * Existing Inquiry ID created on your backend.
52
+ */
53
+ inquiryId: string;
54
+ templateId?: never;
55
+ templateVersion?: never;
56
+ } | {
57
+ /**
58
+ * Inquiry template ID from Persona Dashboard (recommended).
59
+ */
60
+ templateId: string;
61
+ inquiryId?: never;
62
+ templateVersion?: never;
63
+ } | {
64
+ /**
65
+ * Inquiry template version ID from Persona Dashboard.
66
+ */
67
+ templateVersion: string;
68
+ inquiryId?: never;
69
+ templateId?: never;
70
+ });
62
71
  /**
63
72
  * Payload emitted when an Inquiry is completed.
64
73
  */
@@ -104,3 +113,4 @@ export interface PersonaPlugin {
104
113
  */
105
114
  removeAllListeners(): Promise<void>;
106
115
  }
116
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * Environment where Persona should run.\n */\nexport type PersonaEnvironment = 'production' | 'sandbox';\n\n/**\n * Supported field value types for pre-writing Inquiry fields.\n */\nexport type PersonaFieldValue = string | number | boolean | string[];\n\n/**\n * Serialized field value returned in Inquiry result callbacks.\n */\nexport type PersonaResultFieldValue = string | number | boolean | string[] | null;\n\n/**\n * Input payload used to launch an Inquiry.\n *\n * Provide at least one of:\n * - `templateId`\n * - `templateVersion`\n * - `inquiryId`\n */\nexport interface StartInquiryOptions {\n /**\n * Existing Inquiry ID created on your backend.\n */\n inquiryId?: string;\n\n /**\n * Session token required when resuming an existing Inquiry.\n */\n sessionToken?: string;\n\n /**\n * Inquiry template ID from Persona Dashboard (recommended).\n */\n templateId?: string;\n\n /**\n * Inquiry template version ID from Persona Dashboard.\n */\n templateVersion?: string;\n\n /**\n * Your internal user reference.\n */\n referenceId?: string;\n\n /**\n * Persona account ID.\n */\n accountId?: string;\n\n /**\n * Persona environment.\n *\n * @default 'production'\n */\n environment?: PersonaEnvironment;\n\n /**\n * Locale override, for example `en`, `fr`, `es`.\n */\n locale?: string;\n\n /**\n * Optional fields pre-written into the Inquiry.\n */\n fields?: Record<string, PersonaFieldValue>;\n}\n\n/**\n * Payload emitted when an Inquiry is completed.\n */\nexport interface InquiryCompleteInfo {\n inquiryId: string;\n status: string;\n fields: Record<string, PersonaResultFieldValue>;\n}\n\n/**\n * Payload emitted when an Inquiry is canceled.\n */\nexport interface InquiryCanceledInfo {\n inquiryId?: string;\n sessionToken?: string;\n}\n\n/**\n * Payload emitted when an Inquiry errors.\n */\nexport interface InquiryErrorInfo {\n error: string;\n errorCode?: string;\n cause?: string;\n}\n\nexport interface PersonaPlugin {\n /**\n * Launch a Persona Inquiry flow.\n */\n startInquiry(options: StartInquiryOptions): Promise<void>;\n\n /**\n * Listen for successful completion.\n */\n addListener(\n eventName: 'inquiryComplete',\n listenerFunc: (info: InquiryCompleteInfo) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for cancellation.\n */\n addListener(\n eventName: 'inquiryCanceled',\n listenerFunc: (info: InquiryCanceledInfo) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for unrecoverable errors.\n */\n addListener(eventName: 'inquiryError', listenerFunc: (info: InquiryErrorInfo) => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all registered listeners for this plugin instance.\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\n/**\n * Environment where Persona should run.\n */\nexport type PersonaEnvironment = 'production' | 'sandbox';\n\n/**\n * Supported field value types for pre-writing Inquiry fields.\n */\nexport type PersonaFieldValue = string | number | boolean | string[];\n\n/**\n * Serialized field value returned in Inquiry result callbacks.\n */\nexport type PersonaResultFieldValue = string | number | boolean | string[] | null;\n\ntype StartInquirySharedOptions = {\n /**\n * Session token required when resuming an existing Inquiry.\n */\n sessionToken?: string;\n\n /**\n * Your internal user reference.\n */\n referenceId?: string;\n\n /**\n * Persona account ID.\n */\n accountId?: string;\n\n /**\n * Persona environment.\n *\n * @default 'production'\n */\n environment?: PersonaEnvironment;\n\n /**\n * Locale override, for example `en`, `fr`, `es`.\n *\n * Not supported on iOS when `templateVersion` is used.\n */\n locale?: string;\n\n /**\n * Optional fields pre-written into the Inquiry.\n */\n fields?: Record<string, PersonaFieldValue>;\n};\n\n/**\n * Input payload used to launch an Inquiry.\n *\n * Provide exactly one of `inquiryId`, `templateId`, or `templateVersion`.\n */\nexport type StartInquiryOptions = StartInquirySharedOptions &\n (\n | {\n /**\n * Existing Inquiry ID created on your backend.\n */\n inquiryId: string;\n templateId?: never;\n templateVersion?: never;\n }\n | {\n /**\n * Inquiry template ID from Persona Dashboard (recommended).\n */\n templateId: string;\n inquiryId?: never;\n templateVersion?: never;\n }\n | {\n /**\n * Inquiry template version ID from Persona Dashboard.\n */\n templateVersion: string;\n inquiryId?: never;\n templateId?: never;\n }\n );\n\n/**\n * Payload emitted when an Inquiry is completed.\n */\nexport interface InquiryCompleteInfo {\n inquiryId: string;\n status: string;\n fields: Record<string, PersonaResultFieldValue>;\n}\n\n/**\n * Payload emitted when an Inquiry is canceled.\n */\nexport interface InquiryCanceledInfo {\n inquiryId?: string;\n sessionToken?: string;\n}\n\n/**\n * Payload emitted when an Inquiry errors.\n */\nexport interface InquiryErrorInfo {\n error: string;\n errorCode?: string;\n cause?: string;\n}\n\nexport interface PersonaPlugin {\n /**\n * Launch a Persona Inquiry flow.\n */\n startInquiry(options: StartInquiryOptions): Promise<void>;\n\n /**\n * Listen for successful completion.\n */\n addListener(\n eventName: 'inquiryComplete',\n listenerFunc: (info: InquiryCompleteInfo) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for cancellation.\n */\n addListener(\n eventName: 'inquiryCanceled',\n listenerFunc: (info: InquiryCanceledInfo) => void,\n ): Promise<PluginListenerHandle>;\n\n /**\n * Listen for unrecoverable errors.\n */\n addListener(eventName: 'inquiryError', listenerFunc: (info: InquiryErrorInfo) => void): Promise<PluginListenerHandle>;\n\n /**\n * Remove all registered listeners for this plugin instance.\n */\n removeAllListeners(): Promise<void>;\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
2
  import type { PersonaPlugin, StartInquiryOptions } from './definitions';
3
3
  export declare class PersonaWeb extends WebPlugin implements PersonaPlugin {
4
- startInquiry(_options: StartInquiryOptions): Promise<void>;
4
+ startInquiry(options: StartInquiryOptions): Promise<void>;
5
5
  }
package/dist/esm/web.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
2
  export class PersonaWeb extends WebPlugin {
3
- async startInquiry(_options) {
3
+ async startInquiry(options) {
4
+ void options;
4
5
  throw this.unavailable('Persona Inquiry is only available on iOS and Android.');
5
6
  }
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,KAAK,CAAC,YAAY,CAAC,QAA6B;QAC9C,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC,CAAC;IAClF,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { PersonaPlugin, StartInquiryOptions } from './definitions';\n\nexport class PersonaWeb extends WebPlugin implements PersonaPlugin {\n async startInquiry(_options: StartInquiryOptions): Promise<void> {\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,KAAK,CAAC,YAAY,CAAC,OAA4B;QAC7C,KAAK,OAAO,CAAC;QACb,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC,CAAC;IAClF,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { PersonaPlugin, StartInquiryOptions } from './definitions';\n\nexport class PersonaWeb extends WebPlugin implements PersonaPlugin {\n async startInquiry(options: StartInquiryOptions): Promise<void> {\n void options;\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n"]}
@@ -7,7 +7,7 @@ const Persona = core.registerPlugin('Persona', {
7
7
  });
8
8
 
9
9
  class PersonaWeb extends core.WebPlugin {
10
- async startInquiry(_options) {
10
+ async startInquiry(options) {
11
11
  throw this.unavailable('Persona Inquiry is only available on iOS and Android.');
12
12
  }
13
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Persona = registerPlugin('Persona', {\n web: () => import('./web').then((m) => new m.PersonaWeb()),\n});\nexport * from './definitions';\nexport { Persona };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PersonaWeb extends WebPlugin {\n async startInquiry(_options) {\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;AAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;AAC9D,CAAC;;ACFM,MAAM,UAAU,SAASC,cAAS,CAAC;AAC1C,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;AACjC,QAAQ,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC;AACvF,IAAI;AACJ;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Persona = registerPlugin('Persona', {\n web: () => import('./web').then((m) => new m.PersonaWeb()),\n});\nexport * from './definitions';\nexport { Persona };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PersonaWeb extends WebPlugin {\n async startInquiry(options) {\n void options;\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;AAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;AAC9D,CAAC;;ACFM,MAAM,UAAU,SAASC,cAAS,CAAC;AAC1C,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;AAEhC,QAAQ,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC;AACvF,IAAI;AACJ;;;;;;;"}
package/dist/plugin.js CHANGED
@@ -6,7 +6,7 @@ var capacitorPersona = (function (exports, core) {
6
6
  });
7
7
 
8
8
  class PersonaWeb extends core.WebPlugin {
9
- async startInquiry(_options) {
9
+ async startInquiry(options) {
10
10
  throw this.unavailable('Persona Inquiry is only available on iOS and Android.');
11
11
  }
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Persona = registerPlugin('Persona', {\n web: () => import('./web').then((m) => new m.PersonaWeb()),\n});\nexport * from './definitions';\nexport { Persona };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PersonaWeb extends WebPlugin {\n async startInquiry(_options) {\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;IAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9D,CAAC;;ICFM,MAAM,UAAU,SAASC,cAAS,CAAC;IAC1C,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;IACjC,QAAQ,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC;IACvF,IAAI;IACJ;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Persona = registerPlugin('Persona', {\n web: () => import('./web').then((m) => new m.PersonaWeb()),\n});\nexport * from './definitions';\nexport { Persona };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class PersonaWeb extends WebPlugin {\n async startInquiry(options) {\n void options;\n throw this.unavailable('Persona Inquiry is only available on iOS and Android.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;IAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9D,CAAC;;ICFM,MAAM,UAAU,SAASC,cAAS,CAAC;IAC1C,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;IAEhC,QAAQ,MAAM,IAAI,CAAC,WAAW,CAAC,uDAAuD,CAAC;IACvF,IAAI;IACJ;;;;;;;;;;;"}
@@ -30,17 +30,27 @@ public class PersonaPlugin: CAPPlugin, CAPBridgedPlugin {
30
30
  }
31
31
 
32
32
  private func buildInquiry(call: CAPPluginCall) throws -> Inquiry {
33
- let inquiryId = call.getString("inquiryId")
34
- let sessionToken = call.getString("sessionToken")
35
- let templateId = call.getString("templateId")
36
- let templateVersion = call.getString("templateVersion")
37
- let referenceId = call.getString("referenceId")
38
- let accountId = call.getString("accountId")
39
- let locale = call.getString("locale")
33
+ func opt(_ key: String) -> String? {
34
+ guard let value = call.getString(key)?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else {
35
+ return nil
36
+ }
37
+ return value
38
+ }
39
+
40
+ let inquiryId = opt("inquiryId")
41
+ let sessionToken = opt("sessionToken")
42
+ let templateId = opt("templateId")
43
+ let templateVersion = opt("templateVersion")
44
+ let referenceId = opt("referenceId")
45
+ let accountId = opt("accountId")
46
+ let locale = opt("locale")
40
47
  let fields = makeInquiryFields(from: call.getObject("fields") ?? [:])
41
- let environment = try parseEnvironment(call.getString("environment"))
48
+ let environment = try parseEnvironment(opt("environment"))
42
49
 
43
50
  if let inquiryId {
51
+ if environment != nil {
52
+ throw PersonaPluginError.environmentNotAllowedForResume
53
+ }
44
54
  let builder = Inquiry.from(inquiryId: inquiryId, delegate: self)
45
55
  if let sessionToken {
46
56
  _ = builder.sessionToken(sessionToken)
@@ -107,6 +117,19 @@ public class PersonaPlugin: CAPPlugin, CAPBridgedPlugin {
107
117
 
108
118
  for (key, value) in dictionary {
109
119
  switch value {
120
+ case let value as NSNumber:
121
+ if CFGetTypeID(value) == CFBooleanGetTypeID() {
122
+ output[key] = .bool(value.boolValue)
123
+ } else {
124
+ let doubleValue = value.doubleValue
125
+ if doubleValue.rounded() == doubleValue,
126
+ doubleValue >= Double(Int.min),
127
+ doubleValue < -Double(Int.min) {
128
+ output[key] = .int(value.intValue)
129
+ } else {
130
+ output[key] = .float(value.floatValue)
131
+ }
132
+ }
110
133
  case let value as String:
111
134
  output[key] = .string(value)
112
135
  case let value as Bool:
@@ -117,14 +140,6 @@ public class PersonaPlugin: CAPPlugin, CAPBridgedPlugin {
117
140
  output[key] = .float(value)
118
141
  case let value as Double:
119
142
  output[key] = .float(Float(value))
120
- case let value as NSNumber:
121
- if CFGetTypeID(value) == CFBooleanGetTypeID() {
122
- output[key] = .bool(value.boolValue)
123
- } else if value.doubleValue.rounded() == value.doubleValue {
124
- output[key] = .int(value.intValue)
125
- } else {
126
- output[key] = .float(value.floatValue)
127
- }
128
143
  case let value as Date:
129
144
  output[key] = .datetime(value)
130
145
  case let values as [String]:
@@ -200,6 +215,7 @@ private enum PersonaPluginError: LocalizedError {
200
215
  case invalidEnvironment(String)
201
216
  case invalidConfiguration
202
217
  case templateVersionLocaleUnsupported
218
+ case environmentNotAllowedForResume
203
219
 
204
220
  var errorDescription: String? {
205
221
  switch self {
@@ -211,6 +227,8 @@ private enum PersonaPluginError: LocalizedError {
211
227
  return "Unable to build a Persona inquiry configuration with the provided options."
212
228
  case .templateVersionLocaleUnsupported:
213
229
  return "The locale option is not supported when starting an inquiry with templateVersion on iOS."
230
+ case .environmentNotAllowedForResume:
231
+ return "The environment option cannot be used when resuming an inquiry by inquiryId."
214
232
  }
215
233
  }
216
234
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-persona",
3
- "version": "8.1.1",
3
+ "version": "8.2.1",
4
4
  "description": "Capacitor plugin for launching Persona Inquiry flows on iOS and Android.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -33,7 +33,6 @@
33
33
  "identity-verification"
34
34
  ],
35
35
  "scripts": {
36
- "init-plugin": "./scripts/init-plugin.sh",
37
36
  "verify": "bun run verify:ios && bun run verify:android && bun run verify:web",
38
37
  "verify:ios": "xcodebuild -scheme CapgoCapacitorPersona -destination generic/platform=iOS",
39
38
  "verify:android": "cd android && ./gradlew clean build test && cd ..",
@@ -48,7 +47,10 @@
48
47
  "clean": "rimraf ./dist",
49
48
  "watch": "tsc --watch",
50
49
  "prepublishOnly": "bun run build",
51
- "check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs"
50
+ "check:wiring": "bun scripts/check-capacitor-plugin-wiring.mjs",
51
+ "check:package-identity": "node scripts/check-package-identity.mjs",
52
+ "check:cap9-deprecated": "node scripts/check-cap9-deprecated.mjs",
53
+ "changelog:ai": "node scripts/generate-ai-changelog.mjs"
52
54
  },
53
55
  "devDependencies": {
54
56
  "@capacitor/android": "^8.0.0",