@plyaz/core 1.10.0 → 1.11.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/files/BackendFilesDomainService.d.ts +10 -13
- package/dist/domain/files/BackendFilesDomainService.d.ts.map +1 -1
- package/dist/entry-backend.js +348 -189
- package/dist/entry-backend.js.map +1 -1
- package/dist/entry-backend.mjs +245 -86
- package/dist/entry-backend.mjs.map +1 -1
- package/dist/entry-frontend-browser.js +75 -17
- package/dist/entry-frontend-browser.js.map +1 -1
- package/dist/entry-frontend-browser.mjs +75 -17
- package/dist/entry-frontend-browser.mjs.map +1 -1
- package/dist/entry-frontend.js +75 -17
- package/dist/entry-frontend.js.map +1 -1
- package/dist/entry-frontend.mjs +75 -17
- package/dist/entry-frontend.mjs.map +1 -1
- package/dist/frontend/providers/PlyazProvider.d.ts.map +1 -1
- package/dist/index.js +1284 -1114
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1236 -1066
- package/dist/index.mjs.map +1 -1
- package/dist/init/CoreInitializer.d.ts +16 -0
- package/dist/init/CoreInitializer.d.ts.map +1 -1
- package/dist/init/nestjs/index.js +105 -12
- package/dist/init/nestjs/index.js.map +1 -1
- package/dist/init/nestjs/index.mjs +105 -12
- package/dist/init/nestjs/index.mjs.map +1 -1
- package/dist/services/DbService.d.ts +12 -0
- package/dist/services/DbService.d.ts.map +1 -1
- package/dist/services/NotificationService.d.ts +8 -0
- package/dist/services/NotificationService.d.ts.map +1 -1
- package/dist/services/StorageService.d.ts +8 -0
- package/dist/services/StorageService.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/entry-backend.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TIME_CONSTANTS, FORMAT_CONSTANTS, FILE_CHECK_INTERVAL_DEFAULT, FEATURE_FLAG_CACHE_TTL_DEFAULT, FEATURE_FLAG_FILE_PATHS, FEATURE_FLAG_PROVIDERS, NUMERIC_CONSTANTS, HTTP_STATUS as HTTP_STATUS$1,
|
|
1
|
+
import { TIME_CONSTANTS, FORMAT_CONSTANTS, FILE_CHECK_INTERVAL_DEFAULT, FEATURE_FLAG_CACHE_TTL_DEFAULT, FEATURE_FLAG_FILE_PATHS, FEATURE_FLAG_PROVIDERS, NUMERIC_CONSTANTS, DOWNLOAD_CONFIG, HTTP_STATUS as HTTP_STATUS$1, MATH_CONSTANTS, ISO_STANDARDS, CACHE_MAX_SIZE_DEFAULT, CACHE_CLEANUP_INTERVAL_DEFAULT, DEVELOPMENT_CONFIG, STAGING_CONFIG, PRODUCTION_CONFIG, FNV_CONSTANTS, FEATURES, HASH_SEED_CONSTANTS } from '@plyaz/config';
|
|
2
2
|
import { ERROR_CODES as ERROR_CODES$1, HTTP_STATUS, NODE_ENVIRONMENTS, BACKEND_RUNTIMES, FRONTEND_RUNTIMES, UNIVERSAL_RUNTIMES, ERROR_CATEGORY as ERROR_CATEGORY$1, CORE_EVENTS as CORE_EVENTS$1, PACKAGE_STATUS_CODES, API_ERROR_CODES, OPERATIONS, FEATURE_FLAG_PROVIDERS as FEATURE_FLAG_PROVIDERS$2, FEATURE_FLAG_METADATA } from '@plyaz/types';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import { evaluateAllFeatureFlags, createFeatureFlag, updateFeatureFlag, deleteFeatureFlag, fetchFeatureFlagRules, createApiClient, mergeConfigs, ApiPackageError, setDefaultApiClient } from '@plyaz/api/frontend';
|
|
@@ -1356,7 +1356,7 @@ var init_LoggerAdapter = __esm({
|
|
|
1356
1356
|
let status = "unset";
|
|
1357
1357
|
let statusMessage;
|
|
1358
1358
|
const logSpans = this.logSpans;
|
|
1359
|
-
const
|
|
1359
|
+
const logger8 = this.observabilityLogger;
|
|
1360
1360
|
return {
|
|
1361
1361
|
context,
|
|
1362
1362
|
setAttribute: /* @__PURE__ */ __name((key, value) => {
|
|
@@ -1368,7 +1368,7 @@ var init_LoggerAdapter = __esm({
|
|
|
1368
1368
|
addEvent: /* @__PURE__ */ __name((event) => {
|
|
1369
1369
|
events.push(event);
|
|
1370
1370
|
if (logSpans) {
|
|
1371
|
-
|
|
1371
|
+
logger8.debug(`[SPAN EVENT] ${options.name}: ${event.name}`, {
|
|
1372
1372
|
traceId: context.traceId,
|
|
1373
1373
|
spanId: context.spanId,
|
|
1374
1374
|
eventAttributes: event.attributes
|
|
@@ -1383,7 +1383,7 @@ var init_LoggerAdapter = __esm({
|
|
|
1383
1383
|
const duration = (endTime ?? Date.now()) - startTime;
|
|
1384
1384
|
if (logSpans) {
|
|
1385
1385
|
const logMethod = status === "error" ? "warn" : "debug";
|
|
1386
|
-
|
|
1386
|
+
logger8[logMethod](`[SPAN END] ${options.name}`, {
|
|
1387
1387
|
traceId: context.traceId,
|
|
1388
1388
|
spanId: context.spanId,
|
|
1389
1389
|
durationMs: duration,
|
|
@@ -1396,7 +1396,7 @@ var init_LoggerAdapter = __esm({
|
|
|
1396
1396
|
}, "end"),
|
|
1397
1397
|
recordException: /* @__PURE__ */ __name((error) => {
|
|
1398
1398
|
if (logSpans) {
|
|
1399
|
-
|
|
1399
|
+
logger8.error(`[SPAN ERROR] ${options.name}`, {
|
|
1400
1400
|
traceId: context.traceId,
|
|
1401
1401
|
spanId: context.spanId,
|
|
1402
1402
|
error: error.message,
|
|
@@ -3144,6 +3144,11 @@ var init_CoreInitializer = __esm({
|
|
|
3144
3144
|
environment: globalEnvironment,
|
|
3145
3145
|
runtime,
|
|
3146
3146
|
apiClient: apiConfig ? { baseURL: apiConfig.baseURL, ...apiConfig } : void 0,
|
|
3147
|
+
db: options.db,
|
|
3148
|
+
cache: options.cache,
|
|
3149
|
+
storage: options.storage,
|
|
3150
|
+
notifications: options.notifications,
|
|
3151
|
+
observability: options.observability,
|
|
3147
3152
|
services: mergedServices,
|
|
3148
3153
|
stores: {
|
|
3149
3154
|
// Returns specific slice from namespaced root store (type-safe)
|
|
@@ -3953,26 +3958,76 @@ var init_CoreInitializer = __esm({
|
|
|
3953
3958
|
errorStore,
|
|
3954
3959
|
_Core.buildErrorHandlerConfig(_Core._errorConfig)
|
|
3955
3960
|
);
|
|
3961
|
+
_Core.setupErrorEventSubscription(verbose);
|
|
3962
|
+
_Core.setupErrorStoreSubscription(verbose);
|
|
3963
|
+
_Core.log("Global error handler initialized with CoreEventManager integration", verbose);
|
|
3964
|
+
if (_Core._errorConfig.httpHandler !== false) {
|
|
3965
|
+
await _Core.createHttpErrorHandler(_Core._errorConfig, verbose);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
/**
|
|
3969
|
+
* Log serialized errors with full details.
|
|
3970
|
+
*/
|
|
3971
|
+
static logErrors(errors, prefix = "ErrorStore") {
|
|
3972
|
+
for (const err of errors) {
|
|
3973
|
+
_Core.logger.error(`[${prefix}] ${err.code}: ${err.message}`, {
|
|
3974
|
+
id: err.id,
|
|
3975
|
+
code: err.code,
|
|
3976
|
+
message: err.message,
|
|
3977
|
+
category: err.category,
|
|
3978
|
+
source: err.source,
|
|
3979
|
+
status: err.status,
|
|
3980
|
+
isRetryable: err.isRetryable,
|
|
3981
|
+
context: err.context,
|
|
3982
|
+
timestamp: err.timestamp
|
|
3983
|
+
});
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
/**
|
|
3987
|
+
* Setup SYSTEM.ERROR event subscription for error store updates.
|
|
3988
|
+
* Backend: Also logs errors with full details.
|
|
3989
|
+
* Frontend: Only updates store (logging handled by store subscription).
|
|
3990
|
+
*/
|
|
3991
|
+
static setupErrorEventSubscription(verbose) {
|
|
3992
|
+
const isBackend = BACKEND_RUNTIMES.includes(_Core._coreServices.runtime);
|
|
3956
3993
|
const errorEventCleanup = CoreEventManager.on(
|
|
3957
3994
|
CORE_EVENTS.SYSTEM.ERROR,
|
|
3958
3995
|
(event) => {
|
|
3959
3996
|
if (!_Core._rootStore) return;
|
|
3960
3997
|
try {
|
|
3961
3998
|
const { errors } = event.data;
|
|
3962
|
-
if (errors
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
}
|
|
3999
|
+
if (!errors || errors.length === 0) return;
|
|
4000
|
+
_Core._rootStore.getState().errors.addErrors(errors);
|
|
4001
|
+
if (isBackend) _Core.logErrors(errors);
|
|
4002
|
+
_Core.log(`Added ${errors.length} error(s) to store`, verbose);
|
|
3966
4003
|
} catch (e) {
|
|
3967
4004
|
_Core.logger.error("Failed to handle error event", { error: e });
|
|
3968
4005
|
}
|
|
3969
4006
|
}
|
|
3970
4007
|
);
|
|
3971
4008
|
_Core._eventCleanupFns.push(errorEventCleanup);
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
4009
|
+
}
|
|
4010
|
+
/**
|
|
4011
|
+
* Setup error store subscription for frontend logging.
|
|
4012
|
+
* Logs new errors when they're added to the store.
|
|
4013
|
+
* Only active for non-backend runtimes (browser, nextjs, nuxt, edge).
|
|
4014
|
+
*/
|
|
4015
|
+
static setupErrorStoreSubscription(verbose) {
|
|
4016
|
+
const isFrontend = !BACKEND_RUNTIMES.includes(_Core._coreServices.runtime);
|
|
4017
|
+
if (!isFrontend || !_Core._rootStore) return;
|
|
4018
|
+
let prevErrorCount = 0;
|
|
4019
|
+
const storeUnsubscribe = _Core._rootStore.subscribe((state) => {
|
|
4020
|
+
const currentCount = state.errors.errorCount;
|
|
4021
|
+
if (currentCount <= prevErrorCount) {
|
|
4022
|
+
prevErrorCount = currentCount;
|
|
4023
|
+
return;
|
|
4024
|
+
}
|
|
4025
|
+
const newErrors = state.errors.errors.slice(0, currentCount - prevErrorCount);
|
|
4026
|
+
_Core.logErrors(newErrors, "ErrorStore:FE");
|
|
4027
|
+
prevErrorCount = currentCount;
|
|
4028
|
+
});
|
|
4029
|
+
_Core._eventCleanupFns.push(storeUnsubscribe);
|
|
4030
|
+
_Core.log("Error store subscription initialized for frontend", verbose);
|
|
3976
4031
|
}
|
|
3977
4032
|
/**
|
|
3978
4033
|
* Create HTTP error handler based on detected runtime.
|
|
@@ -8690,7 +8745,7 @@ var init_FrontendExampleDomainService = __esm({
|
|
|
8690
8745
|
// Constructor
|
|
8691
8746
|
// ─────────────────────────────────────────────────────────────────────────
|
|
8692
8747
|
constructor(config = {}, options) {
|
|
8693
|
-
const apiBasePath = config.apiBasePath || "
|
|
8748
|
+
const apiBasePath = config.apiBasePath || "";
|
|
8694
8749
|
super({
|
|
8695
8750
|
serviceName: "ExampleFrontendService",
|
|
8696
8751
|
supportedRuntimes: ["frontend"],
|
|
@@ -8715,20 +8770,20 @@ var init_FrontendExampleDomainService = __esm({
|
|
|
8715
8770
|
// Note: Use relative paths since apiClient.baseURL is already set to apiBasePath
|
|
8716
8771
|
fetchers: {
|
|
8717
8772
|
fetchAll: /* @__PURE__ */ __name(async (query) => {
|
|
8718
|
-
return this.apiClient.get("", { params: query });
|
|
8773
|
+
return this.apiClient.get("/examples", { params: query });
|
|
8719
8774
|
}, "fetchAll"),
|
|
8720
8775
|
fetchById: /* @__PURE__ */ __name(async (id) => {
|
|
8721
|
-
return this.apiClient.get(
|
|
8776
|
+
return this.apiClient.get(`/examples/${id}`);
|
|
8722
8777
|
}, "fetchById"),
|
|
8723
8778
|
create: /* @__PURE__ */ __name(async (data) => {
|
|
8724
|
-
return this.apiClient.post("", data);
|
|
8779
|
+
return this.apiClient.post("/examples", data);
|
|
8725
8780
|
}, "create"),
|
|
8726
8781
|
update: /* @__PURE__ */ __name(async (payload) => {
|
|
8727
8782
|
const { id, data } = payload;
|
|
8728
|
-
return this.apiClient.patch(
|
|
8783
|
+
return this.apiClient.patch(`/examples/${id}`, data);
|
|
8729
8784
|
}, "update"),
|
|
8730
8785
|
delete: /* @__PURE__ */ __name(async (id) => {
|
|
8731
|
-
return this.apiClient.delete(
|
|
8786
|
+
return this.apiClient.delete(`/examples/${id}`);
|
|
8732
8787
|
}, "delete")
|
|
8733
8788
|
}
|
|
8734
8789
|
// Store handlers - customize how data syncs to store
|
|
@@ -8796,7 +8851,7 @@ var init_FrontendExampleDomainService = __esm({
|
|
|
8796
8851
|
// The ?? operator only falls through on null/undefined, not empty strings.
|
|
8797
8852
|
// An empty string is not a valid API path, so we treat it as "not provided" and fall through to default.
|
|
8798
8853
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
8799
|
-
apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || "
|
|
8854
|
+
apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || ""
|
|
8800
8855
|
};
|
|
8801
8856
|
const service = new _FrontendExampleDomainService(mergedConfig, options);
|
|
8802
8857
|
if (mergedConfig.autoFetch) {
|
|
@@ -9200,7 +9255,7 @@ var init_FrontendFilesDomainService = __esm({
|
|
|
9200
9255
|
logger4 = new PackageLogger({ packageName: "core", service: "FrontendFilesDomainService" });
|
|
9201
9256
|
FrontendFilesDomainService = class _FrontendFilesDomainService extends BaseFrontendDomainService {
|
|
9202
9257
|
constructor(config = {}, options) {
|
|
9203
|
-
const apiBasePath = config.apiBasePath || "
|
|
9258
|
+
const apiBasePath = config.apiBasePath || "";
|
|
9204
9259
|
super({
|
|
9205
9260
|
serviceName: "FrontendFilesDomainService",
|
|
9206
9261
|
supportedRuntimes: ["frontend"],
|
|
@@ -9263,7 +9318,7 @@ var init_FrontendFilesDomainService = __esm({
|
|
|
9263
9318
|
// The ?? operator only falls through on null/undefined, not empty strings.
|
|
9264
9319
|
// An empty string is not a valid API path, so we treat it as "not provided" and fall through to default.
|
|
9265
9320
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
9266
|
-
apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || "
|
|
9321
|
+
apiBasePath: config.apiBasePath || options?.apiClient?.options?.baseURL || ""
|
|
9267
9322
|
};
|
|
9268
9323
|
return new _FrontendFilesDomainService(mergedConfig, options);
|
|
9269
9324
|
}
|
|
@@ -9439,10 +9494,11 @@ var init_FrontendFilesDomainService = __esm({
|
|
|
9439
9494
|
__name(resetFilesFrontendService, "resetFilesFrontendService");
|
|
9440
9495
|
}
|
|
9441
9496
|
});
|
|
9442
|
-
var DEFAULT_ENCRYPTION_FIELDS, DEFAULT_CACHE_TTL_SECONDS, DEFAULT_AUDIT_RETENTION_DAYS, DEFAULT_POOL_SIZE, DEFAULT_CONFIG, TABLE_REGISTRY, DbService;
|
|
9497
|
+
var logger5, DEFAULT_ENCRYPTION_FIELDS, DEFAULT_CACHE_TTL_SECONDS, DEFAULT_AUDIT_RETENTION_DAYS, DEFAULT_POOL_SIZE, DEFAULT_CONFIG, TABLE_REGISTRY, DbService;
|
|
9443
9498
|
var init_DbService = __esm({
|
|
9444
9499
|
"src/services/DbService.ts"() {
|
|
9445
9500
|
init_CoreEventManager();
|
|
9501
|
+
logger5 = new PackageLogger({ packageName: "core", service: "DbService" });
|
|
9446
9502
|
DEFAULT_ENCRYPTION_FIELDS = {
|
|
9447
9503
|
// User PII
|
|
9448
9504
|
users: ["password_hash", "phone_number", "date_of_birth"],
|
|
@@ -9536,6 +9592,41 @@ var init_DbService = __esm({
|
|
|
9536
9592
|
};
|
|
9537
9593
|
CoreEventManager.emit(CORE_EVENTS.DATABASE.ERROR, payload);
|
|
9538
9594
|
}
|
|
9595
|
+
/**
|
|
9596
|
+
* Creates merged event handlers that wrap user-provided handlers.
|
|
9597
|
+
* Adds Core-level logging and forwards to user handlers.
|
|
9598
|
+
*
|
|
9599
|
+
* Note: Unlike StorageService/NotificationService, DB events don't emit
|
|
9600
|
+
* to CoreEventManager by default (too verbose). User handlers can emit
|
|
9601
|
+
* if needed.
|
|
9602
|
+
*
|
|
9603
|
+
* @param userHandlers - User-provided event handlers from config
|
|
9604
|
+
* @returns Merged handlers with Core logging + user handlers
|
|
9605
|
+
*/
|
|
9606
|
+
static createMergedEventHandlers(userHandlers) {
|
|
9607
|
+
return {
|
|
9608
|
+
...userHandlers,
|
|
9609
|
+
onAfterWrite: /* @__PURE__ */ __name(async (event) => {
|
|
9610
|
+
logger5.debug("Database write completed", {
|
|
9611
|
+
operation: event.operation,
|
|
9612
|
+
table: event.table,
|
|
9613
|
+
duration: event.duration
|
|
9614
|
+
});
|
|
9615
|
+
if (userHandlers?.onAfterWrite) {
|
|
9616
|
+
await userHandlers.onAfterWrite(event);
|
|
9617
|
+
}
|
|
9618
|
+
}, "onAfterWrite"),
|
|
9619
|
+
onAfterRead: /* @__PURE__ */ __name(async (event) => {
|
|
9620
|
+
logger5.debug("Database read completed", {
|
|
9621
|
+
table: event.table,
|
|
9622
|
+
duration: event.duration
|
|
9623
|
+
});
|
|
9624
|
+
if (userHandlers?.onAfterRead) {
|
|
9625
|
+
await userHandlers.onAfterRead(event);
|
|
9626
|
+
}
|
|
9627
|
+
}, "onAfterRead")
|
|
9628
|
+
};
|
|
9629
|
+
}
|
|
9539
9630
|
/**
|
|
9540
9631
|
* Gets the singleton instance of DbService
|
|
9541
9632
|
*
|
|
@@ -9740,6 +9831,8 @@ var init_DbService = __esm({
|
|
|
9740
9831
|
if (cache) dbConfig.cache = cache;
|
|
9741
9832
|
if (audit) dbConfig.audit = audit;
|
|
9742
9833
|
if (encryption) dbConfig.encryption = encryption;
|
|
9834
|
+
const events = _DbService.createMergedEventHandlers(config.events);
|
|
9835
|
+
if (events) dbConfig.events = events;
|
|
9743
9836
|
return dbConfig;
|
|
9744
9837
|
}
|
|
9745
9838
|
/**
|
|
@@ -10963,11 +11056,10 @@ var BackendFilesDomainService, backendFilesDomainService, _instance2;
|
|
|
10963
11056
|
var init_BackendFilesDomainService = __esm({
|
|
10964
11057
|
"src/domain/files/BackendFilesDomainService.ts"() {
|
|
10965
11058
|
init_base();
|
|
10966
|
-
init_events();
|
|
10967
11059
|
init_files();
|
|
10968
11060
|
init_FilesMapper();
|
|
10969
11061
|
init_FilesValidator();
|
|
10970
|
-
|
|
11062
|
+
init_FilesMapper();
|
|
10971
11063
|
BackendFilesDomainService = class _BackendFilesDomainService extends BaseBackendDomainService {
|
|
10972
11064
|
constructor(config = {}, injected) {
|
|
10973
11065
|
super({
|
|
@@ -11006,7 +11098,6 @@ var init_BackendFilesDomainService = __esm({
|
|
|
11006
11098
|
*/
|
|
11007
11099
|
// eslint-disable-next-line complexity
|
|
11008
11100
|
static async create(config = {}, options) {
|
|
11009
|
-
this.registerEventHandlers();
|
|
11010
11101
|
const injected = {
|
|
11011
11102
|
cache: options?.cache?.instance,
|
|
11012
11103
|
db: options?.db?.instance,
|
|
@@ -11016,59 +11107,6 @@ var init_BackendFilesDomainService = __esm({
|
|
|
11016
11107
|
};
|
|
11017
11108
|
return new _BackendFilesDomainService(config, injected);
|
|
11018
11109
|
}
|
|
11019
|
-
/**
|
|
11020
|
-
* Register event handlers for file upload persistence.
|
|
11021
|
-
* Called by CoreInitializer after storage and DB are initialized.
|
|
11022
|
-
*
|
|
11023
|
-
* Events handled:
|
|
11024
|
-
* - files:upload:uploaded - Persist single file to DB
|
|
11025
|
-
* - files:upload:bulk:uploaded - Persist multiple files to DB
|
|
11026
|
-
*
|
|
11027
|
-
* Deduplication: Uses unique constraint on storage_path.
|
|
11028
|
-
*
|
|
11029
|
-
* @param verbose - Enable verbose logging
|
|
11030
|
-
*/
|
|
11031
|
-
static registerEventHandlers(verbose) {
|
|
11032
|
-
if (BackendEventPersistenceHandler.isRegistered("files")) {
|
|
11033
|
-
return;
|
|
11034
|
-
}
|
|
11035
|
-
BackendEventPersistenceHandler.register({
|
|
11036
|
-
domain: "files",
|
|
11037
|
-
events: {
|
|
11038
|
-
"files:upload:uploaded": {
|
|
11039
|
-
extractPayload: /* @__PURE__ */ __name((payload) => {
|
|
11040
|
-
if (!isObject(payload)) return void 0;
|
|
11041
|
-
const p = payload;
|
|
11042
|
-
if (!FilesMapperClass.isUploadResult(p.result)) return void 0;
|
|
11043
|
-
return p.result;
|
|
11044
|
-
}, "extractPayload"),
|
|
11045
|
-
isBulk: false,
|
|
11046
|
-
validate: /* @__PURE__ */ __name((item) => Boolean(item.metadata?.fileId), "validate")
|
|
11047
|
-
},
|
|
11048
|
-
"files:upload:bulk:uploaded": {
|
|
11049
|
-
extractPayload: /* @__PURE__ */ __name((payload) => {
|
|
11050
|
-
if (!isObject(payload)) return [];
|
|
11051
|
-
const p = payload;
|
|
11052
|
-
const results = p.result?.results;
|
|
11053
|
-
if (!Array.isArray(results)) return [];
|
|
11054
|
-
return results.filter(FilesMapperClass.isUploadResult);
|
|
11055
|
-
}, "extractPayload"),
|
|
11056
|
-
isBulk: true,
|
|
11057
|
-
validate: /* @__PURE__ */ __name((item) => Boolean(item.metadata?.fileId), "validate")
|
|
11058
|
-
}
|
|
11059
|
-
},
|
|
11060
|
-
loadDependencies: /* @__PURE__ */ __name(async () => ({
|
|
11061
|
-
repository: FilesRepository.create(),
|
|
11062
|
-
mapper: FilesMapper
|
|
11063
|
-
}), "loadDependencies"),
|
|
11064
|
-
mapToDbRow: /* @__PURE__ */ __name((mapper, item) => mapper.toDbRow(item), "mapToDbRow"),
|
|
11065
|
-
createRecord: /* @__PURE__ */ __name(async (repository, dbRow) => {
|
|
11066
|
-
return repository.create(dbRow);
|
|
11067
|
-
}, "createRecord"),
|
|
11068
|
-
getUniqueKey: /* @__PURE__ */ __name((item) => item.metadata.path ?? item.metadata.fileId, "getUniqueKey"),
|
|
11069
|
-
verbose
|
|
11070
|
-
});
|
|
11071
|
-
}
|
|
11072
11110
|
isAvailable() {
|
|
11073
11111
|
return this.isServiceEnabled;
|
|
11074
11112
|
}
|
|
@@ -11171,6 +11209,36 @@ var init_BackendFilesDomainService = __esm({
|
|
|
11171
11209
|
}
|
|
11172
11210
|
}
|
|
11173
11211
|
// ─────────────────────────────────────────────────────────────────────────
|
|
11212
|
+
// DB Persistence (called by StorageService on upload complete)
|
|
11213
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
11214
|
+
/**
|
|
11215
|
+
* Persist uploaded file metadata to the media table.
|
|
11216
|
+
* Called by StorageService.onFileUploaded event handler.
|
|
11217
|
+
*
|
|
11218
|
+
* @param metadata - File metadata from storage upload
|
|
11219
|
+
* @param variants - Optional file variants (thumbnails, etc.)
|
|
11220
|
+
* @param userId - Optional user ID who uploaded the file
|
|
11221
|
+
*/
|
|
11222
|
+
async persistUploadedFile(metadata, variants, userId) {
|
|
11223
|
+
const startTime = Date.now();
|
|
11224
|
+
this.logDebug("Persisting uploaded file to DB", {
|
|
11225
|
+
fileId: metadata.fileId,
|
|
11226
|
+
filename: metadata.filename
|
|
11227
|
+
});
|
|
11228
|
+
try {
|
|
11229
|
+
const dbRow = FilesMapper.toDbRow({ metadata, variants }, userId);
|
|
11230
|
+
await this.repository.create(dbRow);
|
|
11231
|
+
this.logDebug("File persisted to media table", {
|
|
11232
|
+
fileId: metadata.fileId,
|
|
11233
|
+
filename: metadata.filename
|
|
11234
|
+
});
|
|
11235
|
+
await this.recordOperationMetrics("persistUploadedFile", Date.now() - startTime, true);
|
|
11236
|
+
} catch (error) {
|
|
11237
|
+
await this.recordOperationMetrics("persistUploadedFile", Date.now() - startTime, false);
|
|
11238
|
+
throw error;
|
|
11239
|
+
}
|
|
11240
|
+
}
|
|
11241
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
11174
11242
|
// NOTE: CRUD and Storage Methods Are Inherited from BaseBackendDomainService
|
|
11175
11243
|
// ─────────────────────────────────────────────────────────────────────────
|
|
11176
11244
|
//
|
|
@@ -11431,6 +11499,8 @@ var getCacheService = /* @__PURE__ */ __name(() => CacheService.getInstance(), "
|
|
|
11431
11499
|
|
|
11432
11500
|
// src/services/StorageService.ts
|
|
11433
11501
|
init_CoreEventManager();
|
|
11502
|
+
init_BackendFilesDomainService();
|
|
11503
|
+
var logger6 = new PackageLogger({ packageName: "core", service: "StorageService" });
|
|
11434
11504
|
var StorageService = class _StorageService {
|
|
11435
11505
|
constructor() {
|
|
11436
11506
|
this.storageService = null;
|
|
@@ -11487,6 +11557,28 @@ var StorageService = class _StorageService {
|
|
|
11487
11557
|
_StorageService.instance = null;
|
|
11488
11558
|
}
|
|
11489
11559
|
}
|
|
11560
|
+
/**
|
|
11561
|
+
* Creates merged event handlers that persist uploads to the media table.
|
|
11562
|
+
* Merges Core's internal DB persistence handler with user-provided handlers.
|
|
11563
|
+
*
|
|
11564
|
+
* @param userHandlers - User-provided event handlers from config
|
|
11565
|
+
* @returns Merged handlers with DB persistence + user handlers
|
|
11566
|
+
*/
|
|
11567
|
+
static createMergedEventHandlers(userHandlers) {
|
|
11568
|
+
return {
|
|
11569
|
+
...userHandlers,
|
|
11570
|
+
// Persist uploaded files to media table, then call user handler
|
|
11571
|
+
onFileUploaded: /* @__PURE__ */ __name(async (payload) => {
|
|
11572
|
+
if (payload.metadata) {
|
|
11573
|
+
const filesService = await getBackendFilesDomainService();
|
|
11574
|
+
await filesService.persistUploadedFile(payload.metadata);
|
|
11575
|
+
}
|
|
11576
|
+
if (userHandlers?.onFileUploaded) {
|
|
11577
|
+
await userHandlers.onFileUploaded(payload);
|
|
11578
|
+
}
|
|
11579
|
+
}, "onFileUploaded")
|
|
11580
|
+
};
|
|
11581
|
+
}
|
|
11490
11582
|
/**
|
|
11491
11583
|
* Initializes the storage service
|
|
11492
11584
|
*
|
|
@@ -11499,7 +11591,13 @@ var StorageService = class _StorageService {
|
|
|
11499
11591
|
return instance;
|
|
11500
11592
|
}
|
|
11501
11593
|
instance.config = config;
|
|
11502
|
-
|
|
11594
|
+
const mergedHandlers = _StorageService.createMergedEventHandlers(config.handlers);
|
|
11595
|
+
const mergedConfig = {
|
|
11596
|
+
...config,
|
|
11597
|
+
handlers: mergedHandlers
|
|
11598
|
+
};
|
|
11599
|
+
logger6.info("[StorageService] Initializing with merged event handlers for DB persistence");
|
|
11600
|
+
instance.storageService = new StorageService$1(mergedConfig);
|
|
11503
11601
|
instance.initialized = true;
|
|
11504
11602
|
return instance;
|
|
11505
11603
|
}
|
|
@@ -11636,6 +11734,7 @@ var StorageService = class _StorageService {
|
|
|
11636
11734
|
|
|
11637
11735
|
// src/services/NotificationService.ts
|
|
11638
11736
|
init_CoreEventManager();
|
|
11737
|
+
var MAX_FAIL_ATTEMPTS = 3;
|
|
11639
11738
|
var NotificationService = class _NotificationService {
|
|
11640
11739
|
constructor() {
|
|
11641
11740
|
this.notificationService = null;
|
|
@@ -11666,6 +11765,58 @@ var NotificationService = class _NotificationService {
|
|
|
11666
11765
|
CoreEventManager.emit(CORE_EVENTS.NOTIFICATION.ERROR, payload);
|
|
11667
11766
|
}
|
|
11668
11767
|
// ─────────────────────────────────────────────────────────────────
|
|
11768
|
+
// Merged Event Handlers
|
|
11769
|
+
// ─────────────────────────────────────────────────────────────────
|
|
11770
|
+
/**
|
|
11771
|
+
* Creates merged event handlers that emit to CoreEventManager.
|
|
11772
|
+
* Merges Core's internal handlers with user-provided handlers.
|
|
11773
|
+
*
|
|
11774
|
+
* @param userHandlers - User-provided event handlers from config
|
|
11775
|
+
* @returns Merged handlers with Core event emission + user handlers
|
|
11776
|
+
*/
|
|
11777
|
+
static createMergedEventHandlers(userHandlers) {
|
|
11778
|
+
return {
|
|
11779
|
+
...userHandlers,
|
|
11780
|
+
// Emit to CoreEventManager on sent, then call user handler
|
|
11781
|
+
onSent: /* @__PURE__ */ __name(async (payload) => {
|
|
11782
|
+
CoreEventManager.emit(CORE_EVENTS.NOTIFICATION.SENT, {
|
|
11783
|
+
notificationId: payload.notificationId,
|
|
11784
|
+
recipientId: payload.recipientId,
|
|
11785
|
+
channel: payload.channel,
|
|
11786
|
+
provider: payload.provider
|
|
11787
|
+
});
|
|
11788
|
+
if (userHandlers?.onSent) {
|
|
11789
|
+
await userHandlers.onSent(payload);
|
|
11790
|
+
}
|
|
11791
|
+
}, "onSent"),
|
|
11792
|
+
// Emit to CoreEventManager on failed, then call user handler
|
|
11793
|
+
onFailed: /* @__PURE__ */ __name(async (payload) => {
|
|
11794
|
+
CoreEventManager.emit(CORE_EVENTS.NOTIFICATION.FAILED, {
|
|
11795
|
+
notificationId: payload.notificationId,
|
|
11796
|
+
recipientId: payload.recipientId,
|
|
11797
|
+
channel: payload.channel,
|
|
11798
|
+
error: payload.error,
|
|
11799
|
+
retryable: payload.retryCount < MAX_FAIL_ATTEMPTS
|
|
11800
|
+
});
|
|
11801
|
+
if (userHandlers?.onFailed) {
|
|
11802
|
+
await userHandlers.onFailed(payload);
|
|
11803
|
+
}
|
|
11804
|
+
}, "onFailed"),
|
|
11805
|
+
// Emit to CoreEventManager on delivered, then call user handler
|
|
11806
|
+
onDelivered: /* @__PURE__ */ __name(async (payload) => {
|
|
11807
|
+
CoreEventManager.emit(CORE_EVENTS.NOTIFICATION.DELIVERED, {
|
|
11808
|
+
notificationId: payload.notificationId,
|
|
11809
|
+
recipientId: payload.recipientId,
|
|
11810
|
+
channel: payload.channel,
|
|
11811
|
+
deliveredAt: payload.deliveredAt
|
|
11812
|
+
});
|
|
11813
|
+
if (userHandlers?.onDelivered) {
|
|
11814
|
+
await userHandlers.onDelivered(payload);
|
|
11815
|
+
}
|
|
11816
|
+
}, "onDelivered")
|
|
11817
|
+
};
|
|
11818
|
+
}
|
|
11819
|
+
// ─────────────────────────────────────────────────────────────────
|
|
11669
11820
|
// Singleton Management
|
|
11670
11821
|
// ─────────────────────────────────────────────────────────────────
|
|
11671
11822
|
/**
|
|
@@ -11703,8 +11854,12 @@ var NotificationService = class _NotificationService {
|
|
|
11703
11854
|
if (instance.initialized) {
|
|
11704
11855
|
return instance;
|
|
11705
11856
|
}
|
|
11857
|
+
const mergedEvents = _NotificationService.createMergedEventHandlers(config.events);
|
|
11706
11858
|
instance.config = config;
|
|
11707
|
-
instance.notificationService = new NotificationService$1(
|
|
11859
|
+
instance.notificationService = new NotificationService$1({
|
|
11860
|
+
...config,
|
|
11861
|
+
events: mergedEvents
|
|
11862
|
+
});
|
|
11708
11863
|
instance.initialized = true;
|
|
11709
11864
|
return instance;
|
|
11710
11865
|
}
|
|
@@ -11822,9 +11977,13 @@ var NotificationService = class _NotificationService {
|
|
|
11822
11977
|
* @returns Promise that resolves to a new dedicated NotificationService instance
|
|
11823
11978
|
*/
|
|
11824
11979
|
static async createInstance(config) {
|
|
11980
|
+
const mergedEvents = _NotificationService.createMergedEventHandlers(config.events);
|
|
11825
11981
|
const dedicatedInstance = new _NotificationService();
|
|
11826
11982
|
dedicatedInstance.config = config;
|
|
11827
|
-
dedicatedInstance.notificationService = new NotificationService$1(
|
|
11983
|
+
dedicatedInstance.notificationService = new NotificationService$1({
|
|
11984
|
+
...config,
|
|
11985
|
+
events: mergedEvents
|
|
11986
|
+
});
|
|
11828
11987
|
dedicatedInstance.initialized = true;
|
|
11829
11988
|
return dedicatedInstance;
|
|
11830
11989
|
}
|
|
@@ -16800,7 +16959,7 @@ ErrorHandlingInterceptor = __decorateClass([
|
|
|
16800
16959
|
|
|
16801
16960
|
// src/backend/featureFlags/config/validation.ts
|
|
16802
16961
|
init_validation();
|
|
16803
|
-
var
|
|
16962
|
+
var logger7 = new PackageLogger({
|
|
16804
16963
|
packageName: "core",
|
|
16805
16964
|
service: "FeatureFlagConfigValidator"
|
|
16806
16965
|
});
|
|
@@ -16986,7 +17145,7 @@ var FeatureFlagConfigValidator = class {
|
|
|
16986
17145
|
static getWarnings(config, environment) {
|
|
16987
17146
|
const env = environment ?? (config.isLoggingEnabled ? NODE_ENVIRONMENTS.DEVELOPMENT : NODE_ENVIRONMENTS.PRODUCTION);
|
|
16988
17147
|
if (config.cacheTtl > NUMERIC_CONSTANTS.ONE_HOUR_SECONDS) {
|
|
16989
|
-
|
|
17148
|
+
logger7.warn(
|
|
16990
17149
|
"Cache TTL is very high (>1 hour). Consider reducing for better responsiveness.",
|
|
16991
17150
|
{
|
|
16992
17151
|
field: "cacheTtl",
|
|
@@ -16996,13 +17155,13 @@ var FeatureFlagConfigValidator = class {
|
|
|
16996
17155
|
);
|
|
16997
17156
|
}
|
|
16998
17157
|
if (env === NODE_ENVIRONMENTS.PRODUCTION && config.isLoggingEnabled) {
|
|
16999
|
-
|
|
17158
|
+
logger7.warn("Logging is enabled in production. Consider disabling for performance.", {
|
|
17000
17159
|
field: "isLoggingEnabled",
|
|
17001
17160
|
code: "PRODUCTION_LOGGING_ENABLED"
|
|
17002
17161
|
});
|
|
17003
17162
|
}
|
|
17004
17163
|
if (env === NODE_ENVIRONMENTS.DEVELOPMENT && !config.isCacheEnabled) {
|
|
17005
|
-
|
|
17164
|
+
logger7.warn("Cache is disabled in development. This may impact performance testing.", {
|
|
17006
17165
|
field: "isCacheEnabled",
|
|
17007
17166
|
code: "DEVELOPMENT_CACHE_DISABLED"
|
|
17008
17167
|
});
|