@sumaris-net/ngx-components 18.14.1 → 18.14.3
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/esm2022/src/app/shared/rx-state/rx-state.decorators.mjs +64 -121
- package/esm2022/src/app/social/feed/discourse/discourse-feed.service.mjs +10 -22
- package/fesm2022/sumaris-net.ngx-components.mjs +72 -139
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/app/shared/rx-state/rx-state.decorators.d.ts +1 -17
- package/src/app/social/feed/discourse/discourse-feed.service.d.ts +2 -2
|
@@ -26365,22 +26365,16 @@ class DecoratorUtils {
|
|
|
26365
26365
|
static createPropertyName(prefix, propertyKey) {
|
|
26366
26366
|
return `${prefix}${this.capitalize(propertyKey)}`;
|
|
26367
26367
|
}
|
|
26368
|
-
static validateStateProperty(target,
|
|
26369
|
-
if (!production &&
|
|
26370
|
-
|
|
26371
|
-
if (!${stateVarName}) {
|
|
26372
|
-
throw new Error('Missing state! Please add a RxState in class: ' + this.constructor.name);
|
|
26368
|
+
static validateStateProperty(target, stateObject) {
|
|
26369
|
+
if (!production && !stateObject) {
|
|
26370
|
+
throw new Error(`Missing state! Please add a RxState in class: ${target.constructor.name}`);
|
|
26373
26371
|
}
|
|
26374
|
-
`;
|
|
26375
|
-
}
|
|
26376
|
-
return '';
|
|
26377
26372
|
}
|
|
26378
26373
|
}
|
|
26379
26374
|
const STATE_VAR_NAME_KEY = '__stateName';
|
|
26380
26375
|
const DEFAULT_STATE_VAR_NAME = '_state';
|
|
26381
26376
|
/**
|
|
26382
26377
|
* Decorator to register the RxState property in a component
|
|
26383
|
-
* Must be used once per class hierarchy
|
|
26384
26378
|
*/
|
|
26385
26379
|
function RxStateRegister() {
|
|
26386
26380
|
return function (target, key) {
|
|
@@ -26397,49 +26391,36 @@ function RxStateRegister() {
|
|
|
26397
26391
|
}
|
|
26398
26392
|
/**
|
|
26399
26393
|
* Decorator for RxState properties with getter/setter access
|
|
26400
|
-
* Creates reactive properties that sync with RxState
|
|
26401
26394
|
*/
|
|
26402
26395
|
function RxStateProperty(statePropertyName, projectValueReducer) {
|
|
26403
26396
|
return function (target, key) {
|
|
26404
|
-
// Vérification de type au runtime (optionnelle)
|
|
26405
|
-
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
26406
|
-
if (descriptor && typeof descriptor.value !== 'undefined') {
|
|
26407
|
-
// On peut ajouter ici des vérifications de type runtime si nécessaire
|
|
26408
|
-
}
|
|
26409
26397
|
const finalStatePropertyName = statePropertyName || key;
|
|
26410
26398
|
const stateVarName = target instanceof RxState ? null : target[STATE_VAR_NAME_KEY] || DEFAULT_STATE_VAR_NAME;
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
const
|
|
26414
|
-
const setMethodName = DecoratorUtils.createMethodName('_set', key);
|
|
26415
|
-
const reducerMethodName = DecoratorUtils.createMethodName('_reduce', key);
|
|
26416
|
-
// State validation (only in development)
|
|
26417
|
-
const stateValidation = DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26418
|
-
// Create reducer logic
|
|
26419
|
-
const reducerLogic = projectValueReducer ? `(state) => this.${reducerMethodName}(state, value)` : '() => value';
|
|
26420
|
-
// Create dynamic methods using Function constructor for better performance
|
|
26421
|
-
const getter = new Function(`
|
|
26422
|
-
return function ${getMethodName}() {
|
|
26423
|
-
${stateValidation}
|
|
26424
|
-
return ${stateObject}.get('${finalStatePropertyName}');
|
|
26425
|
-
}
|
|
26426
|
-
`)();
|
|
26427
|
-
const setter = new Function(`
|
|
26428
|
-
return function ${setMethodName}(value) {
|
|
26429
|
-
${stateValidation}
|
|
26430
|
-
${stateObject}.set('${finalStatePropertyName}', ${reducerLogic});
|
|
26431
|
-
}
|
|
26432
|
-
`)();
|
|
26433
|
-
// Attach methods to prototype
|
|
26434
|
-
target[getMethodName] = getter;
|
|
26435
|
-
target[setMethodName] = setter;
|
|
26436
|
-
if (projectValueReducer) {
|
|
26437
|
-
target[reducerMethodName] = projectValueReducer;
|
|
26438
|
-
}
|
|
26399
|
+
// Create unique property names to avoid conflicts
|
|
26400
|
+
const privateValueKey = `__${key}_value`;
|
|
26401
|
+
const privateInitializedKey = `__${key}_initialized`;
|
|
26439
26402
|
// Define property with getter/setter
|
|
26440
26403
|
Object.defineProperty(target, key, {
|
|
26441
|
-
get:
|
|
26442
|
-
|
|
26404
|
+
get: function () {
|
|
26405
|
+
const stateObject = stateVarName ? this[stateVarName] : this;
|
|
26406
|
+
DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26407
|
+
if (!this[privateInitializedKey]) {
|
|
26408
|
+
this[privateValueKey] = stateObject.get(finalStatePropertyName);
|
|
26409
|
+
this[privateInitializedKey] = true;
|
|
26410
|
+
}
|
|
26411
|
+
return this[privateValueKey];
|
|
26412
|
+
},
|
|
26413
|
+
set: function (value) {
|
|
26414
|
+
const stateObject = stateVarName ? this[stateVarName] : this;
|
|
26415
|
+
DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26416
|
+
this[privateValueKey] = value;
|
|
26417
|
+
if (projectValueReducer) {
|
|
26418
|
+
stateObject.set(finalStatePropertyName, (state) => projectValueReducer(state, value));
|
|
26419
|
+
}
|
|
26420
|
+
else {
|
|
26421
|
+
stateObject.set(finalStatePropertyName, () => value);
|
|
26422
|
+
}
|
|
26423
|
+
},
|
|
26443
26424
|
enumerable: true,
|
|
26444
26425
|
configurable: true,
|
|
26445
26426
|
});
|
|
@@ -26451,117 +26432,79 @@ function RxStateProperty(statePropertyName, projectValueReducer) {
|
|
|
26451
26432
|
}
|
|
26452
26433
|
/**
|
|
26453
26434
|
* Decorator for RxState observable selectors
|
|
26454
|
-
* Creates observable properties that select from RxState
|
|
26455
|
-
*
|
|
26456
|
-
* ⚠️ IMPORTANT: La propriété décorée DOIT être typée comme Observable<T>
|
|
26457
|
-
*
|
|
26458
|
-
* @example
|
|
26459
|
-
* ```typescript
|
|
26460
|
-
* @RxStateSelect()
|
|
26461
|
-
* protected pmfms$: Observable<IPmfm[]>; // ✅ Correct
|
|
26462
|
-
*
|
|
26463
|
-
* @RxStateSelect()
|
|
26464
|
-
* protected badProperty: boolean; // ❌ TypeScript Error
|
|
26465
|
-
* ```
|
|
26466
26435
|
*/
|
|
26467
26436
|
function RxStateSelect(statePropertyName, opts) {
|
|
26468
26437
|
return function (target, key) {
|
|
26469
|
-
//
|
|
26438
|
+
// Convention check
|
|
26470
26439
|
if (!production && !key.endsWith('$')) {
|
|
26471
26440
|
console.warn(`[RxStateSelect] Convention: Property ${target.constructor?.name}.${key} should end with '$' to indicate it's an Observable`);
|
|
26472
26441
|
}
|
|
26473
|
-
// Determine state property name
|
|
26442
|
+
// Determine state property name
|
|
26474
26443
|
const finalStatePropertyName = statePropertyName || key.replace(/\$$/, '');
|
|
26475
26444
|
// Determine state object
|
|
26476
26445
|
const stateVarName = target instanceof RxState ? null : target[STATE_VAR_NAME_KEY] || opts?.stateName || DEFAULT_STATE_VAR_NAME;
|
|
26477
|
-
const stateObject = stateVarName ? `this.${stateVarName}` : 'this';
|
|
26478
26446
|
// Create cache property name
|
|
26479
|
-
const cachePropertyName = `
|
|
26480
|
-
// Generate method name
|
|
26481
|
-
const getMethodName = DecoratorUtils.createMethodName('_get', key.replace(/\$$/, '') + '$');
|
|
26482
|
-
// Create observable selector logic
|
|
26483
|
-
const observableSelector = finalStatePropertyName === '$'
|
|
26484
|
-
? `${stateObject}.$`
|
|
26485
|
-
: finalStatePropertyName.includes('.')
|
|
26486
|
-
? `${stateObject}.select('${finalStatePropertyName.split('.').join("', '")}')`
|
|
26487
|
-
: `${stateObject}.select('${finalStatePropertyName}')`;
|
|
26488
|
-
// State validation
|
|
26489
|
-
const stateValidation = DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26490
|
-
// Create getter with caching
|
|
26491
|
-
const getter = new Function(`
|
|
26492
|
-
return function ${getMethodName}() {
|
|
26493
|
-
${stateValidation}
|
|
26494
|
-
if (!this.${cachePropertyName}) {
|
|
26495
|
-
this.${cachePropertyName} = ${observableSelector};
|
|
26496
|
-
}
|
|
26497
|
-
return this.${cachePropertyName};
|
|
26498
|
-
}
|
|
26499
|
-
`)();
|
|
26500
|
-
// Attach method to prototype
|
|
26501
|
-
target[getMethodName] = getter;
|
|
26447
|
+
const cachePropertyName = `__${key}_cache`;
|
|
26502
26448
|
// Define property with getter only
|
|
26503
26449
|
Object.defineProperty(target, key, {
|
|
26504
|
-
get:
|
|
26450
|
+
get: function () {
|
|
26451
|
+
const stateObject = stateVarName ? this[stateVarName] : this;
|
|
26452
|
+
DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26453
|
+
if (!this[cachePropertyName]) {
|
|
26454
|
+
if (finalStatePropertyName === '$') {
|
|
26455
|
+
this[cachePropertyName] = stateObject.$;
|
|
26456
|
+
}
|
|
26457
|
+
else if (finalStatePropertyName.includes('.')) {
|
|
26458
|
+
const path = finalStatePropertyName.split('.');
|
|
26459
|
+
this[cachePropertyName] = stateObject.select(...path);
|
|
26460
|
+
}
|
|
26461
|
+
else {
|
|
26462
|
+
this[cachePropertyName] = stateObject.select(finalStatePropertyName);
|
|
26463
|
+
}
|
|
26464
|
+
}
|
|
26465
|
+
return this[cachePropertyName];
|
|
26466
|
+
},
|
|
26505
26467
|
enumerable: true,
|
|
26506
26468
|
configurable: false,
|
|
26507
26469
|
});
|
|
26508
26470
|
// Development logging
|
|
26509
26471
|
if (!production) {
|
|
26510
|
-
console.debug(`[RxStateSelect] ${target.constructor?.name}.${key} -> ${
|
|
26472
|
+
console.debug(`[RxStateSelect] ${target.constructor?.name}.${key} -> state.select('${finalStatePropertyName}')`);
|
|
26511
26473
|
}
|
|
26512
26474
|
};
|
|
26513
26475
|
}
|
|
26514
26476
|
/**
|
|
26515
26477
|
* Utility decorator to create computed observables from state
|
|
26516
|
-
*
|
|
26517
|
-
* ⚠️ IMPORTANT: La propriété décorée DOIT être typée comme Observable<T>
|
|
26518
26478
|
*/
|
|
26519
26479
|
function RxStateComputed(dependencies, computeFn, opts) {
|
|
26520
26480
|
return function (target, key) {
|
|
26521
|
-
//
|
|
26481
|
+
// Convention check
|
|
26522
26482
|
if (!production && !key.endsWith('$')) {
|
|
26523
26483
|
console.warn(`[RxStateComputed] Convention: Property ${target.constructor?.name}.${key} should end with '$' to indicate it's an Observable`);
|
|
26524
26484
|
}
|
|
26525
26485
|
const stateVarName = target instanceof RxState ? null : target[STATE_VAR_NAME_KEY] || opts?.stateName || DEFAULT_STATE_VAR_NAME;
|
|
26526
|
-
const
|
|
26527
|
-
const cachePropertyName = `_${key}`;
|
|
26528
|
-
const getMethodName = DecoratorUtils.createMethodName('_get', key.replace(/\$$/, '') + '$');
|
|
26529
|
-
const computeMethodName = DecoratorUtils.createMethodName('_compute', key);
|
|
26530
|
-
const keyCompareMapPropertyName = DecoratorUtils.createPropertyName(`_compareMap`, key);
|
|
26531
|
-
// State validation
|
|
26532
|
-
const stateValidation = DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26533
|
-
// Create dependencies array as string for code generation
|
|
26534
|
-
const dependenciesStr = dependencies.map((dep) => `'${dep}'`).join(', ');
|
|
26535
|
-
// Create the compute method as string, for code generation
|
|
26536
|
-
const computeMethodNameStr = computeFn ? `, (slice) => this.${computeMethodName}(slice)` : '';
|
|
26537
|
-
// Create the comparator map function as string, for code generation
|
|
26538
|
-
const keyCompareMapStr = opts?.keyCompareMap ? `, this.${keyCompareMapPropertyName}` : '';
|
|
26539
|
-
// Create getter with caching using RxState's native multi-select + pipe(map())
|
|
26540
|
-
const getter = new Function(`
|
|
26541
|
-
return function ${getMethodName}() {
|
|
26542
|
-
${stateValidation}
|
|
26543
|
-
if (!this.${cachePropertyName}) {
|
|
26544
|
-
const { map } = require('rxjs/operators');
|
|
26545
|
-
this.${cachePropertyName} = ${stateObject}.select([${dependenciesStr}]${computeMethodNameStr}${keyCompareMapStr});
|
|
26546
|
-
}
|
|
26547
|
-
return this.${cachePropertyName};
|
|
26548
|
-
}
|
|
26549
|
-
`)();
|
|
26550
|
-
// Attach compute method, optional keyCompareMap with unique name, and getter to prototype
|
|
26551
|
-
if (computeFn)
|
|
26552
|
-
target[computeMethodName] = computeFn;
|
|
26553
|
-
if (opts?.keyCompareMap)
|
|
26554
|
-
target[keyCompareMapPropertyName] = opts.keyCompareMap;
|
|
26555
|
-
target[getMethodName] = getter;
|
|
26486
|
+
const cachePropertyName = `__${key}_cache`;
|
|
26556
26487
|
// Define property with getter only
|
|
26557
26488
|
Object.defineProperty(target, key, {
|
|
26558
|
-
get:
|
|
26489
|
+
get: function () {
|
|
26490
|
+
const stateObject = stateVarName ? this[stateVarName] : this;
|
|
26491
|
+
DecoratorUtils.validateStateProperty(target, stateObject);
|
|
26492
|
+
if (!this[cachePropertyName]) {
|
|
26493
|
+
let observable = stateObject.select(dependencies, opts?.keyCompareMap);
|
|
26494
|
+
if (computeFn) {
|
|
26495
|
+
const { map } = require('rxjs/operators');
|
|
26496
|
+
observable = observable.pipe(map(computeFn));
|
|
26497
|
+
}
|
|
26498
|
+
this[cachePropertyName] = observable;
|
|
26499
|
+
}
|
|
26500
|
+
return this[cachePropertyName];
|
|
26501
|
+
},
|
|
26559
26502
|
enumerable: true,
|
|
26560
26503
|
configurable: false,
|
|
26561
26504
|
});
|
|
26562
26505
|
// Development logging
|
|
26563
26506
|
if (!production) {
|
|
26564
|
-
console.debug(`[RxStateComputed] ${target.constructor?.name}.${key} ->
|
|
26507
|
+
console.debug(`[RxStateComputed] ${target.constructor?.name}.${key} -> state.select([${dependencies.map((d) => `'${d}'`).join(', ')}])`);
|
|
26565
26508
|
}
|
|
26566
26509
|
};
|
|
26567
26510
|
}
|
|
@@ -44815,10 +44758,14 @@ class DiscourseFeedService extends StartableService {
|
|
|
44815
44758
|
_logPrefix = '[discourse-feed-service] ';
|
|
44816
44759
|
_state = new RxState();
|
|
44817
44760
|
network = inject(NetworkService);
|
|
44818
|
-
locale
|
|
44819
|
-
feedUrls
|
|
44820
|
-
|
|
44821
|
-
|
|
44761
|
+
locale$ = this._state.select('locale');
|
|
44762
|
+
feedUrls$ = this._state.select('feedUrls');
|
|
44763
|
+
get feedUrls() {
|
|
44764
|
+
return this._state.get('feedUrls');
|
|
44765
|
+
}
|
|
44766
|
+
set feedUrls(urls) {
|
|
44767
|
+
this._state.set('feedUrls', () => urls);
|
|
44768
|
+
}
|
|
44822
44769
|
constructor(settings, environment) {
|
|
44823
44770
|
super(settings);
|
|
44824
44771
|
this.settings = settings;
|
|
@@ -44831,10 +44778,8 @@ class DiscourseFeedService extends StartableService {
|
|
|
44831
44778
|
}
|
|
44832
44779
|
async ngOnStart() {
|
|
44833
44780
|
await this.settings.ready();
|
|
44834
|
-
console.debug(`${this._logPrefix}Service started`, this.settings.locale, this.feedUrls);
|
|
44835
44781
|
return {
|
|
44836
44782
|
locale: this.settings.locale,
|
|
44837
|
-
feedUrls: this.feedUrls,
|
|
44838
44783
|
};
|
|
44839
44784
|
}
|
|
44840
44785
|
watchAll(opts) {
|
|
@@ -44947,18 +44892,6 @@ class DiscourseFeedService extends StartableService {
|
|
|
44947
44892
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DiscourseFeedService, deps: [{ token: LocalSettingsService }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
44948
44893
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DiscourseFeedService, providedIn: 'root' });
|
|
44949
44894
|
}
|
|
44950
|
-
__decorate([
|
|
44951
|
-
RxStateSelect()
|
|
44952
|
-
], DiscourseFeedService.prototype, "locale$", void 0);
|
|
44953
|
-
__decorate([
|
|
44954
|
-
RxStateSelect()
|
|
44955
|
-
], DiscourseFeedService.prototype, "feedUrls$", void 0);
|
|
44956
|
-
__decorate([
|
|
44957
|
-
RxStateProperty()
|
|
44958
|
-
], DiscourseFeedService.prototype, "locale", void 0);
|
|
44959
|
-
__decorate([
|
|
44960
|
-
RxStateProperty()
|
|
44961
|
-
], DiscourseFeedService.prototype, "feedUrls", void 0);
|
|
44962
44895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DiscourseFeedService, decorators: [{
|
|
44963
44896
|
type: Injectable,
|
|
44964
44897
|
args: [{ providedIn: 'root' }]
|
|
@@ -44967,7 +44900,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
44967
44900
|
}, {
|
|
44968
44901
|
type: Inject,
|
|
44969
44902
|
args: [ENVIRONMENT]
|
|
44970
|
-
}] }]
|
|
44903
|
+
}] }] });
|
|
44971
44904
|
|
|
44972
44905
|
const PersonFragments = {
|
|
44973
44906
|
person: gql$1 `
|