moost 0.7.1 → 0.7.2

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/index.cjs CHANGED
@@ -48,7 +48,7 @@ let stamped = false;
48
48
  if (stamped) return;
49
49
  stamped = true;
50
50
  stampModuleIdentity({
51
- version: "0.7.1",
51
+ version: "0.7.2",
52
52
  path: typeof __filename === "string" ? __filename : require("url").pathToFileURL(__filename).href
53
53
  });
54
54
  }
@@ -136,7 +136,7 @@ function getDefaultLogger(topic) {
136
136
 
137
137
  //#endregion
138
138
  //#region packages/moost/src/event-scope.ts
139
- function _define_property$1(obj, key, value) {
139
+ function _define_property$2(obj, key, value) {
140
140
  if (key in obj) Object.defineProperty(obj, key, {
141
141
  value,
142
142
  enumerable: true,
@@ -232,7 +232,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
232
232
  super({
233
233
  logger: parent.logger,
234
234
  parent
235
- }), _define_property$1(this, "isolated", void 0), this.isolated = isolated;
235
+ }), _define_property$2(this, "isolated", void 0), this.isolated = isolated;
236
236
  }
237
237
  };
238
238
  /**
@@ -385,6 +385,16 @@ let sourceRefs = [];
385
385
 
386
386
  //#endregion
387
387
  //#region packages/moost/src/metadata/moost-metadata.ts
388
+ function _define_property$1(obj, key, value) {
389
+ if (key in obj) Object.defineProperty(obj, key, {
390
+ value,
391
+ enumerable: true,
392
+ configurable: true,
393
+ writable: true
394
+ });
395
+ else obj[key] = value;
396
+ return obj;
397
+ }
388
398
  const METADATA_WORKSPACE = "moost";
389
399
  /**
390
400
  * A param entry is "bare" when it carries nothing but the design-time type
@@ -394,7 +404,71 @@ const METADATA_WORKSPACE = "moost";
394
404
  */ function isBareParam(param) {
395
405
  return !param || Object.entries(param).every(([key, value]) => key === "type" || value === void 0);
396
406
  }
397
- const moostMate = new _prostojs_mate.Mate(METADATA_WORKSPACE, {
407
+ /**
408
+ * List keys that describe behaviour stacked on a class or method. Under
409
+ * `@Inherit()` they ACCUMULATE along `extends` (base entries first, then the
410
+ * subclass's own) instead of following the shallow own-wins merge — a subclass
411
+ * adding a guard must not silently drop the base's error mapping or guard.
412
+ * `authTransports` is written by `@Authenticate` (event-http) next to its
413
+ * interceptor entry and has to travel with it. Route `handlers`, params,
414
+ * `importController` (re-mounting would duplicate routes) and documentation
415
+ * lists (swagger tags/security, …) keep own-wins semantics.
416
+ */ const ACCUMULATED_KEYS = [
417
+ "interceptors",
418
+ "pipes",
419
+ "authTransports",
420
+ "properties",
421
+ "requiredProps"
422
+ ];
423
+ /**
424
+ * The identity an entry is deduplicated by when it appears on both levels: the
425
+ * `handler` reference for interceptor/pipe entries, the value itself otherwise.
426
+ */ function entryIdentity(entry) {
427
+ return entry?.handler ?? entry;
428
+ }
429
+ /**
430
+ * Inherited entries first, then the own ones. An own entry that re-declares an
431
+ * inherited one (same identity) takes the inherited entry's place.
432
+ */ function accumulate(inherited, own) {
433
+ const ownById = /* @__PURE__ */ new Map();
434
+ for (const entry of own) {
435
+ const id = entryIdentity(entry);
436
+ if (!ownById.has(id)) ownById.set(id, entry);
437
+ }
438
+ const result = [];
439
+ const placed = /* @__PURE__ */ new Set();
440
+ for (const entry of inherited) {
441
+ const id = entryIdentity(entry);
442
+ if (ownById.has(id)) {
443
+ placed.add(id);
444
+ result.push(ownById.get(id));
445
+ } else result.push(entry);
446
+ }
447
+ for (const entry of own) if (!placed.has(entryIdentity(entry))) result.push(entry);
448
+ return result;
449
+ }
450
+ const moostMate = new class MoostMate extends _prostojs_mate.Mate {
451
+ read(target, propKey) {
452
+ const result = super.read(target, propKey);
453
+ const meta = result;
454
+ if (!meta || this.settled.has(meta)) return result;
455
+ this.settled.add(meta);
456
+ const ctor = (0, _prostojs_mate.getConstructor)(target);
457
+ const own = Reflect.getOwnMetadata(this.workspace, typeof propKey === "string" ? ctor.prototype : ctor, propKey);
458
+ if (own && meta !== own) {
459
+ const inherited = this.read(Object.getPrototypeOf(ctor), propKey);
460
+ for (const key of ACCUMULATED_KEYS) {
461
+ const ownList = own[key];
462
+ const inheritedList = inherited?.[key];
463
+ if (Array.isArray(ownList) && Array.isArray(inheritedList) && inheritedList.length > 0) meta[key] = accumulate(inheritedList, ownList);
464
+ }
465
+ }
466
+ return result;
467
+ }
468
+ constructor(...args) {
469
+ super(...args), _define_property$1(this, "settled", /* @__PURE__ */ new WeakSet());
470
+ }
471
+ }(METADATA_WORKSPACE, {
398
472
  readType: true,
399
473
  readReturnType: true,
400
474
  collectPropKeys: true,
@@ -1366,6 +1440,12 @@ function fillLabel(target, key, index, name) {
1366
1440
  * overrides, which merge the parent's metadata under their own (so adding
1367
1441
  * e.g. a rate-limit decorator to an override does not unbind the parent's
1368
1442
  * `@Get`/`@Post` route).
1443
+ * - Exception to "own keys win" (since 0.7.2): interceptors (incl.
1444
+ * `@Authenticate` guards), pipes and prop decorators ACCUMULATE on the class
1445
+ * and on overridden methods, parent first. The same interceptor/pipe
1446
+ * *reference* on both levels runs once; a factory called on each level runs
1447
+ * twice. A subclass can't remove a base class's class-level interceptors.
1448
+ * Routes, params and `@ImportController` still replace.
1369
1449
  * - On a method/prop: enables inheritance for just that member.
1370
1450
  * - `@Inherit(false)` on an overridden member opts out of the merge for a
1371
1451
  * deliberate full replacement (the member keeps only its own metadata).
package/dist/index.d.ts CHANGED
@@ -1147,6 +1147,12 @@ declare function HandlerPaths(method?: string, opts?: TGetHandlerPathsOptions):
1147
1147
  * overrides, which merge the parent's metadata under their own (so adding
1148
1148
  * e.g. a rate-limit decorator to an override does not unbind the parent's
1149
1149
  * `@Get`/`@Post` route).
1150
+ * - Exception to "own keys win" (since 0.7.2): interceptors (incl.
1151
+ * `@Authenticate` guards), pipes and prop decorators ACCUMULATE on the class
1152
+ * and on overridden methods, parent first. The same interceptor/pipe
1153
+ * *reference* on both levels runs once; a factory called on each level runs
1154
+ * twice. A subclass can't remove a base class's class-level interceptors.
1155
+ * Routes, params and `@ImportController` still replace.
1150
1156
  * - On a method/prop: enables inheritance for just that member.
1151
1157
  * - `@Inherit(false)` on an overridden member opts out of the merge for a
1152
1158
  * deliberate full replacement (the member keeps only its own metadata).
package/dist/index.mjs CHANGED
@@ -47,7 +47,7 @@ let stamped = false;
47
47
  if (stamped) return;
48
48
  stamped = true;
49
49
  stampModuleIdentity({
50
- version: "0.7.1",
50
+ version: "0.7.2",
51
51
  path: typeof __filename === "string" ? __filename : import.meta.url
52
52
  });
53
53
  }
@@ -135,7 +135,7 @@ function getDefaultLogger(topic) {
135
135
 
136
136
  //#endregion
137
137
  //#region packages/moost/src/event-scope.ts
138
- function _define_property$1(obj, key, value) {
138
+ function _define_property$2(obj, key, value) {
139
139
  if (key in obj) Object.defineProperty(obj, key, {
140
140
  value,
141
141
  enumerable: true,
@@ -231,7 +231,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
231
231
  super({
232
232
  logger: parent.logger,
233
233
  parent
234
- }), _define_property$1(this, "isolated", void 0), this.isolated = isolated;
234
+ }), _define_property$2(this, "isolated", void 0), this.isolated = isolated;
235
235
  }
236
236
  };
237
237
  /**
@@ -384,6 +384,16 @@ let sourceRefs = [];
384
384
 
385
385
  //#endregion
386
386
  //#region packages/moost/src/metadata/moost-metadata.ts
387
+ function _define_property$1(obj, key, value) {
388
+ if (key in obj) Object.defineProperty(obj, key, {
389
+ value,
390
+ enumerable: true,
391
+ configurable: true,
392
+ writable: true
393
+ });
394
+ else obj[key] = value;
395
+ return obj;
396
+ }
387
397
  const METADATA_WORKSPACE = "moost";
388
398
  /**
389
399
  * A param entry is "bare" when it carries nothing but the design-time type
@@ -393,7 +403,71 @@ const METADATA_WORKSPACE = "moost";
393
403
  */ function isBareParam(param) {
394
404
  return !param || Object.entries(param).every(([key, value]) => key === "type" || value === void 0);
395
405
  }
396
- const moostMate = new Mate(METADATA_WORKSPACE, {
406
+ /**
407
+ * List keys that describe behaviour stacked on a class or method. Under
408
+ * `@Inherit()` they ACCUMULATE along `extends` (base entries first, then the
409
+ * subclass's own) instead of following the shallow own-wins merge — a subclass
410
+ * adding a guard must not silently drop the base's error mapping or guard.
411
+ * `authTransports` is written by `@Authenticate` (event-http) next to its
412
+ * interceptor entry and has to travel with it. Route `handlers`, params,
413
+ * `importController` (re-mounting would duplicate routes) and documentation
414
+ * lists (swagger tags/security, …) keep own-wins semantics.
415
+ */ const ACCUMULATED_KEYS = [
416
+ "interceptors",
417
+ "pipes",
418
+ "authTransports",
419
+ "properties",
420
+ "requiredProps"
421
+ ];
422
+ /**
423
+ * The identity an entry is deduplicated by when it appears on both levels: the
424
+ * `handler` reference for interceptor/pipe entries, the value itself otherwise.
425
+ */ function entryIdentity(entry) {
426
+ return entry?.handler ?? entry;
427
+ }
428
+ /**
429
+ * Inherited entries first, then the own ones. An own entry that re-declares an
430
+ * inherited one (same identity) takes the inherited entry's place.
431
+ */ function accumulate(inherited, own) {
432
+ const ownById = /* @__PURE__ */ new Map();
433
+ for (const entry of own) {
434
+ const id = entryIdentity(entry);
435
+ if (!ownById.has(id)) ownById.set(id, entry);
436
+ }
437
+ const result = [];
438
+ const placed = /* @__PURE__ */ new Set();
439
+ for (const entry of inherited) {
440
+ const id = entryIdentity(entry);
441
+ if (ownById.has(id)) {
442
+ placed.add(id);
443
+ result.push(ownById.get(id));
444
+ } else result.push(entry);
445
+ }
446
+ for (const entry of own) if (!placed.has(entryIdentity(entry))) result.push(entry);
447
+ return result;
448
+ }
449
+ const moostMate = new class MoostMate extends Mate {
450
+ read(target, propKey) {
451
+ const result = super.read(target, propKey);
452
+ const meta = result;
453
+ if (!meta || this.settled.has(meta)) return result;
454
+ this.settled.add(meta);
455
+ const ctor = getConstructor$1(target);
456
+ const own = Reflect.getOwnMetadata(this.workspace, typeof propKey === "string" ? ctor.prototype : ctor, propKey);
457
+ if (own && meta !== own) {
458
+ const inherited = this.read(Object.getPrototypeOf(ctor), propKey);
459
+ for (const key of ACCUMULATED_KEYS) {
460
+ const ownList = own[key];
461
+ const inheritedList = inherited?.[key];
462
+ if (Array.isArray(ownList) && Array.isArray(inheritedList) && inheritedList.length > 0) meta[key] = accumulate(inheritedList, ownList);
463
+ }
464
+ }
465
+ return result;
466
+ }
467
+ constructor(...args) {
468
+ super(...args), _define_property$1(this, "settled", /* @__PURE__ */ new WeakSet());
469
+ }
470
+ }(METADATA_WORKSPACE, {
397
471
  readType: true,
398
472
  readReturnType: true,
399
473
  collectPropKeys: true,
@@ -1365,6 +1439,12 @@ function fillLabel(target, key, index, name) {
1365
1439
  * overrides, which merge the parent's metadata under their own (so adding
1366
1440
  * e.g. a rate-limit decorator to an override does not unbind the parent's
1367
1441
  * `@Get`/`@Post` route).
1442
+ * - Exception to "own keys win" (since 0.7.2): interceptors (incl.
1443
+ * `@Authenticate` guards), pipes and prop decorators ACCUMULATE on the class
1444
+ * and on overridden methods, parent first. The same interceptor/pipe
1445
+ * *reference* on both levels runs once; a factory called on each level runs
1446
+ * twice. A subclass can't remove a base class's class-level interceptors.
1447
+ * Routes, params and `@ImportController` still replace.
1368
1448
  * - On a method/prop: enables inheritance for just that member.
1369
1449
  * - `@Inherit(false)` on an overridden member opts out of the merge for a
1370
1450
  * deliberate full replacement (the member keeps only its own metadata).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moost",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "moost",
5
5
  "keywords": [
6
6
  "composables",
@@ -49,7 +49,7 @@
49
49
  "@wooksjs/event-http": "^0.8.0",
50
50
  "@wooksjs/http-body": "^0.8.0",
51
51
  "vitest": "4.1.12",
52
- "@moostjs/event-http": "^0.7.1"
52
+ "@moostjs/event-http": "^0.7.2"
53
53
  },
54
54
  "scripts": {
55
55
  "pub": "pnpm publish --access public",