@explorins/pers-sdk 2.1.40 → 2.2.0-alpha.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.
Files changed (33) hide show
  1. package/dist/chunks/{pers-sdk-DuDWwRWC.js → pers-sdk-CBRtrG03.js} +458 -4
  2. package/dist/chunks/pers-sdk-CBRtrG03.js.map +1 -0
  3. package/dist/chunks/{pers-sdk-CBvzmlL_.cjs → pers-sdk-DcNDMx1Y.cjs} +457 -2
  4. package/dist/chunks/pers-sdk-DcNDMx1Y.cjs.map +1 -0
  5. package/dist/core/events/event-types.d.ts +5 -1
  6. package/dist/core/events/event-types.d.ts.map +1 -1
  7. package/dist/core.cjs +2 -1
  8. package/dist/core.cjs.map +1 -1
  9. package/dist/core.js +1 -1
  10. package/dist/custom-field/api/custom-field-api.d.ts +58 -0
  11. package/dist/custom-field/api/custom-field-api.d.ts.map +1 -0
  12. package/dist/custom-field/index.d.ts +2 -0
  13. package/dist/custom-field/index.d.ts.map +1 -0
  14. package/dist/index.cjs +141 -26
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +82 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/managers/custom-field-definition-manager.d.ts +317 -0
  19. package/dist/managers/custom-field-definition-manager.d.ts.map +1 -0
  20. package/dist/managers/index.d.ts +1 -0
  21. package/dist/managers/index.d.ts.map +1 -1
  22. package/dist/node.cjs +1 -1
  23. package/dist/node.js +1 -1
  24. package/dist/package.json +2 -2
  25. package/dist/pers-sdk.d.ts +28 -1
  26. package/dist/pers-sdk.d.ts.map +1 -1
  27. package/dist/shared/index.d.ts +1 -0
  28. package/dist/shared/index.d.ts.map +1 -1
  29. package/dist/shared/utils/image-url-utils.d.ts +76 -0
  30. package/dist/shared/utils/image-url-utils.d.ts.map +1 -0
  31. package/package.json +2 -2
  32. package/dist/chunks/pers-sdk-CBvzmlL_.cjs.map +0 -1
  33. package/dist/chunks/pers-sdk-DuDWwRWC.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { AccountOwnerType, MembershipRole, WebhookMethod, WebhookExecutionStatus } from '@explorins/pers-shared';
1
+ import { AccountOwnerType, MembershipRole, WebhookMethod, WebhookExecutionStatus, validateAllFields, validateFieldValue } from '@explorins/pers-shared';
2
2
  import { i as isTokenExpired, d as decodeJwtPayload, e as getTokenTimeToLive, E as ErrorUtils, A as AuthenticationError, b as PersApiError } from './index--OssIds0.js';
3
3
  import { UserService, UserApi } from '../user.js';
4
4
  import { createUserStatusSDK } from '../user-status.js';
@@ -1585,7 +1585,7 @@ class DefaultAuthProvider {
1585
1585
  /** SDK package name */
1586
1586
  const SDK_NAME = "@explorins/pers-sdk";
1587
1587
  /** SDK version - injected from package.json at build time */
1588
- const SDK_VERSION = "2.1.40";
1588
+ const SDK_VERSION = "2.2.0-alpha.1";
1589
1589
  /** Full SDK identifier for headers */
1590
1590
  const SDK_USER_AGENT = `${SDK_NAME}/${SDK_VERSION}`;
1591
1591
 
@@ -10106,6 +10106,429 @@ class WalletEventsManager {
10106
10106
  }
10107
10107
  }
10108
10108
 
10109
+ /**
10110
+ * Custom Field Definitions API
10111
+ *
10112
+ * Low-level API for custom field definition CRUD operations.
10113
+ * Used internally by CustomFieldDefinitionManager.
10114
+ *
10115
+ * @internal
10116
+ */
10117
+ class CustomFieldApi {
10118
+ constructor(apiClient) {
10119
+ this.apiClient = apiClient;
10120
+ this.basePath = '/custom-field-definitions';
10121
+ }
10122
+ /**
10123
+ * List all custom field definitions
10124
+ * Backend returns non-paginated array sorted by sortOrder
10125
+ */
10126
+ async getDefinitions(entityType) {
10127
+ const params = new URLSearchParams();
10128
+ if (entityType) {
10129
+ params.append('entityType', entityType);
10130
+ }
10131
+ const query = params.toString();
10132
+ const url = query ? `${this.basePath}?${query}` : this.basePath;
10133
+ return this.apiClient.get(url);
10134
+ }
10135
+ /**
10136
+ * Get a single custom field definition by ID
10137
+ */
10138
+ async getDefinition(id) {
10139
+ return this.apiClient.get(`${this.basePath}/${id}`);
10140
+ }
10141
+ /**
10142
+ * Create a new custom field definition
10143
+ */
10144
+ async createDefinition(data) {
10145
+ return this.apiClient.post(this.basePath, data);
10146
+ }
10147
+ /**
10148
+ * Update an existing custom field definition
10149
+ */
10150
+ async updateDefinition(id, data) {
10151
+ return this.apiClient.put(`${this.basePath}/${id}`, data);
10152
+ }
10153
+ /**
10154
+ * Delete a custom field definition
10155
+ */
10156
+ async deleteDefinition(id) {
10157
+ return this.apiClient.delete(`${this.basePath}/${id}`);
10158
+ }
10159
+ /**
10160
+ * Get usage count for a field definition
10161
+ */
10162
+ async getUsages(id) {
10163
+ return this.apiClient.get(`${this.basePath}/${id}/usages`);
10164
+ }
10165
+ /**
10166
+ * Resolve dynamic select options for a field
10167
+ */
10168
+ async resolveSelectOptions(id) {
10169
+ return this.apiClient.get(`${this.basePath}/${id}/options`);
10170
+ }
10171
+ }
10172
+
10173
+ /**
10174
+ * Custom Field Definition Manager - Manage tenant-specific custom fields
10175
+ *
10176
+ * Provides CRUD operations for custom field definitions that extend the built-in
10177
+ * user profile fields. Custom fields are defined per-tenant and can be used for
10178
+ * additional user data collection, redemption requirements, and form validation.
10179
+ *
10180
+ * @group Managers
10181
+ * @category Custom Fields
10182
+ *
10183
+ * @example Basic Operations
10184
+ * ```typescript
10185
+ * // List all user custom fields
10186
+ * const fields = await sdk.customFields.getDefinitions();
10187
+ *
10188
+ * // Create a new custom field
10189
+ * const field = await sdk.customFields.createDefinition({
10190
+ * key: 'employee_id',
10191
+ * label: 'Employee ID',
10192
+ * fieldType: 'text',
10193
+ * validation: { required: true, pattern: '^E[0-9]{5}$' }
10194
+ * });
10195
+ *
10196
+ * // Update a field
10197
+ * await sdk.customFields.updateDefinition(field.id, {
10198
+ * label: 'Company Employee ID'
10199
+ * });
10200
+ *
10201
+ * // Delete a field
10202
+ * await sdk.customFields.deleteDefinition(field.id);
10203
+ * ```
10204
+ *
10205
+ * @example Validation
10206
+ * ```typescript
10207
+ * // Validate user custom data against definitions
10208
+ * const definitions = await sdk.customFields.getDefinitions();
10209
+ * const errors = sdk.customFields.validateUserData(
10210
+ * { employee_id: 'INVALID' },
10211
+ * definitions
10212
+ * );
10213
+ * if (errors.length > 0) {
10214
+ * console.log('Validation errors:', errors);
10215
+ * }
10216
+ * ```
10217
+ */
10218
+ class CustomFieldDefinitionManager {
10219
+ constructor(apiClient, events) {
10220
+ this.events = events;
10221
+ this.api = new CustomFieldApi(apiClient);
10222
+ }
10223
+ /**
10224
+ * List all custom field definitions for the tenant
10225
+ *
10226
+ * Retrieves all custom field definitions, optionally filtered by entity type.
10227
+ * Results are sorted by sortOrder (ascending).
10228
+ *
10229
+ * @param options - Query options including entity type filter
10230
+ * @returns Array of custom field definitions
10231
+ *
10232
+ * @example List All User Fields
10233
+ * ```typescript
10234
+ * const fields = await sdk.customFields.getDefinitions();
10235
+ * console.log(`Found ${fields.length} custom fields`);
10236
+ *
10237
+ * fields.forEach(field => {
10238
+ * console.log(`${field.key}: ${field.label} (${field.fieldType})`);
10239
+ * });
10240
+ * ```
10241
+ *
10242
+ * @example Filter by Entity Type
10243
+ * ```typescript
10244
+ * // Get only business custom fields
10245
+ * const businessFields = await sdk.customFields.getDefinitions({
10246
+ * entityType: 'business'
10247
+ * });
10248
+ * ```
10249
+ */
10250
+ async getDefinitions(options) {
10251
+ return this.api.getDefinitions(options?.entityType);
10252
+ }
10253
+ /**
10254
+ * Get a single custom field definition by ID
10255
+ *
10256
+ * @param id - The UUID of the custom field definition
10257
+ * @returns The custom field definition
10258
+ * @throws {PersApiError} When definition not found (404)
10259
+ *
10260
+ * @example
10261
+ * ```typescript
10262
+ * try {
10263
+ * const field = await sdk.customFields.getDefinition('uuid-here');
10264
+ * console.log('Field:', field.label);
10265
+ * } catch (error) {
10266
+ * if (error.statusCode === 404) {
10267
+ * console.log('Field not found');
10268
+ * }
10269
+ * }
10270
+ * ```
10271
+ */
10272
+ async getDefinition(id) {
10273
+ return this.api.getDefinition(id);
10274
+ }
10275
+ /**
10276
+ * Create a new custom field definition
10277
+ *
10278
+ * Creates a new custom field for the tenant. The field key must be unique
10279
+ * within the tenant and entity type combination.
10280
+ *
10281
+ * @param data - The field definition data
10282
+ * @returns The created custom field definition
10283
+ * @throws {PersApiError} When key already exists (409) or validation fails (400)
10284
+ *
10285
+ * @example Text Field with Pattern
10286
+ * ```typescript
10287
+ * const employeeIdField = await sdk.customFields.createDefinition({
10288
+ * key: 'employee_id',
10289
+ * label: 'Employee ID',
10290
+ * description: 'Your company employee ID (E + 5 digits)',
10291
+ * fieldType: 'text',
10292
+ * validation: {
10293
+ * required: true,
10294
+ * pattern: '^E[0-9]{5}$',
10295
+ * patternMessage: 'Must be E followed by 5 digits'
10296
+ * },
10297
+ * sortOrder: 1
10298
+ * });
10299
+ * ```
10300
+ *
10301
+ * @example Date Field with Comparison
10302
+ * ```typescript
10303
+ * const checkOutField = await sdk.customFields.createDefinition({
10304
+ * key: 'check_out',
10305
+ * label: 'Check-out Date',
10306
+ * fieldType: 'date',
10307
+ * validation: {
10308
+ * required: true,
10309
+ * comparisons: [
10310
+ * { field: 'check_in', operator: '>', message: 'Must be after check-in' }
10311
+ * ]
10312
+ * },
10313
+ * sortOrder: 2
10314
+ * });
10315
+ * ```
10316
+ *
10317
+ * @example Select Field with Static Options
10318
+ * ```typescript
10319
+ * const departmentField = await sdk.customFields.createDefinition({
10320
+ * key: 'department',
10321
+ * label: 'Department',
10322
+ * fieldType: 'select',
10323
+ * selectOptions: [
10324
+ * { value: 'engineering', label: 'Engineering' },
10325
+ * { value: 'sales', label: 'Sales' },
10326
+ * { value: 'hr', label: 'Human Resources' }
10327
+ * ],
10328
+ * validation: { required: true }
10329
+ * });
10330
+ * ```
10331
+ *
10332
+ * @example Select Field with Dynamic Options
10333
+ * ```typescript
10334
+ * const hotelField = await sdk.customFields.createDefinition({
10335
+ * key: 'preferred_hotel',
10336
+ * label: 'Preferred Hotel',
10337
+ * fieldType: 'select',
10338
+ * selectOptionsSource: {
10339
+ * entity: 'business',
10340
+ * valueField: 'id',
10341
+ * labelField: 'name',
10342
+ * filter: { tags: ['hotel'], isActive: true }
10343
+ * },
10344
+ * validation: { required: true }
10345
+ * });
10346
+ * ```
10347
+ */
10348
+ async createDefinition(data) {
10349
+ const result = await this.api.createDefinition(data);
10350
+ // Using 'user' domain until pers-shared adds 'customField' domain
10351
+ this.events?.emitSuccess({
10352
+ domain: 'user',
10353
+ type: 'definition_created',
10354
+ userMessage: `Custom field "${result.label}" created`,
10355
+ details: { id: result.id, key: result.key }
10356
+ });
10357
+ return result;
10358
+ }
10359
+ /**
10360
+ * Update an existing custom field definition
10361
+ *
10362
+ * Updates a custom field definition. Note that key and entityType cannot
10363
+ * be changed after creation.
10364
+ *
10365
+ * @param id - The UUID of the custom field definition to update
10366
+ * @param data - The fields to update (partial update supported)
10367
+ * @returns The updated custom field definition
10368
+ * @throws {PersApiError} When definition not found (404) or validation fails (400)
10369
+ *
10370
+ * @example Update Label and Validation
10371
+ * ```typescript
10372
+ * const updated = await sdk.customFields.updateDefinition('uuid-here', {
10373
+ * label: 'Employee ID (Required)',
10374
+ * validation: {
10375
+ * required: true,
10376
+ * minLength: 6,
10377
+ * maxLength: 6
10378
+ * }
10379
+ * });
10380
+ * ```
10381
+ *
10382
+ * @example Update Sort Order
10383
+ * ```typescript
10384
+ * await sdk.customFields.updateDefinition('uuid-here', {
10385
+ * sortOrder: 5
10386
+ * });
10387
+ * ```
10388
+ */
10389
+ async updateDefinition(id, data) {
10390
+ const result = await this.api.updateDefinition(id, data);
10391
+ // Using 'user' domain until pers-shared adds 'customField' domain
10392
+ this.events?.emitSuccess({
10393
+ domain: 'user',
10394
+ type: 'definition_updated',
10395
+ userMessage: `Custom field "${result.label}" updated`,
10396
+ details: { id: result.id, key: result.key }
10397
+ });
10398
+ return result;
10399
+ }
10400
+ /**
10401
+ * Delete a custom field definition (soft delete)
10402
+ *
10403
+ * Soft deletes a custom field definition. Existing user data in customData
10404
+ * is preserved, but the field will no longer appear in forms or validation.
10405
+ *
10406
+ * ⚠️ Consider the impact on existing user data before deleting.
10407
+ *
10408
+ * @param id - The UUID of the custom field definition to delete
10409
+ * @throws {PersApiError} When definition not found (404)
10410
+ *
10411
+ * @example
10412
+ * ```typescript
10413
+ * try {
10414
+ * await sdk.customFields.deleteDefinition('uuid-here');
10415
+ * console.log('Field deleted');
10416
+ * } catch (error) {
10417
+ * console.log('Failed to delete:', error.message);
10418
+ * }
10419
+ * ```
10420
+ */
10421
+ async deleteDefinition(id) {
10422
+ await this.api.deleteDefinition(id);
10423
+ // Using 'user' domain until pers-shared adds 'customField' domain
10424
+ this.events?.emitSuccess({
10425
+ domain: 'user',
10426
+ type: 'definition_deleted',
10427
+ userMessage: 'Custom field deleted',
10428
+ details: { id }
10429
+ });
10430
+ }
10431
+ /**
10432
+ * Resolve dynamic select options for a field
10433
+ *
10434
+ * For fields with selectOptionsSource (dynamic options from entities),
10435
+ * this resolves the actual options by querying the source entity.
10436
+ *
10437
+ * @param id - The UUID of the custom field definition
10438
+ * @returns Array of select options
10439
+ *
10440
+ * @example
10441
+ * ```typescript
10442
+ * const field = await sdk.customFields.getDefinition('hotel-field-id');
10443
+ *
10444
+ * if (field.selectOptionsSource) {
10445
+ * // Options come from entity - need to resolve
10446
+ * const options = await sdk.customFields.resolveSelectOptions(field.id);
10447
+ * console.log('Available hotels:', options);
10448
+ * } else {
10449
+ * // Static options
10450
+ * console.log('Options:', field.selectOptions);
10451
+ * }
10452
+ * ```
10453
+ */
10454
+ async resolveSelectOptions(id) {
10455
+ const response = await this.api.resolveSelectOptions(id);
10456
+ return response.options;
10457
+ }
10458
+ /**
10459
+ * Validate user custom data against field definitions
10460
+ *
10461
+ * Client-side validation using the same rules as the backend. Use this
10462
+ * to validate form data before submission.
10463
+ *
10464
+ * @param data - User's custom data (key-value pairs)
10465
+ * @param definitions - Custom field definitions to validate against
10466
+ * @returns Array of validation errors (empty if valid)
10467
+ *
10468
+ * @example Form Validation
10469
+ * ```typescript
10470
+ * const definitions = await sdk.customFields.getDefinitions();
10471
+ * const formData = {
10472
+ * employee_id: 'E123', // Missing a digit
10473
+ * department: 'engineering'
10474
+ * };
10475
+ *
10476
+ * const errors = sdk.customFields.validateUserData(formData, definitions);
10477
+ * if (errors.length > 0) {
10478
+ * errors.forEach(err => {
10479
+ * console.log(`${err.field}: ${err.message}`);
10480
+ * });
10481
+ * return; // Don't submit
10482
+ * }
10483
+ *
10484
+ * // No errors, safe to submit
10485
+ * await sdk.users.updateCurrentUser({ customData: formData });
10486
+ * ```
10487
+ */
10488
+ validateUserData(data, definitions) {
10489
+ // Convert CustomFieldDefinitionDTO to FieldDefinition for validation
10490
+ const fieldDefinitions = definitions.map(def => ({
10491
+ key: def.key,
10492
+ fieldType: def.fieldType,
10493
+ label: def.label,
10494
+ validation: def.validation ?? undefined,
10495
+ }));
10496
+ return validateAllFields(data, fieldDefinitions);
10497
+ }
10498
+ /**
10499
+ * Validate a single field value
10500
+ *
10501
+ * Validates a single value against a field's rules. Useful for
10502
+ * real-time validation as the user types.
10503
+ *
10504
+ * @param value - The value to validate
10505
+ * @param definition - The field definition
10506
+ * @returns Validation error or null if valid
10507
+ *
10508
+ * @example Real-time Validation
10509
+ * ```typescript
10510
+ * const employeeIdField = definitions.find(d => d.key === 'employee_id');
10511
+ *
10512
+ * const handleBlur = (value: string) => {
10513
+ * const error = sdk.customFields.validateFieldValue(value, employeeIdField);
10514
+ * if (error) {
10515
+ * setFieldError('employee_id', error.message);
10516
+ * } else {
10517
+ * clearFieldError('employee_id');
10518
+ * }
10519
+ * };
10520
+ * ```
10521
+ */
10522
+ validateFieldValue(value, definition) {
10523
+ const error = validateFieldValue(value, definition.validation ?? null, definition.fieldType);
10524
+ if (error) {
10525
+ // Add field key to error
10526
+ return { ...error, field: definition.key };
10527
+ }
10528
+ return null;
10529
+ }
10530
+ }
10531
+
10109
10532
  /**
10110
10533
  * @fileoverview PERS SDK - Platform-agnostic TypeScript SDK with High-Level Managers
10111
10534
  *
@@ -10794,6 +11217,37 @@ class PersSDK {
10794
11217
  }
10795
11218
  return this._webhooks;
10796
11219
  }
11220
+ /**
11221
+ * Custom Field Definition Manager - Manage tenant-specific custom fields
11222
+ *
11223
+ * Provides CRUD operations for custom field definitions that extend the built-in
11224
+ * user profile fields. Custom fields are tenant-specific and support validation.
11225
+ *
11226
+ * @returns CustomFieldDefinitionManager instance
11227
+ *
11228
+ * @example Basic Operations
11229
+ * ```typescript
11230
+ * // List all custom fields
11231
+ * const fields = await sdk.customFields.getDefinitions();
11232
+ *
11233
+ * // Create a new field
11234
+ * const field = await sdk.customFields.createDefinition({
11235
+ * key: 'employee_id',
11236
+ * label: 'Employee ID',
11237
+ * fieldType: 'text',
11238
+ * validation: { required: true }
11239
+ * });
11240
+ *
11241
+ * // Validate user data
11242
+ * const errors = sdk.customFields.validateUserData(formData, fields.data);
11243
+ * ```
11244
+ */
11245
+ get customFields() {
11246
+ if (!this._customFields) {
11247
+ this._customFields = new CustomFieldDefinitionManager(this.apiClient, this._events);
11248
+ }
11249
+ return this._customFields;
11250
+ }
10797
11251
  /**
10798
11252
  * Wallet Events Manager - Real-time blockchain events for user's wallets
10799
11253
  *
@@ -10900,5 +11354,5 @@ function createPersSDK(httpClient, config) {
10900
11354
  return new PersSDK(httpClient, config);
10901
11355
  }
10902
11356
 
10903
- export { AuthStatus as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, WebhookManager as E, FATAL_AUTH_CODES as F, WalletEventsManager as G, FileApi as H, IndexedDBTokenStorage as I, FileService as J, ApiKeyApi as K, LocalStorageTokenStorage as L, MemoryTokenStorage as M, WebhookApi as N, WebhookService as O, PersSDK as P, PersEventsClient as Q, RedemptionManager as R, SDK_NAME as S, TokenManager as T, UserManager as U, createPersEventsClient as V, WebDPoPCryptoProvider as W, AuthTokenManager as a, AUTH_STORAGE_KEYS as b, createPersSDK as c, DPOP_STORAGE_KEYS as d, SDK_VERSION as e, SDK_USER_AGENT as f, PersApiClient as g, DEFAULT_PERS_CONFIG as h, buildApiRoot as i, buildWalletEventsWsUrl as j, StaticJwtAuthProvider as k, AuthApi as l, mergeWithDefaults as m, isFatalAuthErrorInMessage as n, AuthService as o, DPoPManager as p, PersEventEmitter as q, AuthManager as r, UserStatusManager as s, TransactionManager as t, PurchaseManager as u, FileManager as v, ApiKeyManager as w, AnalyticsManager as x, DonationManager as y, TriggerSourceManager as z };
10904
- //# sourceMappingURL=pers-sdk-DuDWwRWC.js.map
11357
+ export { AuthTokenManager as A, BusinessManager as B, CampaignManager as C, DefaultAuthProvider as D, WalletEventsManager as E, FATAL_AUTH_CODES as F, CustomFieldDefinitionManager as G, AuthStatus as H, IndexedDBTokenStorage as I, FileApi as J, FileService as K, LocalStorageTokenStorage as L, MemoryTokenStorage as M, ApiKeyApi as N, WebhookApi as O, PersSDK as P, WebhookService as Q, RedemptionManager as R, SDK_NAME as S, TokenManager as T, UserManager as U, PersEventsClient as V, WebDPoPCryptoProvider as W, createPersEventsClient as X, AUTH_STORAGE_KEYS as a, DPOP_STORAGE_KEYS as b, SDK_VERSION as c, SDK_USER_AGENT as d, createPersSDK as e, PersApiClient as f, DEFAULT_PERS_CONFIG as g, buildApiRoot as h, buildWalletEventsWsUrl as i, StaticJwtAuthProvider as j, AuthApi as k, isFatalAuthErrorInMessage as l, mergeWithDefaults as m, AuthService as n, DPoPManager as o, PersEventEmitter as p, AuthManager as q, UserStatusManager as r, TransactionManager as s, PurchaseManager as t, FileManager as u, ApiKeyManager as v, AnalyticsManager as w, DonationManager as x, TriggerSourceManager as y, WebhookManager as z };
11358
+ //# sourceMappingURL=pers-sdk-CBRtrG03.js.map