@praxium/sdk 0.3.31 → 0.3.42

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/dist/index.d.ts CHANGED
@@ -180,20 +180,37 @@ type SocialLinks = {
180
180
  */
181
181
  type TeamMembers = Array<PublicTeamMember>;
182
182
  /**
183
- * Custom field exposed on the public team API
183
+ * Custom field with server-resolved label (specific locale requested).
184
+ * When locale is 'nl' or 'en', the server resolves labels and values
185
+ * to that locale — label is a plain string, values are resolved strings.
184
186
  */
185
187
  type CustomField = {
186
188
  /** Field identifier (snake_case) */
187
189
  identifier: string;
188
190
  /** Custom field type (e.g., STRING, LONG_TEXT, SEARCHABLE_LIST) */
189
191
  type: string;
190
- /** Localized field label */
191
- label: LocalizedText;
192
+ /** Server-resolved field label for the requested locale */
193
+ label: string;
192
194
  /** Resolved field value (type depends on field.type) */
193
195
  value: unknown;
194
196
  };
195
197
  /**
196
- * Public team member profile
198
+ * Custom field with multilingual label (locale='*' requested).
199
+ * When locale is '*', the server returns all translations — label
200
+ * is a MultilingualText object, values are multilingual objects.
201
+ */
202
+ type MultilingualCustomField = {
203
+ /** Field identifier (snake_case) */
204
+ identifier: string;
205
+ /** Custom field type (e.g., STRING, LONG_TEXT, SEARCHABLE_LIST) */
206
+ type: string;
207
+ /** Multilingual field label (all available locales) */
208
+ label: MultilingualText;
209
+ /** Multilingual field value (type depends on field.type) */
210
+ value: unknown;
211
+ };
212
+ /**
213
+ * Public team member profile with server-resolved custom fields
197
214
  */
198
215
  type PublicTeamMember = {
199
216
  /**
@@ -209,10 +226,33 @@ type PublicTeamMember = {
209
226
  */
210
227
  publicImage: string;
211
228
  /**
212
- * Custom fields assigned to the public-team API access profile
229
+ * Custom fields with server-resolved labels and values
213
230
  */
214
231
  customFields: Array<CustomField>;
215
232
  };
233
+ /**
234
+ * Public team member profile with multilingual custom fields (locale='*')
235
+ */
236
+ type MultilingualTeamMember = {
237
+ /**
238
+ * Staff member UUID
239
+ */
240
+ id: string;
241
+ /**
242
+ * Public display name
243
+ */
244
+ publicName: string;
245
+ /**
246
+ * Public profile image URL (Supabase CDN)
247
+ */
248
+ publicImage: string;
249
+ /**
250
+ * Custom fields with multilingual labels and values
251
+ */
252
+ customFields: Array<MultilingualCustomField>;
253
+ };
254
+ /** Text in multiple languages. Keys are locale codes (e.g., 'nl', 'en'). */
255
+ type MultilingualText = Record<string, string>;
216
256
  /**
217
257
  * Bilingual text with Dutch (nl) and English (en) translations
218
258
  */
@@ -226,8 +266,6 @@ type BilingualText = {
226
266
  */
227
267
  en: string;
228
268
  };
229
- /** Text with locale-specific values. Keys are locale codes (e.g., 'nl', 'en'). */
230
- type LocalizedText = Record<string, string>;
231
269
  /**
232
270
  * FAQs grouped by category, ordered by category.order then faq.order
233
271
  */
@@ -611,6 +649,17 @@ type SubmitContactFormData = {
611
649
  url: '/api/public/{tenantSlug}/contact';
612
650
  };
613
651
 
652
+ /**
653
+ * Supported locale codes for server-side content resolution.
654
+ * Adding a new language requires an SDK release.
655
+ */
656
+ type SupportedLocale = 'nl' | 'en';
657
+ /**
658
+ * Locale parameter for client creation.
659
+ * - Specific locale (`'nl'`, `'en'`) — server resolves labels/values
660
+ * - `'*'` — server returns all translations (multilingual mode)
661
+ */
662
+ type ClientLocale = SupportedLocale | '*';
614
663
  interface TenantClientConfig {
615
664
  /** Platform base URL (e.g., 'https://platform.praxium.nl') */
616
665
  baseUrl: string;
@@ -618,18 +667,16 @@ interface TenantClientConfig {
618
667
  apiKey: string;
619
668
  /** Tenant identifier slug (must match the slug in the API key) */
620
669
  tenantSlug: string;
621
- /** Accept-Language header for locale-aware responses (e.g., 'nl', 'en') */
622
- locale: string;
670
+ /** Locale for server-side content resolution */
671
+ locale: ClientLocale;
623
672
  }
624
- declare function createTenantClient(config: TenantClientConfig): {
625
- /** Resolve a LocalizedText to a string using the client's configured locale. */
626
- localize: (text: LocalizedText | null | undefined) => string;
673
+ /** Shared methods available on both client types */
674
+ interface TenantClientBase {
627
675
  getOpeningHours: () => Promise<OpeningHours>;
628
676
  getContactDetails: () => Promise<ContactDetails>;
629
677
  getLocation: () => Promise<Location>;
630
678
  getBusinessName: () => Promise<BusinessName>;
631
679
  getSocialLinks: () => Promise<SocialLinks>;
632
- getTeamMembers: () => Promise<TeamMembers>;
633
680
  getFaq: () => Promise<FaqContent>;
634
681
  getServiceVariants: () => Promise<PricingVariants>;
635
682
  getInsuranceInfo: () => Promise<InsuranceList>;
@@ -637,10 +684,22 @@ declare function createTenantClient(config: TenantClientConfig): {
637
684
  getPaymentMethods: () => Promise<PaymentMethodList>;
638
685
  getPolicyInfo: () => Promise<PolicyList>;
639
686
  getBookableServices: () => Promise<BookableServices>;
640
- submitContactForm: (body: SubmitContactFormData["body"]) => Promise<ContactFormResult>;
641
- };
642
- /** Return type of createTenantClient for type inference */
643
- type TenantClient = ReturnType<typeof createTenantClient>;
687
+ submitContactForm: (body: SubmitContactFormData['body']) => Promise<ContactFormResult>;
688
+ }
689
+ /** Client for locale-specific responses (locale='nl', 'en', etc.) */
690
+ interface TenantClient extends TenantClientBase {
691
+ getTeamMembers: () => Promise<TeamMembers>;
692
+ }
693
+ /** Client for multilingual responses (locale='*') */
694
+ interface MultilingualTenantClient extends TenantClientBase {
695
+ getTeamMembers: () => Promise<MultilingualTeamMember[]>;
696
+ }
697
+ /** Multilingual mode: returns MultilingualTeamMember[] (use localizeText() helper for resolution) */
698
+ declare function createTenantClient(config: TenantClientConfig & {
699
+ locale: '*';
700
+ }): MultilingualTenantClient;
701
+ /** Locale-specific mode: returns PublicTeamMember[] with resolved labels/values */
702
+ declare function createTenantClient(config: TenantClientConfig): TenantClient;
644
703
 
645
704
  /**
646
705
  * Typed error hierarchy for the Praxium SDK.
@@ -707,39 +766,69 @@ declare class PraxiumRateLimitError extends PraxiumError {
707
766
  /**
708
767
  * Get a custom field value by identifier from a team member's custom fields.
709
768
  *
769
+ * Works with both resolved (locale-specific) and multilingual (locale='*') members.
770
+ *
710
771
  * **Type safety warning:** The generic `T` is a cast (`as T`) — the caller is
711
772
  * responsible for ensuring `T` matches the actual runtime value shape for the
712
773
  * given field type. No runtime validation is performed.
713
774
  *
714
- * Runtime value shapes by custom field type:
775
+ * Runtime value shapes by custom field type (locale-specific):
715
776
  * - `STRING` → `string`
716
777
  * - `LONG_TEXT` → `string`
717
778
  * - `NUMBER` → `number`
718
779
  * - `BOOLEAN` → `boolean`
719
- * - `SINGLE_SELECT` → `BilingualText` (`{ nl: string; en: string }`)
720
- * - `MULTI_SELECT` → `BilingualText[]`
721
- * - `SEARCHABLE_LIST` → `BilingualText[]`
780
+ * - `SINGLE_SELECT` → `string`
781
+ * - `MULTI_SELECT` → `string[]`
782
+ * - `SEARCHABLE_LIST` → `string[]`
722
783
  * - `DATE` → `string` (ISO 8601 date)
723
784
  *
785
+ * Runtime value shapes by custom field type (locale='*'):
786
+ * - `SINGLE_SELECT` → `MultilingualText`
787
+ * - `MULTI_SELECT` → `MultilingualText[]`
788
+ * - `SEARCHABLE_LIST` → `MultilingualText[]`
789
+ * - Others: same as locale-specific
790
+ *
724
791
  * @example
725
792
  * ```ts
726
- * // Caller must match T to the field's actual type:
727
- * const specs = getCustomFieldValue<BilingualText[]>(member, 'specializations')
793
+ * // Locale-specific client (values are resolved strings):
794
+ * const specs = getCustomFieldValue<string[]>(member, 'specializations')
728
795
  * const bigNr = getCustomFieldValue<string>(member, 'big_number')
796
+ *
797
+ * // Multilingual client (locale='*'):
798
+ * const specs = getCustomFieldValue<MultilingualText[]>(member, 'specializations')
729
799
  * ```
730
800
  *
731
- * @param member - Public team member
801
+ * @param member - Public team member (resolved or multilingual)
732
802
  * @param identifier - Field identifier to look up
733
803
  * @returns The field value cast to `T`, or `null` if no field with that identifier exists
734
804
  */
735
- declare function getCustomFieldValue<T = unknown>(member: PublicTeamMember, identifier: string): T | null;
805
+ declare function getCustomFieldValue<T = unknown>(member: PublicTeamMember | MultilingualTeamMember, identifier: string): T | null;
736
806
  /**
737
807
  * Get a custom field by identifier.
738
808
  *
739
- * @param member - Public team member
809
+ * @param member - Public team member (resolved or multilingual)
740
810
  * @param identifier - Field identifier to look up
741
811
  * @returns The full custom field, or undefined if not found
742
812
  */
743
813
  declare function getCustomField(member: PublicTeamMember, identifier: string): CustomField | undefined;
814
+ declare function getCustomField(member: MultilingualTeamMember, identifier: string): MultilingualCustomField | undefined;
815
+ /**
816
+ * Resolve a MultilingualText object to a single string for the given locale.
817
+ *
818
+ * Fallback chain: requested locale → 'en' (fallback) → first available value → ''
819
+ *
820
+ * @param text - Multilingual text object with locale keys
821
+ * @param locale - Desired locale code (e.g., 'nl', 'en', 'de')
822
+ * @returns The resolved text string, or empty string if no value available
823
+ *
824
+ * @example
825
+ * ```typescript
826
+ * const label = { nl: 'Specialisaties', en: 'Specializations' }
827
+ * localizeText(label, 'nl') // 'Specialisaties'
828
+ * localizeText(label, 'de') // 'Specializations' (falls back to 'en')
829
+ * localizeText({}, 'nl') // ''
830
+ * ```
831
+ */
832
+ declare function localizeText(text: MultilingualText | null | undefined, locale: SupportedLocale): string;
744
833
 
745
- export { type ApiError, type BilingualText, type BookableService, type BookableServices, type BookableVariantInfo, type BusinessName, type ContactDetails, type ContactFormResult, type CustomField, type FaqCategory, type FaqContent, type FaqGroup, type FaqItem, type FeatureItem, type FeatureList, type InsuranceInfo, type InsuranceList, type LocalizedText, type Location, type OpeningHours, type PaymentMethod, type PaymentMethodList, type PolicyInfo, type PolicyList, PraxiumAuthError, PraxiumError, PraxiumForbiddenError, PraxiumNotFoundError, PraxiumRateLimitError, PraxiumValidationError, type PricingVariant, type PricingVariants, type PublicDaySchedule, type PublicTeamMember, type ServiceCategoryInfo, type SocialLinks, type TeamMembers, type TenantClient, type TenantClientConfig, type ValidationDetail, createTenantClient, getCustomField, getCustomFieldValue };
834
+ export { type ApiError, type BilingualText, type BookableService, type BookableServices, type BookableVariantInfo, type BusinessName, type ClientLocale, type ContactDetails, type ContactFormResult, type CustomField, type FaqCategory, type FaqContent, type FaqGroup, type FaqItem, type FeatureItem, type FeatureList, type InsuranceInfo, type InsuranceList, type Location, type MultilingualCustomField, type MultilingualTeamMember, type MultilingualTenantClient, type MultilingualText, type OpeningHours, type PaymentMethod, type PaymentMethodList, type PolicyInfo, type PolicyList, PraxiumAuthError, PraxiumError, PraxiumForbiddenError, PraxiumNotFoundError, PraxiumRateLimitError, PraxiumValidationError, type PricingVariant, type PricingVariants, type PublicDaySchedule, type PublicTeamMember, type ServiceCategoryInfo, type SocialLinks, type SupportedLocale, type TeamMembers, type TenantClient, type TenantClientConfig, type ValidationDetail, createTenantClient, getCustomField, getCustomFieldValue, localizeText };
package/dist/index.js CHANGED
@@ -928,19 +928,6 @@ var STATUS_ERROR_MAP = {
928
928
  429: PraxiumRateLimitError
929
929
  };
930
930
 
931
- // src/helpers.ts
932
- function getCustomFieldValue(member, identifier) {
933
- const field = member.customFields.find((f) => f.identifier === identifier);
934
- return field ? field.value : null;
935
- }
936
- function getCustomField(member, identifier) {
937
- return member.customFields.find((f) => f.identifier === identifier);
938
- }
939
- function getLocalizedText(text, locale) {
940
- if (!text) return "";
941
- return text[locale] || text["en"] || Object.values(text)[0] || "";
942
- }
943
-
944
931
  // src/tenant-client.ts
945
932
  function unwrapOrThrow(result) {
946
933
  if (result.data !== void 0 && result.error === void 0) {
@@ -969,10 +956,7 @@ function createTenantClient(config) {
969
956
  return request;
970
957
  });
971
958
  const path = { tenantSlug: config.tenantSlug };
972
- return {
973
- // ─── Locale Helper ───
974
- /** Resolve a LocalizedText to a string using the client's configured locale. */
975
- localize: (text) => getLocalizedText(text, config.locale),
959
+ const baseMethods = {
976
960
  // ─── Layout Endpoints ───
977
961
  getOpeningHours: () => getOpeningHours({ client: clientInstance, path }).then(unwrapOrThrow),
978
962
  getContactDetails: () => getContactDetails({ client: clientInstance, path }).then(unwrapOrThrow),
@@ -980,7 +964,6 @@ function createTenantClient(config) {
980
964
  getBusinessName: () => getBusinessName({ client: clientInstance, path }).then(unwrapOrThrow),
981
965
  getSocialLinks: () => getSocialLinks({ client: clientInstance, path }).then(unwrapOrThrow),
982
966
  // ─── Content Endpoints ───
983
- getTeamMembers: () => getTeamMembers({ client: clientInstance, path }).then(unwrapOrThrow),
984
967
  getFaq: () => getFaq({ client: clientInstance, path }).then(unwrapOrThrow),
985
968
  getServiceVariants: () => getServiceVariants({ client: clientInstance, path }).then(unwrapOrThrow),
986
969
  getInsuranceInfo: () => getInsuranceInfo({ client: clientInstance, path }).then(unwrapOrThrow),
@@ -991,6 +974,29 @@ function createTenantClient(config) {
991
974
  // ─── Contact Form ───
992
975
  submitContactForm: (body) => submitContactForm({ client: clientInstance, path, body }).then(unwrapOrThrow)
993
976
  };
977
+ if (config.locale === "*") {
978
+ return {
979
+ ...baseMethods,
980
+ getTeamMembers: () => getTeamMembers({ client: clientInstance, path }).then(unwrapOrThrow)
981
+ };
982
+ }
983
+ return {
984
+ ...baseMethods,
985
+ getTeamMembers: () => getTeamMembers({ client: clientInstance, path }).then(unwrapOrThrow)
986
+ };
987
+ }
988
+
989
+ // src/helpers.ts
990
+ function getCustomFieldValue(member, identifier) {
991
+ const field = member.customFields.find((f) => f.identifier === identifier);
992
+ return field ? field.value : null;
993
+ }
994
+ function getCustomField(member, identifier) {
995
+ return member.customFields.find((f) => f.identifier === identifier);
996
+ }
997
+ function localizeText(text, locale) {
998
+ if (!text) return "";
999
+ return text[locale] || text["en"] || Object.values(text)[0] || "";
994
1000
  }
995
1001
  export {
996
1002
  PraxiumAuthError,
@@ -1001,5 +1007,6 @@ export {
1001
1007
  PraxiumValidationError,
1002
1008
  createTenantClient,
1003
1009
  getCustomField,
1004
- getCustomFieldValue
1010
+ getCustomFieldValue,
1011
+ localizeText
1005
1012
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxium/sdk",
3
- "version": "0.3.31",
3
+ "version": "0.3.42",
4
4
  "description": "Official TypeScript SDK for the Praxium platform API",
5
5
  "type": "module",
6
6
  "exports": {