@plyaz/core 1.10.1 → 1.11.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 (36) hide show
  1. package/dist/base/observability/DatadogAdapter.d.ts.map +1 -1
  2. package/dist/domain/example/FrontendExampleDomainService.d.ts.map +1 -1
  3. package/dist/domain/featureFlags/module.d.ts.map +1 -1
  4. package/dist/domain/files/BackendFilesDomainService.d.ts +10 -13
  5. package/dist/domain/files/BackendFilesDomainService.d.ts.map +1 -1
  6. package/dist/entry-backend.js +382 -200
  7. package/dist/entry-backend.js.map +1 -1
  8. package/dist/entry-backend.mjs +280 -98
  9. package/dist/entry-backend.mjs.map +1 -1
  10. package/dist/entry-frontend-browser.js +122 -35
  11. package/dist/entry-frontend-browser.js.map +1 -1
  12. package/dist/entry-frontend-browser.mjs +123 -33
  13. package/dist/entry-frontend-browser.mjs.map +1 -1
  14. package/dist/entry-frontend.js +122 -35
  15. package/dist/entry-frontend.js.map +1 -1
  16. package/dist/entry-frontend.mjs +123 -33
  17. package/dist/entry-frontend.mjs.map +1 -1
  18. package/dist/frontend/providers/PlyazProvider.d.ts +1 -3
  19. package/dist/frontend/providers/PlyazProvider.d.ts.map +1 -1
  20. package/dist/index.js +1339 -1134
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +1290 -1085
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/init/CoreInitializer.d.ts +31 -1
  25. package/dist/init/CoreInitializer.d.ts.map +1 -1
  26. package/dist/init/nestjs/index.js +126 -14
  27. package/dist/init/nestjs/index.js.map +1 -1
  28. package/dist/init/nestjs/index.mjs +127 -15
  29. package/dist/init/nestjs/index.mjs.map +1 -1
  30. package/dist/services/DbService.d.ts +12 -0
  31. package/dist/services/DbService.d.ts.map +1 -1
  32. package/dist/services/NotificationService.d.ts +8 -0
  33. package/dist/services/NotificationService.d.ts.map +1 -1
  34. package/dist/services/StorageService.d.ts +8 -0
  35. package/dist/services/StorageService.d.ts.map +1 -1
  36. package/package.json +3 -3
@@ -7,8 +7,7 @@ import { EventEmitter } from 'events';
7
7
  import { ERROR_CODES as ERROR_CODES$1, ERROR_CATEGORY as ERROR_CATEGORY$1, API_ERROR_CODES as API_ERROR_CODES$1 } from '@plyaz/types/errors';
8
8
  import { OBSERVABILITY_METRICS } from '@plyaz/types/observability';
9
9
  import { clearEventEmitter, setEventEmitter, initializeGlobalErrorHandler } from '@plyaz/errors/middleware';
10
- import { STORE_KEYS, useRootStore, createStandaloneFeatureFlagStore } from '@plyaz/store';
11
- export { useRootStore } from '@plyaz/store';
10
+ import { STORE_KEYS, createStandaloneFeatureFlagStore } from '@plyaz/store';
12
11
  import { CORE_EVENTS as CORE_EVENTS$1, SERVICE_KEYS } from '@plyaz/types/core';
13
12
  import { uploadFile, uploadFiles, generateDocument, downloadFile, getSignedUrl, deleteFile, getFile } from '@plyaz/api';
14
13
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
@@ -2773,6 +2772,24 @@ var Core = class _Core {
2773
2772
  */
2774
2773
  this._rootStore = null;
2775
2774
  }
2775
+ static {
2776
+ /**
2777
+ * Injected store hook for frontend (set via setRootStoreHook before initialize).
2778
+ * This is used instead of directly importing from @plyaz/store to prevent
2779
+ * duplicate store instances when bundlers create multiple module copies.
2780
+ */
2781
+ this._injectedStoreHook = null;
2782
+ }
2783
+ /**
2784
+ * Set the root store hook for frontend use.
2785
+ * Must be called before Core.initialize() when running in browser.
2786
+ * PlyazProvider calls this automatically with the store prop.
2787
+ *
2788
+ * @param store - The useRootStore hook from @plyaz/store
2789
+ */
2790
+ static setRootStoreHook(store) {
2791
+ _Core._injectedStoreHook = store;
2792
+ }
2776
2793
  /**
2777
2794
  * Setup environment and context
2778
2795
  */
@@ -3683,8 +3700,14 @@ var Core = class _Core {
3683
3700
  static async initializeRootStore(config, verbose) {
3684
3701
  const isFrontend = typeof window !== "undefined";
3685
3702
  if (isFrontend) {
3686
- _Core.log("Using frontend root store (Zustand)", verbose);
3687
- _Core._rootStore = useRootStore;
3703
+ if (!_Core._injectedStoreHook) {
3704
+ throw new CorePackageError(
3705
+ "Root store hook not set. Call Core.setRootStoreHook(useRootStore) before Core.initialize(), or use PlyazProvider with the store prop: <PlyazProvider store={useRootStore} ...>",
3706
+ ERROR_CODES.CLIENT_INITIALIZATION_FAILED
3707
+ );
3708
+ }
3709
+ _Core.log("Using frontend root store (Zustand) - injected via setRootStoreHook", verbose);
3710
+ _Core._rootStore = _Core._injectedStoreHook;
3688
3711
  } else {
3689
3712
  _Core.log("Creating backend composite store (in-memory)", verbose);
3690
3713
  const ServerErrorMiddleware = getCoreDependency("ServerErrorMiddleware");
@@ -3793,26 +3816,76 @@ var Core = class _Core {
3793
3816
  errorStore,
3794
3817
  _Core.buildErrorHandlerConfig(_Core._errorConfig)
3795
3818
  );
3819
+ _Core.setupErrorEventSubscription(verbose);
3820
+ _Core.setupErrorStoreSubscription(verbose);
3821
+ _Core.log("Global error handler initialized with CoreEventManager integration", verbose);
3822
+ if (_Core._errorConfig.httpHandler !== false) {
3823
+ await _Core.createHttpErrorHandler(_Core._errorConfig, verbose);
3824
+ }
3825
+ }
3826
+ /**
3827
+ * Log serialized errors with full details.
3828
+ */
3829
+ static logErrors(errors, prefix = "ErrorStore") {
3830
+ for (const err of errors) {
3831
+ _Core.logger.error(`[${prefix}] ${err.code}: ${err.message}`, {
3832
+ id: err.id,
3833
+ code: err.code,
3834
+ message: err.message,
3835
+ category: err.category,
3836
+ source: err.source,
3837
+ status: err.status,
3838
+ isRetryable: err.isRetryable,
3839
+ context: err.context,
3840
+ timestamp: err.timestamp
3841
+ });
3842
+ }
3843
+ }
3844
+ /**
3845
+ * Setup SYSTEM.ERROR event subscription for error store updates.
3846
+ * Backend: Also logs errors with full details.
3847
+ * Frontend: Only updates store (logging handled by store subscription).
3848
+ */
3849
+ static setupErrorEventSubscription(verbose) {
3850
+ const isBackend = BACKEND_RUNTIMES.includes(_Core._coreServices.runtime);
3796
3851
  const errorEventCleanup = CoreEventManager.on(
3797
3852
  CORE_EVENTS$1.SYSTEM.ERROR,
3798
3853
  (event) => {
3799
3854
  if (!_Core._rootStore) return;
3800
3855
  try {
3801
3856
  const { errors } = event.data;
3802
- if (errors && errors.length > 0) {
3803
- _Core._rootStore.getState().errors.addErrors(errors);
3804
- _Core.log(`Added ${errors.length} error(s) to store`, verbose);
3805
- }
3857
+ if (!errors || errors.length === 0) return;
3858
+ _Core._rootStore.getState().errors.addErrors(errors);
3859
+ if (isBackend) _Core.logErrors(errors);
3860
+ _Core.log(`Added ${errors.length} error(s) to store`, verbose);
3806
3861
  } catch (e) {
3807
3862
  _Core.logger.error("Failed to handle error event", { error: e });
3808
3863
  }
3809
3864
  }
3810
3865
  );
3811
3866
  _Core._eventCleanupFns.push(errorEventCleanup);
3812
- _Core.log("Global error handler initialized with CoreEventManager integration", verbose);
3813
- if (_Core._errorConfig.httpHandler !== false) {
3814
- await _Core.createHttpErrorHandler(_Core._errorConfig, verbose);
3815
- }
3867
+ }
3868
+ /**
3869
+ * Setup error store subscription for frontend logging.
3870
+ * Logs new errors when they're added to the store.
3871
+ * Only active for non-backend runtimes (browser, nextjs, nuxt, edge).
3872
+ */
3873
+ static setupErrorStoreSubscription(verbose) {
3874
+ const isFrontend = !BACKEND_RUNTIMES.includes(_Core._coreServices.runtime);
3875
+ if (!isFrontend || !_Core._rootStore) return;
3876
+ let prevErrorCount = 0;
3877
+ const storeUnsubscribe = _Core._rootStore.subscribe((state) => {
3878
+ const currentCount = state.errors.errorCount;
3879
+ if (currentCount <= prevErrorCount) {
3880
+ prevErrorCount = currentCount;
3881
+ return;
3882
+ }
3883
+ const newErrors = state.errors.errors.slice(0, currentCount - prevErrorCount);
3884
+ _Core.logErrors(newErrors, "ErrorStore:FE");
3885
+ prevErrorCount = currentCount;
3886
+ });
3887
+ _Core._eventCleanupFns.push(storeUnsubscribe);
3888
+ _Core.log("Error store subscription initialized for frontend", verbose);
3816
3889
  }
3817
3890
  /**
3818
3891
  * Create HTTP error handler based on detected runtime.
@@ -6819,7 +6892,7 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
6819
6892
  // Constructor
6820
6893
  // ─────────────────────────────────────────────────────────────────────────
6821
6894
  constructor(config = {}, options) {
6822
- const apiBasePath = config.apiBasePath || "/api/examples";
6895
+ const apiBasePath = config.apiBasePath || "";
6823
6896
  super({
6824
6897
  serviceName: "ExampleFrontendService",
6825
6898
  supportedRuntimes: ["frontend"],
@@ -6844,20 +6917,20 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
6844
6917
  // Note: Use relative paths since apiClient.baseURL is already set to apiBasePath
6845
6918
  fetchers: {
6846
6919
  fetchAll: /* @__PURE__ */ __name(async (query) => {
6847
- return this.apiClient.get("", { params: query });
6920
+ return this.apiClient.get("/examples", { params: query });
6848
6921
  }, "fetchAll"),
6849
6922
  fetchById: /* @__PURE__ */ __name(async (id) => {
6850
- return this.apiClient.get(`/${id}`);
6923
+ return this.apiClient.get(`/examples/${id}`);
6851
6924
  }, "fetchById"),
6852
6925
  create: /* @__PURE__ */ __name(async (data) => {
6853
- return this.apiClient.post("", data);
6926
+ return this.apiClient.post("/examples", data);
6854
6927
  }, "create"),
6855
6928
  update: /* @__PURE__ */ __name(async (payload) => {
6856
6929
  const { id, data } = payload;
6857
- return this.apiClient.patch(`/${id}`, data);
6930
+ return this.apiClient.patch(`/examples/${id}`, data);
6858
6931
  }, "update"),
6859
6932
  delete: /* @__PURE__ */ __name(async (id) => {
6860
- return this.apiClient.delete(`/${id}`);
6933
+ return this.apiClient.delete(`/examples/${id}`);
6861
6934
  }, "delete")
6862
6935
  }
6863
6936
  // Store handlers - customize how data syncs to store
@@ -6925,7 +6998,7 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
6925
6998
  // The ?? operator only falls through on null/undefined, not empty strings.
6926
6999
  // An empty string is not a valid API path, so we treat it as "not provided" and fall through to default.
6927
7000
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
6928
- apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || "/api/examples"
7001
+ apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || ""
6929
7002
  };
6930
7003
  const service = new _FrontendExampleDomainService(mergedConfig, options);
6931
7004
  if (mergedConfig.autoFetch) {
@@ -7086,7 +7159,10 @@ var FrontendExampleDomainService = class _FrontendExampleDomainService extends B
7086
7159
  const response = await this.apiClient.post(endpoint, data);
7087
7160
  if (!this.isResponseSuccess(response)) {
7088
7161
  const error = this.extractResponseError(response);
7089
- throw new Error(`Failed to send email: ${JSON.stringify(error)}`);
7162
+ throw new CorePackageError(
7163
+ `Failed to send email: ${JSON.stringify(error)}`,
7164
+ ERROR_CODES.CORE_OPERATION_FAILED
7165
+ );
7090
7166
  }
7091
7167
  const result = this.unwrapResponseData(response.data);
7092
7168
  CoreEventManager.emit(`${this.eventPrefix}:email:sent`, { result });
@@ -8628,22 +8704,27 @@ async function initializeCore(config) {
8628
8704
  });
8629
8705
  }
8630
8706
  __name(initializeCore, "initializeCore");
8631
- function createStoreRegistry() {
8707
+ function createStoreRegistry(store) {
8632
8708
  return {
8633
8709
  getStore(key) {
8634
- const state = useRootStore.getState();
8710
+ const state = store.getState();
8635
8711
  if (!state) {
8636
8712
  logger4.warn(
8637
8713
  "Store state is undefined - store may not be hydrated yet. This can cause side effects if called during SSR or before initialization."
8638
8714
  );
8639
8715
  return void 0;
8640
8716
  }
8641
- return state[key];
8717
+ const slice = state[key];
8718
+ logger4.debug(`[StoreRegistry] getStore('${key}')`, {
8719
+ hasSlice: !!slice,
8720
+ sliceKeys: slice ? Object.keys(slice) : []
8721
+ });
8722
+ return slice;
8642
8723
  }
8643
8724
  };
8644
8725
  }
8645
8726
  __name(createStoreRegistry, "createStoreRegistry");
8646
- async function initializeServices(config) {
8727
+ async function initializeServices(config, store) {
8647
8728
  if (!config.services || config.services.length === 0) return;
8648
8729
  if (config.verbose) {
8649
8730
  globalThis.console.log("[PlyazProvider] Initializing domain services...");
@@ -8655,7 +8736,7 @@ async function initializeServices(config) {
8655
8736
  observability: config.observability,
8656
8737
  services: config.services,
8657
8738
  // Provide store registry for injecting stores into services
8658
- stores: createStoreRegistry()
8739
+ stores: createStoreRegistry(store)
8659
8740
  });
8660
8741
  if (config.verbose) {
8661
8742
  globalThis.console.log(
@@ -8692,6 +8773,7 @@ function createServicesObject(config, featureFlagStore) {
8692
8773
  __name(createServicesObject, "createServicesObject");
8693
8774
  function PlyazProvider({
8694
8775
  children,
8776
+ store,
8695
8777
  config,
8696
8778
  loading,
8697
8779
  error: errorComponent,
@@ -8705,8 +8787,9 @@ function PlyazProvider({
8705
8787
  const initialize = useCallback(async () => {
8706
8788
  try {
8707
8789
  setError(null);
8790
+ Core.setRootStoreHook(store);
8708
8791
  await initializeCore(config);
8709
- await initializeServices(config);
8792
+ await initializeServices(config, store);
8710
8793
  await initializeFeatureFlags(featureFlagStore);
8711
8794
  setIsReady(true);
8712
8795
  onReady?.(createServicesObject(config, featureFlagStore));
@@ -8716,7 +8799,7 @@ function PlyazProvider({
8716
8799
  onError?.(initError);
8717
8800
  globalThis.console.error("[PlyazProvider] Initialization failed:", initError);
8718
8801
  }
8719
- }, [config, featureFlagStore, onReady, onError]);
8802
+ }, [config, store, featureFlagStore, onReady, onError]);
8720
8803
  const reinitialize = useCallback(async () => {
8721
8804
  setIsReady(false);
8722
8805
  ServiceRegistry.disposeAll();
@@ -8765,8 +8848,9 @@ __name(PlyazProvider, "PlyazProvider");
8765
8848
  function usePlyaz() {
8766
8849
  const context = useContext(PlyazContext);
8767
8850
  if (!context) {
8768
- throw new Error(
8769
- "usePlyaz must be used within a PlyazProvider. Wrap your app with <PlyazProvider config={...}>...</PlyazProvider>"
8851
+ throw new CorePackageError(
8852
+ "usePlyaz must be used within a PlyazProvider. Wrap your app with <PlyazProvider config={...}>...</PlyazProvider>",
8853
+ ERROR_CODES.CORE_PROVIDER_NOT_FOUND
8770
8854
  );
8771
8855
  }
8772
8856
  return context;
@@ -8775,7 +8859,10 @@ __name(usePlyaz, "usePlyaz");
8775
8859
  function useApi() {
8776
8860
  const { api, isReady } = usePlyaz();
8777
8861
  if (!isReady || !api) {
8778
- throw new Error("API client is not ready. Make sure PlyazProvider has finished initializing.");
8862
+ throw new CorePackageError(
8863
+ "API client is not ready. Make sure PlyazProvider has finished initializing.",
8864
+ ERROR_CODES.CORE_PROVIDER_INITIALIZATION_FAILED
8865
+ );
8779
8866
  }
8780
8867
  return api;
8781
8868
  }
@@ -8818,7 +8905,10 @@ __name(useEnvironment, "useEnvironment");
8818
8905
  function useService(key) {
8819
8906
  const { getService, isReady } = usePlyaz();
8820
8907
  if (!isReady) {
8821
- throw new Error(`PlyazProvider not ready. Cannot get service '${key}'.`);
8908
+ throw new CorePackageError(
8909
+ `PlyazProvider not ready. Cannot get service '${key}'.`,
8910
+ ERROR_CODES.CORE_PROVIDER_INITIALIZATION_FAILED
8911
+ );
8822
8912
  }
8823
8913
  return useMemo(() => getService(key), [getService, key]);
8824
8914
  }
@@ -9065,7 +9155,7 @@ var FilesMapper = new FilesMapperClass();
9065
9155
  var logger5 = new PackageLogger({ packageName: "core", service: "FrontendFilesDomainService" });
9066
9156
  var FrontendFilesDomainService = class _FrontendFilesDomainService extends BaseFrontendDomainService {
9067
9157
  constructor(config = {}, options) {
9068
- const apiBasePath = config.apiBasePath || "/api";
9158
+ const apiBasePath = config.apiBasePath || "";
9069
9159
  super({
9070
9160
  serviceName: "FrontendFilesDomainService",
9071
9161
  supportedRuntimes: ["frontend"],
@@ -9128,7 +9218,7 @@ var FrontendFilesDomainService = class _FrontendFilesDomainService extends BaseF
9128
9218
  // The ?? operator only falls through on null/undefined, not empty strings.
9129
9219
  // An empty string is not a valid API path, so we treat it as "not provided" and fall through to default.
9130
9220
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
9131
- apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || "/api"
9221
+ apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || ""
9132
9222
  };
9133
9223
  return new _FrontendFilesDomainService(mergedConfig, options);
9134
9224
  }