@plyaz/core 1.8.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/domain/base/BaseDomainService.d.ts +9 -4
  2. package/dist/domain/base/BaseDomainService.d.ts.map +1 -1
  3. package/dist/domain/example/FrontendExampleDomainService.d.ts.map +1 -1
  4. package/dist/domain/featureFlags/FrontendFeatureFlagDomainService.d.ts.map +1 -1
  5. package/dist/entry-backend.js +313 -207
  6. package/dist/entry-backend.js.map +1 -1
  7. package/dist/entry-backend.mjs +250 -144
  8. package/dist/entry-backend.mjs.map +1 -1
  9. package/dist/entry-frontend-browser.js +238 -141
  10. package/dist/entry-frontend-browser.js.map +1 -1
  11. package/dist/entry-frontend-browser.mjs +240 -143
  12. package/dist/entry-frontend-browser.mjs.map +1 -1
  13. package/dist/entry-frontend.js +238 -141
  14. package/dist/entry-frontend.js.map +1 -1
  15. package/dist/entry-frontend.mjs +240 -143
  16. package/dist/entry-frontend.mjs.map +1 -1
  17. package/dist/frontend/providers/PlyazProvider.d.ts.map +1 -1
  18. package/dist/index.js +315 -207
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs +251 -144
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/init/CoreInitializer.d.ts +13 -2
  23. package/dist/init/CoreInitializer.d.ts.map +1 -1
  24. package/dist/init/nestjs/index.js +217 -136
  25. package/dist/init/nestjs/index.js.map +1 -1
  26. package/dist/init/nestjs/index.mjs +219 -138
  27. package/dist/init/nestjs/index.mjs.map +1 -1
  28. package/dist/services/ApiClientService.d.ts +43 -0
  29. package/dist/services/ApiClientService.d.ts.map +1 -1
  30. package/dist/services/CacheService.d.ts +5 -0
  31. package/dist/services/CacheService.d.ts.map +1 -1
  32. package/package.json +2 -2
@@ -246,6 +246,14 @@ var HEX_RADIX = 16;
246
246
  var HEX_SLICE_START = 2;
247
247
  var HEX_SLICE_END = 18;
248
248
  var SPAN_ID_LENGTH = 16;
249
+ function generateId() {
250
+ const cryptoApi = globalThis.crypto;
251
+ if (cryptoApi?.randomUUID) {
252
+ return cryptoApi.randomUUID();
253
+ }
254
+ return `${Date.now()}-${Math.random().toString(RANDOM_ID_RADIX).slice(RANDOM_ID_SLICE_START)}`;
255
+ }
256
+ __name(generateId, "generateId");
249
257
  function generateShortId() {
250
258
  const cryptoApi = globalThis.crypto;
251
259
  if (cryptoApi?.randomUUID) {
@@ -558,6 +566,80 @@ var ApiClientService = class _ApiClientService {
558
566
  static {
559
567
  this.initPromise = null;
560
568
  }
569
+ /**
570
+ * Build the core error handler for API clients.
571
+ * This handler emits errors to CoreEventManager for global error handling.
572
+ *
573
+ * Handles:
574
+ * - Single errors (network, timeout)
575
+ * - Array of errors from API responses (validation, business logic)
576
+ * - Serialization to unified SerializedError format
577
+ * - Event emission to CORE_EVENTS.SYSTEM.ERROR and CORE_EVENTS.API.REQUEST_ERROR
578
+ *
579
+ * @returns Error handler function compatible with ApiClientOptions.onError
580
+ */
581
+ static buildCoreErrorHandler() {
582
+ return async (error) => {
583
+ const requestId = errors.generateRequestId();
584
+ const method = error.config?.method ?? "UNKNOWN";
585
+ const url = error.config?.url ?? "unknown";
586
+ try {
587
+ const errorDetails = Array.isArray(error.response?.data) ? error.response.data : [];
588
+ if (errorDetails.length === 0) {
589
+ const serializedError = {
590
+ id: requestId,
591
+ code: types.ERROR_CODES.CORE_API_CLIENT_REQUEST_FAILED,
592
+ message: error.message ?? "API request failed",
593
+ status: error.status,
594
+ category: types.ERROR_CATEGORY.Network,
595
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
596
+ isRetryable: error.status ? error.status >= types.HTTP_STATUS.INTERNAL_SERVER_ERROR : false,
597
+ source: "api-client",
598
+ dismissed: false,
599
+ context: {
600
+ method,
601
+ url,
602
+ requestId
603
+ }
604
+ };
605
+ CoreEventManager.emit(types.CORE_EVENTS.SYSTEM.ERROR, { errors: [serializedError] });
606
+ } else {
607
+ const serializedErrors = errorDetails.map(
608
+ (detail, index) => ({
609
+ id: `${requestId}-${index}`,
610
+ code: detail.errorCode ?? types.ERROR_CODES.CORE_API_CLIENT_REQUEST_FAILED,
611
+ message: detail.message ?? error.message ?? "API request failed",
612
+ status: error.status,
613
+ category: types.ERROR_CATEGORY.Network,
614
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
615
+ isRetryable: error.status ? error.status >= types.HTTP_STATUS.INTERNAL_SERVER_ERROR : false,
616
+ source: "api-client",
617
+ dismissed: false,
618
+ context: {
619
+ method,
620
+ url,
621
+ requestId,
622
+ field: detail.field,
623
+ valueGiven: detail.valueGiven,
624
+ allowedValues: detail.allowedValues,
625
+ constraints: detail.constraints
626
+ }
627
+ })
628
+ );
629
+ CoreEventManager.emit(types.CORE_EVENTS.SYSTEM.ERROR, { errors: serializedErrors });
630
+ }
631
+ } catch (e) {
632
+ console.error("[ApiClientService] Failed to emit error event:", e);
633
+ }
634
+ _ApiClientService.emitApiError(error, {
635
+ method,
636
+ url,
637
+ requestId,
638
+ status: error.status,
639
+ duration: 0
640
+ });
641
+ };
642
+ }
561
643
  /**
562
644
  * Initialize the API client with environment config and API options
563
645
  *
@@ -595,71 +677,12 @@ var ApiClientService = class _ApiClientService {
595
677
  * 2. Environment metadata (envConfig - apiKey)
596
678
  * 3. API configuration (apiConfig - baseURL, encryption, timeout, etc.)
597
679
  */
598
- // eslint-disable-next-line max-lines-per-function, complexity
680
+ // eslint-disable-next-line complexity
599
681
  static async createClient(envConfig, apiConfig) {
600
682
  try {
601
683
  const envDefaults = getConfigForEnvironment(envConfig.env);
602
684
  const envMetadataMapped = mapEnvironmentMetadata(envConfig, envDefaults);
603
- const coreErrorHandler = /* @__PURE__ */ __name(async (error) => {
604
- const requestId = errors.generateRequestId();
605
- const method = error.config?.method ?? "UNKNOWN";
606
- const url = error.config?.url ?? "unknown";
607
- try {
608
- const errorDetails = Array.isArray(error.response?.data) ? error.response.data : [];
609
- if (errorDetails.length === 0) {
610
- const serializedError = {
611
- id: requestId,
612
- code: types.ERROR_CODES.CORE_API_CLIENT_REQUEST_FAILED,
613
- message: error.message ?? "API request failed",
614
- status: error.status,
615
- category: types.ERROR_CATEGORY.Network,
616
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
617
- isRetryable: error.status ? error.status >= types.HTTP_STATUS.INTERNAL_SERVER_ERROR : false,
618
- source: "api-client",
619
- dismissed: false,
620
- context: {
621
- method,
622
- url,
623
- requestId
624
- }
625
- };
626
- CoreEventManager.emit(types.CORE_EVENTS.SYSTEM.ERROR, { errors: [serializedError] });
627
- } else {
628
- const serializedErrors = errorDetails.map(
629
- (detail, index) => ({
630
- id: `${requestId}-${index}`,
631
- code: detail.errorCode ?? types.ERROR_CODES.CORE_API_CLIENT_REQUEST_FAILED,
632
- message: detail.message ?? error.message ?? "API request failed",
633
- status: error.status,
634
- category: types.ERROR_CATEGORY.Network,
635
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
636
- isRetryable: error.status ? error.status >= types.HTTP_STATUS.INTERNAL_SERVER_ERROR : false,
637
- source: "api-client",
638
- dismissed: false,
639
- context: {
640
- method,
641
- url,
642
- requestId,
643
- field: detail.field,
644
- valueGiven: detail.valueGiven,
645
- allowedValues: detail.allowedValues,
646
- constraints: detail.constraints
647
- }
648
- })
649
- );
650
- CoreEventManager.emit(types.CORE_EVENTS.SYSTEM.ERROR, { errors: serializedErrors });
651
- }
652
- } catch (e) {
653
- console.error("[ApiClientService] Failed to emit error event:", e);
654
- }
655
- _ApiClientService.emitApiError(error, {
656
- method,
657
- url,
658
- requestId,
659
- status: error.status,
660
- duration: 0
661
- });
662
- }, "coreErrorHandler");
685
+ const coreErrorHandler = _ApiClientService.buildCoreErrorHandler();
663
686
  const userOnError = apiConfig?.onError;
664
687
  const combinedOnError = userOnError ? Array.isArray(userOnError) ? [...userOnError, coreErrorHandler] : [userOnError, coreErrorHandler] : coreErrorHandler;
665
688
  const mergedOptions = frontend.mergeConfigs(
@@ -834,11 +857,13 @@ var ApiClientService = class _ApiClientService {
834
857
  try {
835
858
  const envDefaults = getConfigForEnvironment(envConfig.env);
836
859
  const envMetadataMapped = mapEnvironmentMetadata(envConfig, envDefaults);
837
- const mergedOptions = frontend.mergeConfigs(
838
- envDefaults,
839
- envMetadataMapped,
840
- apiConfig ?? {}
841
- );
860
+ const coreErrorHandler = _ApiClientService.buildCoreErrorHandler();
861
+ const userOnError = apiConfig?.onError;
862
+ const combinedOnError = userOnError ? Array.isArray(userOnError) ? [...userOnError, coreErrorHandler] : [userOnError, coreErrorHandler] : coreErrorHandler;
863
+ const mergedOptions = frontend.mergeConfigs(envDefaults, envMetadataMapped, {
864
+ ...apiConfig ?? {},
865
+ onError: combinedOnError
866
+ });
842
867
  validateEnvironmentConfig(envConfig, mergedOptions);
843
868
  const dedicatedClient = await frontend.createApiClient(mergedOptions);
844
869
  return dedicatedClient;
@@ -860,6 +885,61 @@ var ApiClientService = class _ApiClientService {
860
885
  );
861
886
  }
862
887
  }
888
+ /**
889
+ * Create a standalone API client with Core error handling.
890
+ *
891
+ * This is a simpler alternative to `createInstance()` that doesn't require
892
+ * environment config. Use this when you just need the error handling without
893
+ * environment-specific defaults (production validation, etc.).
894
+ *
895
+ * **Use cases:**
896
+ * - Domain services that need their own API client
897
+ * - Testing with isolated API clients
898
+ * - Simple client creation without environment setup
899
+ *
900
+ * @param apiConfig - API configuration (baseURL, timeout, etc.)
901
+ * @returns Promise that resolves to a client with Core error handling
902
+ *
903
+ * @example
904
+ * ```typescript
905
+ * // In BaseDomainService or any service
906
+ * const client = await ApiClientService.createStandaloneClient({
907
+ * baseURL: '/api/examples',
908
+ * timeout: 10000,
909
+ * });
910
+ *
911
+ * // Errors are automatically emitted to CoreEventManager
912
+ * const response = await client.get('/items');
913
+ * ```
914
+ */
915
+ static async createStandaloneClient(apiConfig) {
916
+ try {
917
+ const coreErrorHandler = _ApiClientService.buildCoreErrorHandler();
918
+ const userOnError = apiConfig.onError;
919
+ const combinedOnError = userOnError ? Array.isArray(userOnError) ? [...userOnError, coreErrorHandler] : [userOnError, coreErrorHandler] : coreErrorHandler;
920
+ const client = await frontend.createApiClient({
921
+ ...apiConfig,
922
+ onError: combinedOnError
923
+ });
924
+ return client;
925
+ } catch (error) {
926
+ throw new frontend.ApiPackageError(
927
+ "service.standalone_client_creation.failed",
928
+ types.PACKAGE_STATUS_CODES.INITIALIZATION_FAILED,
929
+ types.API_ERROR_CODES.CLIENT_INITIALIZATION_FAILED,
930
+ {
931
+ cause: error instanceof Error ? error : void 0,
932
+ context: {
933
+ operation: types.OPERATIONS.INITIALIZATION,
934
+ originalError: error instanceof Error ? error.message : String(error),
935
+ i18n: {
936
+ error: error instanceof Error ? error.message : String(error)
937
+ }
938
+ }
939
+ }
940
+ );
941
+ }
942
+ }
863
943
  };
864
944
  var BaseAdapter = class {
865
945
  constructor() {
@@ -3416,6 +3496,7 @@ var Core = class _Core {
3416
3496
  _Core._errorHandler.destroy();
3417
3497
  _Core._errorHandler = null;
3418
3498
  middleware.clearEventEmitter();
3499
+ errors.BaseError.clearEventEmitter();
3419
3500
  }
3420
3501
  _Core._errorConfig = {};
3421
3502
  _Core._httpErrorHandler = null;
@@ -3604,6 +3685,28 @@ var Core = class _Core {
3604
3685
  };
3605
3686
  }
3606
3687
  }
3688
+ /**
3689
+ * Serialize a PackageErrorLike to SerializedError format.
3690
+ * Used by BaseError.setEventEmitter() to convert errors for the store.
3691
+ */
3692
+ static serializePackageError(error) {
3693
+ const serviceName = typeof error.context?.service === "string" ? error.context.service : "core";
3694
+ return {
3695
+ id: generateId(),
3696
+ code: error.errorCode ?? types.ERROR_CODES.UNKNOWN_ERROR,
3697
+ message: error.message,
3698
+ status: error.statusCode,
3699
+ category: error.category ?? errors$1.ERROR_CATEGORY.Server,
3700
+ timestamp: error.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
3701
+ isRetryable: error.retryable ?? false,
3702
+ source: serviceName,
3703
+ dismissed: false,
3704
+ context: {
3705
+ correlationId: error.correlationId,
3706
+ ...error.context
3707
+ }
3708
+ };
3709
+ }
3607
3710
  /** Get error store actions from root store */
3608
3711
  static getErrorStoreActions() {
3609
3712
  if (!_Core._rootStore) {
@@ -3615,12 +3718,17 @@ var Core = class _Core {
3615
3718
  return _Core._rootStore.getState().errors;
3616
3719
  }
3617
3720
  /** Build global error handler config */
3618
- // eslint-disable-next-line complexity
3619
3721
  static buildErrorHandlerConfig(config) {
3722
+ const baseErrorFilter = /* @__PURE__ */ __name((error) => {
3723
+ if (error instanceof errors.BaseError) {
3724
+ return false;
3725
+ }
3726
+ return config?.filter ? config.filter(error) : true;
3727
+ }, "baseErrorFilter");
3620
3728
  return {
3621
3729
  source: config?.source ?? "global",
3622
3730
  maxErrors: config?.maxErrors ?? DEFAULT_MAX_ERRORS,
3623
- filter: config?.filter,
3731
+ filter: baseErrorFilter,
3624
3732
  onError: config?.onError,
3625
3733
  logToConsole: config?.logToConsole ?? false
3626
3734
  };
@@ -3641,6 +3749,15 @@ var Core = class _Core {
3641
3749
  });
3642
3750
  await _Core.initializeRootStore(_Core._errorConfig, verbose);
3643
3751
  middleware.setEventEmitter(CoreEventManager.emit.bind(CoreEventManager));
3752
+ errors.BaseError.setEventEmitter((error) => {
3753
+ const serializedError = _Core.serializePackageError(error);
3754
+ const serviceName = serializedError.source ?? "core";
3755
+ CoreEventManager.emit(core.CORE_EVENTS.SYSTEM.ERROR, {
3756
+ errors: [serializedError],
3757
+ context: serviceName,
3758
+ recoverable: error.retryable ?? false
3759
+ });
3760
+ });
3644
3761
  const errorStore = _Core.getErrorStoreActions();
3645
3762
  _Core._errorHandler = middleware.initializeGlobalErrorHandler(
3646
3763
  errorStore,
@@ -3736,9 +3853,15 @@ var Core = class _Core {
3736
3853
  }
3737
3854
  /**
3738
3855
  * Subscribe to CoreEventManager error events
3739
- * Forwards system, entity, API, validation, database, and auth errors to the global error handler.
3856
+ * Forwards entity, API, validation, database, and auth errors to the global error handler.
3857
+ *
3858
+ * NOTE: SYSTEM.ERROR is NOT subscribed here - it's handled in initializeErrorHandler()
3859
+ * via the BaseError.setEventEmitter() + addErrors() pattern to avoid duplicate subscriptions.
3740
3860
  *
3741
- * Note: Database errors (DATABASE.ERROR) are only subscribed on backend runtimes since
3861
+ * For non-BaseError errors, domain-specific events (ENTITY.ERROR, API.REQUEST_ERROR, etc.)
3862
+ * are captured here. BaseError instances are skipped (they already auto-emit via SYSTEM.ERROR).
3863
+ *
3864
+ * Database errors (DATABASE.ERROR) are only subscribed on backend runtimes since
3742
3865
  * DbService is backend-only (skipDb: true on frontend).
3743
3866
  */
3744
3867
  static subscribeToErrorEvents(verbose) {
@@ -3746,78 +3869,36 @@ var Core = class _Core {
3746
3869
  return;
3747
3870
  }
3748
3871
  _Core.log("Subscribing to error events...", verbose);
3749
- const cleanupSystemError = CoreEventManager.on(core.CORE_EVENTS.SYSTEM.ERROR, (event) => {
3750
- if (_Core._errorHandler && event.data?.errors?.length) {
3751
- for (const err of event.data.errors) {
3752
- _Core._errorHandler.captureError(err, "system");
3872
+ const subscribeError = /* @__PURE__ */ __name((event, source) => {
3873
+ return CoreEventManager.on(event, (e) => {
3874
+ if (_Core._errorHandler && e.data?.error && !(e.data.error instanceof errors.BaseError)) {
3875
+ _Core._errorHandler.captureError(e.data.error, source);
3753
3876
  }
3754
- }
3755
- });
3756
- const cleanupEntityError = CoreEventManager.on(core.CORE_EVENTS.ENTITY.ERROR, (event) => {
3757
- if (_Core._errorHandler && event.data) {
3758
- _Core._errorHandler.captureError(event.data.error, "entity");
3759
- }
3760
- });
3761
- const cleanupApiError = CoreEventManager.on(core.CORE_EVENTS.API.REQUEST_ERROR, (event) => {
3762
- if (_Core._errorHandler && event.data) {
3763
- _Core._errorHandler.captureError(event.data.error, "api");
3764
- }
3765
- });
3766
- const cleanupValidationError = CoreEventManager.on(core.CORE_EVENTS.VALIDATION.FAILED, (event) => {
3767
- if (_Core._errorHandler && event.data) {
3768
- _Core._errorHandler.captureError(event.data.error, "validation");
3769
- }
3770
- });
3771
- const cleanupAuthUnauthorized = CoreEventManager.on(core.CORE_EVENTS.AUTH.UNAUTHORIZED, (event) => {
3772
- if (_Core._errorHandler && event.data?.error) {
3773
- _Core._errorHandler.captureError(event.data.error, "auth");
3774
- }
3775
- });
3776
- const cleanupAuthSessionExpired = CoreEventManager.on(
3777
- core.CORE_EVENTS.AUTH.SESSION_EXPIRED,
3778
- (event) => {
3779
- if (_Core._errorHandler && event.data?.error) {
3780
- _Core._errorHandler.captureError(event.data.error, "auth");
3781
- }
3782
- }
3783
- );
3877
+ });
3878
+ }, "subscribeError");
3784
3879
  _Core._eventCleanupFns.push(
3785
- cleanupSystemError,
3786
- cleanupEntityError,
3787
- cleanupApiError,
3788
- cleanupValidationError,
3789
- cleanupAuthUnauthorized,
3790
- cleanupAuthSessionExpired
3880
+ subscribeError(core.CORE_EVENTS.ENTITY.ERROR, "entity"),
3881
+ subscribeError(core.CORE_EVENTS.API.REQUEST_ERROR, "api"),
3882
+ subscribeError(core.CORE_EVENTS.VALIDATION.FAILED, "validation"),
3883
+ subscribeError(core.CORE_EVENTS.AUTH.UNAUTHORIZED, "auth"),
3884
+ subscribeError(core.CORE_EVENTS.AUTH.SESSION_EXPIRED, "auth")
3791
3885
  );
3792
3886
  if (_Core.isRuntimeCompatible("backend")) {
3793
- const cleanupDatabaseError = CoreEventManager.on(core.CORE_EVENTS.DATABASE.ERROR, (event) => {
3794
- if (_Core._errorHandler && event.data) {
3795
- _Core._errorHandler.captureError(event.data.error, "database");
3796
- }
3797
- });
3798
- _Core._eventCleanupFns.push(cleanupDatabaseError);
3799
- const cleanupStorageError = CoreEventManager.on(core.CORE_EVENTS.STORAGE.ERROR, (event) => {
3800
- if (_Core._errorHandler && event.data) {
3801
- _Core._errorHandler.captureError(event.data.error, "storage");
3802
- }
3803
- });
3804
- _Core._eventCleanupFns.push(cleanupStorageError);
3805
- const cleanupNotificationError = CoreEventManager.on(
3806
- core.CORE_EVENTS.NOTIFICATION.ERROR,
3807
- (event) => {
3808
- if (_Core._errorHandler && event.data) {
3809
- _Core._errorHandler.captureError(event.data.error, "notification");
3810
- }
3811
- }
3887
+ _Core._eventCleanupFns.push(
3888
+ subscribeError(core.CORE_EVENTS.DATABASE.ERROR, "database"),
3889
+ subscribeError(core.CORE_EVENTS.STORAGE.ERROR, "storage"),
3890
+ subscribeError(core.CORE_EVENTS.NOTIFICATION.ERROR, "notification"),
3891
+ subscribeError(core.CORE_EVENTS.CACHE.ERROR, "cache")
3892
+ );
3893
+ _Core.log(
3894
+ "Subscribed to backend error events (database, storage, notification, cache)",
3895
+ verbose
3812
3896
  );
3813
- _Core._eventCleanupFns.push(cleanupNotificationError);
3814
- _Core.log("Subscribed to backend error events (database, storage, notification)", verbose);
3815
- }
3816
- const eventTypes = ["system", "entity", "api", "validation", "auth"];
3817
- if (_Core.isRuntimeCompatible("backend")) {
3818
- eventTypes.push("database", "storage", "notification");
3819
3897
  }
3820
- _Core.log(`Subscribed to error events: ${eventTypes.join(", ")}`, verbose);
3898
+ const eventTypes = ["entity", "api", "validation", "auth"];
3899
+ if (_Core.isRuntimeCompatible("backend"))
3900
+ eventTypes.push("database", "storage", "notification", "cache");
3901
+ _Core.log(`Subscribed to domain error events: ${eventTypes.join(", ")}`, verbose);
3821
3902
  }
3822
3903
  /** Handle fetch flags error and return empty flags */
3823
3904
  static handleFetchFlagsError(error, config, verbose) {
@@ -4064,6 +4145,11 @@ var BaseDomainService = class {
4064
4145
  /**
4065
4146
  * Initialize API client asynchronously
4066
4147
  * Called from constructor if apiClientConfig is provided
4148
+ *
4149
+ * Uses ApiClientService.createStandaloneClient() which includes:
4150
+ * - Automatic error handling (single errors and arrays)
4151
+ * - Event emission to CORE_EVENTS.SYSTEM.ERROR and CORE_EVENTS.API.REQUEST_ERROR
4152
+ * - Serialization to unified SerializedError format
4067
4153
  */
4068
4154
  initializeApiClient() {
4069
4155
  if (this._clientInitPromise || !this._apiClientConfig) {
@@ -4071,7 +4157,7 @@ var BaseDomainService = class {
4071
4157
  }
4072
4158
  this._clientInitPromise = (async () => {
4073
4159
  try {
4074
- this._apiClient = await frontend.createApiClient(this._apiClientConfig);
4160
+ this._apiClient = await ApiClientService.createStandaloneClient(this._apiClientConfig);
4075
4161
  if (this._setAsDefaultClient) {
4076
4162
  frontend.setDefaultApiClient(this._apiClient);
4077
4163
  }
@@ -6206,7 +6292,7 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
6206
6292
  // Constructor
6207
6293
  // ─────────────────────────────────────────────────────────────────────────
6208
6294
  constructor(config = {}, options) {
6209
- const apiBasePath = config.apiBasePath ?? "/api/examples";
6295
+ const apiBasePath = config.apiBasePath || "/api/examples";
6210
6296
  super({
6211
6297
  serviceName: "ExampleFrontendService",
6212
6298
  supportedRuntimes: ["frontend"],
@@ -6310,7 +6396,11 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
6310
6396
  static async create(config, options) {
6311
6397
  const mergedConfig = {
6312
6398
  ...config,
6313
- apiBasePath: config.apiBasePath ?? options?.apiClient?.options?.baseURL ?? "/api/examples"
6399
+ // Use || instead of ?? because api.baseURL may be '' (empty string) for same-origin requests.
6400
+ // The ?? operator only falls through on null/undefined, not empty strings.
6401
+ // An empty string is not a valid API path, so we treat it as "not provided" and fall through to default.
6402
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
6403
+ apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || "/api/examples"
6314
6404
  };
6315
6405
  const service = new _FrontendExampleDomainService(mergedConfig, options);
6316
6406
  if (mergedConfig.autoFetch) {
@@ -7619,7 +7709,10 @@ var FrontendFeatureFlagDomainService = class _FrontendFeatureFlagDomainService e
7619
7709
  }
7620
7710
  /** Build API client for feature flags */
7621
7711
  static async buildApiClient(config, options) {
7622
- const apiBasePath = config.apiBasePath ?? options?.apiClient?.options?.baseURL ?? "/feature-flags";
7712
+ const apiBasePath = (
7713
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
7714
+ config.apiBasePath || options?.apiClient?.options?.baseURL || "/feature-flags"
7715
+ );
7623
7716
  return frontend.createApiClient({ ...options?.apiClient?.options, baseURL: apiBasePath });
7624
7717
  }
7625
7718
  /** Build feature flag provider */
@@ -7973,7 +8066,11 @@ async function initializeCore(config) {
7973
8066
  apiKey: config.api.apiKey,
7974
8067
  setAsDefault: true,
7975
8068
  ...apiConfig
7976
- }
8069
+ },
8070
+ // Feature flags config (passed to Core for memory provider setup)
8071
+ featureFlags: config.featureFlags
8072
+ // Error handler is auto-initialized by Core.initialize()
8073
+ // Store (Zustand) is auto-connected via useRootStore in Core.initializeRootStore()
7977
8074
  });
7978
8075
  }
7979
8076
  __name(initializeCore, "initializeCore");