@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.
- package/dist/domain/base/BaseDomainService.d.ts +9 -4
- package/dist/domain/base/BaseDomainService.d.ts.map +1 -1
- package/dist/domain/example/FrontendExampleDomainService.d.ts.map +1 -1
- package/dist/domain/featureFlags/FrontendFeatureFlagDomainService.d.ts.map +1 -1
- package/dist/entry-backend.js +313 -207
- package/dist/entry-backend.js.map +1 -1
- package/dist/entry-backend.mjs +250 -144
- package/dist/entry-backend.mjs.map +1 -1
- package/dist/entry-frontend-browser.js +238 -141
- package/dist/entry-frontend-browser.js.map +1 -1
- package/dist/entry-frontend-browser.mjs +240 -143
- package/dist/entry-frontend-browser.mjs.map +1 -1
- package/dist/entry-frontend.js +238 -141
- package/dist/entry-frontend.js.map +1 -1
- package/dist/entry-frontend.mjs +240 -143
- package/dist/entry-frontend.mjs.map +1 -1
- package/dist/frontend/providers/PlyazProvider.d.ts.map +1 -1
- package/dist/index.js +315 -207
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +251 -144
- package/dist/index.mjs.map +1 -1
- package/dist/init/CoreInitializer.d.ts +13 -2
- package/dist/init/CoreInitializer.d.ts.map +1 -1
- package/dist/init/nestjs/index.js +217 -136
- package/dist/init/nestjs/index.js.map +1 -1
- package/dist/init/nestjs/index.mjs +219 -138
- package/dist/init/nestjs/index.mjs.map +1 -1
- package/dist/services/ApiClientService.d.ts +43 -0
- package/dist/services/ApiClientService.d.ts.map +1 -1
- package/dist/services/CacheService.d.ts +5 -0
- package/dist/services/CacheService.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/entry-frontend.js
CHANGED
|
@@ -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
|
|
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 =
|
|
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
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
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
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
_Core._errorHandler.captureError(
|
|
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
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
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
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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");
|