@xemahq/object-projection-nest 0.3.0 → 0.4.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/README.md +39 -3
- package/dist/projection/describe-objects.dto.d.ts +2 -2
- package/dist/projection/describe-objects.dto.d.ts.map +1 -1
- package/dist/projection/describe-objects.dto.js +2 -2
- package/dist/projection/describe-objects.dto.js.map +1 -1
- package/dist/projection/index.d.ts +1 -0
- package/dist/projection/index.d.ts.map +1 -1
- package/dist/projection/index.js +1 -0
- package/dist/projection/index.js.map +1 -1
- package/dist/projection/object-projection-publisher.service.d.ts +6 -2
- package/dist/projection/object-projection-publisher.service.d.ts.map +1 -1
- package/dist/projection/object-projection-publisher.service.js +22 -1
- package/dist/projection/object-projection-publisher.service.js.map +1 -1
- package/dist/projection/projection-digest.d.ts +3 -0
- package/dist/projection/projection-digest.d.ts.map +1 -0
- package/dist/projection/projection-digest.js +12 -0
- package/dist/projection/projection-digest.js.map +1 -0
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -11,7 +11,37 @@ surface that every XemaObject-owning service exposes so
|
|
|
11
11
|
| --- | --- |
|
|
12
12
|
| `GET /describe-objects` wire DTOs | `DescribeObjectsResponseDto`, `XemaObjectResponseDto`, `XemaSpaceRefDto`, `XemaSubjectRefDto` |
|
|
13
13
|
| CloudEvent descriptor factory | `defineObjectProjectionEvents(serviceName)` |
|
|
14
|
-
|
|
|
14
|
+
| change-driven publisher with reconcile-on-boot | `ObjectProjectionPublisherService` |
|
|
15
|
+
| the slice content digest it compares | `projectionEnvelopeDigest(envelope)` |
|
|
16
|
+
|
|
17
|
+
## Freshness model: reconcile on boot, publish on change
|
|
18
|
+
|
|
19
|
+
The publisher pushes the COMPLETE slice **unconditionally at boot** and
|
|
20
|
+
thereafter **only when the slice has actually changed**.
|
|
21
|
+
|
|
22
|
+
- **boot** — always publishes. A fresh process knows nothing about what the
|
|
23
|
+
registry currently holds for its source, so this is what repairs a slice
|
|
24
|
+
whose publish was dropped or failed before the last restart.
|
|
25
|
+
- **every `PROJECTION_REFRESH_INTERVAL_MS`** — builds the envelope, digests it
|
|
26
|
+
locally, and publishes *only* if the digest differs from the last
|
|
27
|
+
successfully published one. In a quiet hour this puts **nothing** on the bus.
|
|
28
|
+
- **`scheduleRepublish()`** — an optional per-write hook that collapses
|
|
29
|
+
detection latency from one interval to `PROJECTION_DEBOUNCE_MS`. It passes
|
|
30
|
+
the same digest gate, so a write that projects to identical content still
|
|
31
|
+
publishes nothing. Wiring one can only ever make a producer more responsive,
|
|
32
|
+
never noisier.
|
|
33
|
+
- **`publishProjection(Manual)`** — forced, like boot. "Force a resync" that
|
|
34
|
+
silently did nothing would be worse than the republish it saves.
|
|
35
|
+
|
|
36
|
+
The interval is a POLL, not a heartbeat, and it is deliberately still here:
|
|
37
|
+
most producers in the fleet wire no per-write hook, so for them it *is* the
|
|
38
|
+
change signal. Deleting it would leave them publishing at boot and never again
|
|
39
|
+
— the registry's cache would go stale on every write with nothing anywhere
|
|
40
|
+
reporting a failure.
|
|
41
|
+
|
|
42
|
+
The baseline is per PROCESS and in memory. Two replicas each publish once per
|
|
43
|
+
real change instead of once a minute each; the consumer applies an idempotent
|
|
44
|
+
REPLACE, so the duplicate costs nothing.
|
|
15
45
|
|
|
16
46
|
## Producer shape
|
|
17
47
|
|
|
@@ -65,5 +95,11 @@ subpath export, every consuming pod crashes at boot with
|
|
|
65
95
|
- A row that cannot be projected (missing scope qualifier, missing version)
|
|
66
96
|
MUST throw a typed error carrying the row id. Never skip it silently.
|
|
67
97
|
- The publisher logs and does not rethrow on transport failure — a
|
|
68
|
-
cache-refresh push must not crash its host. The
|
|
69
|
-
|
|
98
|
+
cache-refresh push must not crash its host. The next tick retries **because
|
|
99
|
+
the baseline advances only after `publish` resolves**, and the consumer can
|
|
100
|
+
always recover the same slice over the pull path.
|
|
101
|
+
- An ABSENT key and an EMPTY collection are different slices. The digest uses
|
|
102
|
+
the kernel's `canonicalJsonStringify`, which drops an `undefined` property
|
|
103
|
+
and keeps `[]`, so a producer that starts emitting an empty collection where
|
|
104
|
+
it previously omitted the key republishes once. That is correct, and it costs
|
|
105
|
+
nothing across a deploy because the boot publish re-seeds the baseline anyway.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ObjectLifecycle, XemaObjectKind } from '@xemahq/
|
|
2
|
-
import { SpaceKind } from '@xemahq/
|
|
1
|
+
import { ObjectLifecycle, XemaObjectKind } from '@xemahq/contracts/object';
|
|
2
|
+
import { SpaceKind } from '@xemahq/contracts/space';
|
|
3
3
|
export declare class XemaSubjectRefDto {
|
|
4
4
|
kind: string;
|
|
5
5
|
ref: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-objects.dto.d.ts","sourceRoot":"","sources":["../../src/projection/describe-objects.dto.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,cAAc,EACf,MAAM,
|
|
1
|
+
{"version":3,"file":"describe-objects.dto.d.ts","sourceRoot":"","sources":["../../src/projection/describe-objects.dto.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,cAAc,EACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAmBpD,qBAAa,iBAAiB;IAM5B,IAAI,EAAG,MAAM,CAAC;IAMd,GAAG,EAAG,MAAM,CAAC;CACd;AAQD,qBAAa,eAAe;IAO1B,IAAI,EAAG,SAAS,CAAC;IAGjB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,qBAAa,qBAAqB;IAKhC,GAAG,EAAG,MAAM,CAAC;IAOb,IAAI,EAAG,cAAc,CAAC;IAGtB,KAAK,EAAG,eAAe,CAAC;IAGxB,KAAK,EAAG,iBAAiB,CAAC;IAO1B,OAAO,EAAG,MAAM,CAAC;IAOjB,SAAS,EAAG,eAAe,CAAC;IAQ5B,OAAO,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAUD,qBAAa,0BAA0B;IAMrC,MAAM,EAAG,MAAM,CAAC;IAMhB,OAAO,EAAG,qBAAqB,EAAE,CAAC;CACnC"}
|
|
@@ -11,8 +11,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.DescribeObjectsResponseDto = exports.XemaObjectResponseDto = exports.XemaSpaceRefDto = exports.XemaSubjectRefDto = void 0;
|
|
13
13
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
-
const object_1 = require("@xemahq/
|
|
15
|
-
const space_1 = require("@xemahq/
|
|
14
|
+
const object_1 = require("@xemahq/contracts/object");
|
|
15
|
+
const space_1 = require("@xemahq/contracts/space");
|
|
16
16
|
class XemaSubjectRefDto {
|
|
17
17
|
kind;
|
|
18
18
|
ref;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-objects.dto.js","sourceRoot":"","sources":["../../src/projection/describe-objects.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA8C;AAC9C,
|
|
1
|
+
{"version":3,"file":"describe-objects.dto.js","sourceRoot":"","sources":["../../src/projection/describe-objects.dto.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/projection/index.ts"],"names":[],"mappings":"AAiBA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uCAAuC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/projection/index.ts"],"names":[],"mappings":"AAiBA,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uCAAuC,CAAC"}
|
package/dist/projection/index.js
CHANGED
|
@@ -16,5 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./describe-objects.dto"), exports);
|
|
18
18
|
__exportStar(require("./projection-events"), exports);
|
|
19
|
+
__exportStar(require("./projection-digest"), exports);
|
|
19
20
|
__exportStar(require("./object-projection-publisher.service"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/projection/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAiBA,yDAAuC;AACvC,sDAAoC;AACpC,wEAAsD"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/projection/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAiBA,yDAAuC;AACvC,sDAAoC;AACpC,sDAAoC;AACpC,wEAAsD"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Logger, type OnApplicationBootstrap, type OnApplicationShutdown } from '@nestjs/common';
|
|
2
|
-
import type { DescribeObjectsResponseDto } from './describe-objects.dto';
|
|
3
2
|
import type { ObjectProjectionPublishedDescriptor } from './projection-events';
|
|
4
3
|
import type { DescriptorEventPublisherService } from '@xemahq/events/nest';
|
|
5
4
|
export declare const PROJECTION_DEBOUNCE_MS = 1000;
|
|
@@ -10,10 +9,14 @@ export declare enum ObjectProjectionPublishReason {
|
|
|
10
9
|
Manual = "manual",
|
|
11
10
|
Change = "change"
|
|
12
11
|
}
|
|
12
|
+
export interface ObjectProjectionEnvelope {
|
|
13
|
+
readonly source: string;
|
|
14
|
+
readonly objects: readonly unknown[];
|
|
15
|
+
}
|
|
13
16
|
export interface ObjectProjectionPublisherOptions {
|
|
14
17
|
readonly source: string;
|
|
15
18
|
readonly descriptor: ObjectProjectionPublishedDescriptor;
|
|
16
|
-
buildEnvelope(): Promise<
|
|
19
|
+
buildEnvelope(): Promise<ObjectProjectionEnvelope>;
|
|
17
20
|
}
|
|
18
21
|
export declare abstract class ObjectProjectionPublisherService implements OnApplicationBootstrap, OnApplicationShutdown {
|
|
19
22
|
private readonly publisher;
|
|
@@ -22,6 +25,7 @@ export declare abstract class ObjectProjectionPublisherService implements OnAppl
|
|
|
22
25
|
private timer;
|
|
23
26
|
private debounceTimer;
|
|
24
27
|
private publishing;
|
|
28
|
+
private lastPublishedDigest;
|
|
25
29
|
protected constructor(publisher: DescriptorEventPublisherService, options: ObjectProjectionPublisherOptions);
|
|
26
30
|
onApplicationBootstrap(): Promise<void>;
|
|
27
31
|
onApplicationShutdown(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-projection-publisher.service.d.ts","sourceRoot":"","sources":["../../src/projection/object-projection-publisher.service.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"object-projection-publisher.service.d.ts","sourceRoot":"","sources":["../../src/projection/object-projection-publisher.service.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,KAAK,EACV,+BAA+B,EAEhC,MAAM,qBAAqB,CAAC;AAO7B,eAAO,MAAM,sBAAsB,OAAQ,CAAC;AAoB5C,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAMrD,oBAAY,6BAA6B;IACvC,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AA0CD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;CACtC;AAKD,MAAM,WAAW,gCAAgC;IAO/C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAMxB,QAAQ,CAAC,UAAU,EAAE,mCAAmC,CAAC;IAmBzD,aAAa,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACpD;AAuED,8BAAsB,gCACpB,YAAW,sBAAsB,EAAE,qBAAqB;IAmBtD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAlB1B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAElC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAAS;IAU3B,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,SAAS,aACU,SAAS,EAAE,+BAA+B,EAC1C,OAAO,EAAE,gCAAgC;IAOtD,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB7C,qBAAqB,IAAI,IAAI;IAyB7B,SAAS,CAAC,iBAAiB,IAAI,IAAI;IA4B7B,iBAAiB,CACrB,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,IAAI,CAAC;IA+FhB,OAAO,CAAC,eAAe;CAQxB"}
|
|
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ObjectProjectionPublisherService = exports.ObjectProjectionPublishReason = exports.PROJECTION_REFRESH_INTERVAL_MS = exports.PROJECTION_DEBOUNCE_MS = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const common_1 = require("@nestjs/common");
|
|
6
|
+
const tenant_1 = require("@xemahq/contracts/tenant");
|
|
6
7
|
const events_1 = require("@xemahq/events");
|
|
7
|
-
const
|
|
8
|
+
const projection_digest_1 = require("./projection-digest");
|
|
8
9
|
exports.PROJECTION_DEBOUNCE_MS = 1_000;
|
|
9
10
|
exports.PROJECTION_REFRESH_INTERVAL_MS = 60_000;
|
|
10
11
|
var ObjectProjectionPublishReason;
|
|
@@ -14,6 +15,16 @@ var ObjectProjectionPublishReason;
|
|
|
14
15
|
ObjectProjectionPublishReason["Manual"] = "manual";
|
|
15
16
|
ObjectProjectionPublishReason["Change"] = "change";
|
|
16
17
|
})(ObjectProjectionPublishReason || (exports.ObjectProjectionPublishReason = ObjectProjectionPublishReason = {}));
|
|
18
|
+
function publishesUnconditionally(reason) {
|
|
19
|
+
switch (reason) {
|
|
20
|
+
case ObjectProjectionPublishReason.Boot:
|
|
21
|
+
case ObjectProjectionPublishReason.Manual:
|
|
22
|
+
return true;
|
|
23
|
+
case ObjectProjectionPublishReason.Periodic:
|
|
24
|
+
case ObjectProjectionPublishReason.Change:
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
17
28
|
class ObjectProjectionPublisherService {
|
|
18
29
|
publisher;
|
|
19
30
|
options;
|
|
@@ -21,6 +32,7 @@ class ObjectProjectionPublisherService {
|
|
|
21
32
|
timer;
|
|
22
33
|
debounceTimer;
|
|
23
34
|
publishing = false;
|
|
35
|
+
lastPublishedDigest;
|
|
24
36
|
constructor(publisher, options) {
|
|
25
37
|
this.publisher = publisher;
|
|
26
38
|
this.options = options;
|
|
@@ -65,7 +77,16 @@ class ObjectProjectionPublisherService {
|
|
|
65
77
|
throw new Error(`Projection envelope source "${envelope.source}" does not match ` +
|
|
66
78
|
`the configured publisher source "${this.options.source}".`);
|
|
67
79
|
}
|
|
80
|
+
const digest = (0, projection_digest_1.projectionEnvelopeDigest)(envelope);
|
|
81
|
+
if (!publishesUnconditionally(reason) &&
|
|
82
|
+
digest === this.lastPublishedDigest) {
|
|
83
|
+
this.logger.log(`Unchanged ${this.options.descriptor.type} ` +
|
|
84
|
+
`reason=${reason} source=${envelope.source} ` +
|
|
85
|
+
`objectCount=${envelope.objects.length} — nothing published`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
68
88
|
await this.publisher.publish(this.options.descriptor, envelope, this.platformContext(), {});
|
|
89
|
+
this.lastPublishedDigest = digest;
|
|
69
90
|
this.logger.log(`Published ${this.options.descriptor.type} ` +
|
|
70
91
|
`reason=${reason} source=${envelope.source} ` +
|
|
71
92
|
`objectCount=${envelope.objects.length}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-projection-publisher.service.js","sourceRoot":"","sources":["../../src/projection/object-projection-publisher.service.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AAEzC,2CAIwB;AACxB,2CAA2C;
|
|
1
|
+
{"version":3,"file":"object-projection-publisher.service.js","sourceRoot":"","sources":["../../src/projection/object-projection-publisher.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection-digest.d.ts","sourceRoot":"","sources":["../../src/projection/projection-digest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AA+DtF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,wBAAwB,GACjC,MAAM,CAKR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projectionEnvelopeDigest = projectionEnvelopeDigest;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const content_address_1 = require("@xemahq/contracts/content-address");
|
|
6
|
+
function projectionEnvelopeDigest(envelope) {
|
|
7
|
+
const wire = JSON.parse(JSON.stringify(envelope));
|
|
8
|
+
return (0, node_crypto_1.createHash)('sha256')
|
|
9
|
+
.update((0, content_address_1.canonicalJsonStringify)(wire), 'utf8')
|
|
10
|
+
.digest('hex');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=projection-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection-digest.js","sourceRoot":"","sources":["../../src/projection/projection-digest.ts"],"names":[],"mappings":";;AAmEA,4DAOC;AA1ED,6CAAyC;AAEzC,uEAA2E;AAiE3E,SAAgB,wBAAwB,CACtC,QAAkC;IAElC,MAAM,IAAI,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3D,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,IAAA,wCAAsB,EAAC,IAAI,CAAC,EAAE,MAAM,CAAC;SAC5C,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/object-projection-nest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared NestJS building blocks for the XSI plane-1 object projection surface (`GET /describe-objects` + the `xema.object-registry.projection.published.v1` CloudEvent) that every XemaObject-owning service implements.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -14,23 +14,22 @@
|
|
|
14
14
|
"peerDependencies": {
|
|
15
15
|
"@nestjs/common": ">=11.0.0",
|
|
16
16
|
"@nestjs/swagger": ">=11.0.0",
|
|
17
|
-
"@xemahq/events": "^0.
|
|
18
|
-
"@xemahq/
|
|
17
|
+
"@xemahq/events": "^0.11.0",
|
|
18
|
+
"@xemahq/contracts": "^0.1.0",
|
|
19
19
|
"zod": "^4.3.6"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@eslint/js": "^9.39.4",
|
|
23
22
|
"@nestjs/common": "11.1.18",
|
|
24
23
|
"@nestjs/swagger": "11.2.6",
|
|
24
|
+
"@types/jest": "^30.0.0",
|
|
25
25
|
"@types/node": "25.2.3",
|
|
26
|
-
"@xemahq/
|
|
27
|
-
"@xemahq/
|
|
26
|
+
"@xemahq/eslint-config": "^0.5.0",
|
|
27
|
+
"@xemahq/events": "^0.11.0",
|
|
28
|
+
"@xemahq/contracts": "^0.1.0",
|
|
28
29
|
"eslint": "^9.39.4",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"eslint-plugin-unused-imports": "^4.4.1",
|
|
30
|
+
"jest": "^30.3.0",
|
|
31
|
+
"ts-jest": "^29.4.9",
|
|
32
32
|
"typescript": "5.9.3",
|
|
33
|
-
"typescript-eslint": "^8.56.1",
|
|
34
33
|
"zod": "^4.3.6"
|
|
35
34
|
},
|
|
36
35
|
"exports": {
|
|
@@ -56,8 +55,9 @@
|
|
|
56
55
|
},
|
|
57
56
|
"scripts": {
|
|
58
57
|
"clean": "rm -rf dist",
|
|
59
|
-
"build": "tsc -p tsconfig.json",
|
|
58
|
+
"build": "tsc -p tsconfig.build.json",
|
|
60
59
|
"lint": "eslint .",
|
|
60
|
+
"test": "jest --config jest.config.ts",
|
|
61
61
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
62
62
|
}
|
|
63
63
|
}
|