@rytass/wms-module-graphql 0.10.1 → 0.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.
Files changed (58) hide show
  1. package/index.cjs.js +1017 -114
  2. package/lib/dto/consumption-order-item.dto.d.ts +17 -0
  3. package/lib/dto/consumption-order-item.dto.js +43 -0
  4. package/lib/dto/consumption-order.dto.d.ts +14 -0
  5. package/lib/dto/consumption-order.dto.js +52 -0
  6. package/lib/dto/index.d.ts +3 -0
  7. package/lib/dto/inventory-count-order.dto.d.ts +7 -1
  8. package/lib/dto/inventory-count-order.dto.js +11 -1
  9. package/lib/dto/order-reference.dto.d.ts +22 -0
  10. package/lib/dto/order-reference.dto.js +73 -0
  11. package/lib/dto/stock.dto.d.ts +15 -0
  12. package/lib/dto/stock.dto.js +28 -0
  13. package/lib/events/operation-result-map.d.ts +13 -0
  14. package/lib/events/typed-maps.d.ts +17 -7
  15. package/lib/events/wms-mutation.interceptor.d.ts +11 -9
  16. package/lib/events/wms-mutation.interceptor.js +19 -45
  17. package/lib/graphql.module.d.ts +1 -1
  18. package/lib/graphql.module.js +30 -13
  19. package/lib/inputs/consumption-order.args.d.ts +47 -0
  20. package/lib/inputs/consumption-order.args.js +182 -0
  21. package/lib/inputs/find-stock.args.d.ts +6 -0
  22. package/lib/inputs/find-stock.args.js +10 -0
  23. package/lib/inputs/order-reference.args.d.ts +32 -0
  24. package/lib/inputs/order-reference.args.js +103 -0
  25. package/lib/inputs/split-batch.args.d.ts +6 -0
  26. package/lib/inputs/split-batch.args.js +11 -0
  27. package/lib/mutations/consumption-order.mutation.d.ts +18 -0
  28. package/lib/mutations/consumption-order.mutation.js +90 -0
  29. package/lib/mutations/loader.mutation.js +3 -0
  30. package/lib/mutations/material.mutation.js +3 -0
  31. package/lib/mutations/order-reference.mutation.d.ts +13 -0
  32. package/lib/mutations/order-reference.mutation.js +57 -0
  33. package/lib/mutations/receive-inventory-order.mutation.js +3 -0
  34. package/lib/mutations/ship-inventory-order.mutation.js +3 -0
  35. package/lib/queries/consumption-order.query.d.ts +9 -0
  36. package/lib/queries/consumption-order.query.js +45 -0
  37. package/lib/queries/loader.query.js +4 -3
  38. package/lib/queries/material.query.js +3 -0
  39. package/lib/queries/order-reference.query.d.ts +8 -0
  40. package/lib/queries/order-reference.query.js +34 -0
  41. package/lib/queries/recieve-inventory-order.query.js +3 -0
  42. package/lib/queries/ship-inventory-order.query.js +3 -0
  43. package/lib/queries/stock.query.js +4 -5
  44. package/lib/resolvers/aggregated-stock.resolver.js +3 -0
  45. package/lib/resolvers/change-log.resolver.js +3 -0
  46. package/lib/resolvers/consumption-order.resolver.d.ts +40 -0
  47. package/lib/resolvers/consumption-order.resolver.js +238 -0
  48. package/lib/resolvers/loader-type.resolver.js +3 -0
  49. package/lib/resolvers/loader.resolver.js +3 -1
  50. package/lib/resolvers/material.resolver.js +3 -1
  51. package/lib/resolvers/receive-inventory-order.resolver.js +3 -0
  52. package/lib/resolvers/ship-inventory-order.resolver.js +3 -0
  53. package/lib/resolvers/stock.resolver.js +3 -0
  54. package/lib/resolvers/transfer-order.resolver.js +3 -0
  55. package/lib/scalars/index.d.ts +1 -0
  56. package/lib/scalars/json-object.scalar.d.ts +2 -0
  57. package/lib/scalars/json-object.scalar.js +62 -0
  58. package/package.json +2 -2
@@ -0,0 +1,17 @@
1
+ export declare class ConsumptionOrderItemDto {
2
+ id: string;
3
+ materialId: string;
4
+ batchId: string;
5
+ locationId: string;
6
+ loaderId: string | null;
7
+ targetLocationId: string | null;
8
+ targetLoaderId: string | null;
9
+ orderId: string;
10
+ unitId: string | null;
11
+ targetConsumedQuantity: number;
12
+ removedAt: Date | null;
13
+ }
14
+ declare const ConsumptionOrderItems_base: new () => import("./pagination.dto").PaginatedType<ConsumptionOrderItemDto>;
15
+ export declare class ConsumptionOrderItems extends ConsumptionOrderItems_base {
16
+ }
17
+ export {};
@@ -0,0 +1,43 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { Field, ID, Float, ObjectType } from '@nestjs/graphql';
3
+ import { PaginatedResponse } from './pagination.dto.js';
4
+
5
+ let ConsumptionOrderItemDto = class ConsumptionOrderItemDto {
6
+ id;
7
+ materialId;
8
+ batchId;
9
+ locationId;
10
+ loaderId;
11
+ targetLocationId;
12
+ targetLoaderId;
13
+ orderId;
14
+ unitId;
15
+ targetConsumedQuantity;
16
+ removedAt;
17
+ };
18
+ __decorate([
19
+ Field(() => ID),
20
+ __metadata("design:type", String)
21
+ ], ConsumptionOrderItemDto.prototype, "id", void 0);
22
+ __decorate([
23
+ Field(() => String, { nullable: true }),
24
+ __metadata("design:type", Object)
25
+ ], ConsumptionOrderItemDto.prototype, "unitId", void 0);
26
+ __decorate([
27
+ Field(() => Float),
28
+ __metadata("design:type", Number)
29
+ ], ConsumptionOrderItemDto.prototype, "targetConsumedQuantity", void 0);
30
+ __decorate([
31
+ Field(() => Date, { nullable: true }),
32
+ __metadata("design:type", Object)
33
+ ], ConsumptionOrderItemDto.prototype, "removedAt", void 0);
34
+ ConsumptionOrderItemDto = __decorate([
35
+ ObjectType()
36
+ ], ConsumptionOrderItemDto);
37
+ let ConsumptionOrderItems = class ConsumptionOrderItems extends PaginatedResponse(ConsumptionOrderItemDto) {
38
+ };
39
+ ConsumptionOrderItems = __decorate([
40
+ ObjectType()
41
+ ], ConsumptionOrderItems);
42
+
43
+ export { ConsumptionOrderItemDto, ConsumptionOrderItems };
@@ -0,0 +1,14 @@
1
+ import { ConsumptionOrderItemDto } from './consumption-order-item.dto';
2
+ export declare class ConsumptionOrderDto {
3
+ id: string;
4
+ key: string;
5
+ description: string | null;
6
+ createdBy: string | null;
7
+ removedAt: Date | null;
8
+ createdAt: Date;
9
+ items: ConsumptionOrderItemDto[];
10
+ }
11
+ declare const ConsumptionOrders_base: new () => import("./pagination.dto").PaginatedType<ConsumptionOrderDto>;
12
+ export declare class ConsumptionOrders extends ConsumptionOrders_base {
13
+ }
14
+ export {};
@@ -0,0 +1,52 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
3
+ import { ConsumptionOrderItemDto } from './consumption-order-item.dto.js';
4
+ import { PaginatedResponse } from './pagination.dto.js';
5
+
6
+ let ConsumptionOrderDto = class ConsumptionOrderDto {
7
+ id;
8
+ key;
9
+ description;
10
+ createdBy;
11
+ removedAt;
12
+ createdAt;
13
+ items;
14
+ };
15
+ __decorate([
16
+ Field(() => ID),
17
+ __metadata("design:type", String)
18
+ ], ConsumptionOrderDto.prototype, "id", void 0);
19
+ __decorate([
20
+ Field(() => String),
21
+ __metadata("design:type", String)
22
+ ], ConsumptionOrderDto.prototype, "key", void 0);
23
+ __decorate([
24
+ Field(() => String, { nullable: true }),
25
+ __metadata("design:type", Object)
26
+ ], ConsumptionOrderDto.prototype, "description", void 0);
27
+ __decorate([
28
+ Field(() => String, { nullable: true }),
29
+ __metadata("design:type", Object)
30
+ ], ConsumptionOrderDto.prototype, "createdBy", void 0);
31
+ __decorate([
32
+ Field(() => Date, { nullable: true }),
33
+ __metadata("design:type", Object)
34
+ ], ConsumptionOrderDto.prototype, "removedAt", void 0);
35
+ __decorate([
36
+ Field(() => Date),
37
+ __metadata("design:type", Date)
38
+ ], ConsumptionOrderDto.prototype, "createdAt", void 0);
39
+ __decorate([
40
+ Field(() => [ConsumptionOrderItemDto]),
41
+ __metadata("design:type", Array)
42
+ ], ConsumptionOrderDto.prototype, "items", void 0);
43
+ ConsumptionOrderDto = __decorate([
44
+ ObjectType()
45
+ ], ConsumptionOrderDto);
46
+ let ConsumptionOrders = class ConsumptionOrders extends PaginatedResponse(ConsumptionOrderDto) {
47
+ };
48
+ ConsumptionOrders = __decorate([
49
+ ObjectType()
50
+ ], ConsumptionOrders);
51
+
52
+ export { ConsumptionOrderDto, ConsumptionOrders };
@@ -23,3 +23,6 @@ export * from './scrape-order-item.dto';
23
23
  export * from './quality-inspection-order.dto';
24
24
  export * from './quality-inspection-order-item.dto';
25
25
  export * from './inventory-count-order.dto';
26
+ export * from './consumption-order.dto';
27
+ export * from './consumption-order-item.dto';
28
+ export * from './order-reference.dto';
@@ -23,8 +23,14 @@ export declare class InventoryCountOrderItemDto {
23
23
  isAddition: boolean;
24
24
  held: boolean | null;
25
25
  inShipment: boolean | null;
26
- /** `null` = awaiting inspection, `false` = failed, `true` = passed. */
26
+ /**
27
+ * `false` = failed, `true` = passed, `null` = not inspected — which is the
28
+ * resting state of almost every batch and does **not** on its own mean
29
+ * awaiting inspection. Pair it with `requiresInspection`.
30
+ */
27
31
  inspectionResult: boolean | null;
32
+ /** Whether anybody had asked for this position to be inspected. */
33
+ requiresInspection: boolean | null;
28
34
  transferId: string | null;
29
35
  vendorId: string | null;
30
36
  customerId: string | null;
@@ -36,8 +36,14 @@ let InventoryCountOrderItemDto = class InventoryCountOrderItemDto {
36
36
  // a record of what was found. `null` before counting has started.
37
37
  held;
38
38
  inShipment;
39
- /** `null` = awaiting inspection, `false` = failed, `true` = passed. */
39
+ /**
40
+ * `false` = failed, `true` = passed, `null` = not inspected — which is the
41
+ * resting state of almost every batch and does **not** on its own mean
42
+ * awaiting inspection. Pair it with `requiresInspection`.
43
+ */
40
44
  inspectionResult;
45
+ /** Whether anybody had asked for this position to be inspected. */
46
+ requiresInspection;
41
47
  transferId;
42
48
  vendorId;
43
49
  customerId;
@@ -96,6 +102,10 @@ __decorate([
96
102
  Field(() => Boolean, { nullable: true }),
97
103
  __metadata("design:type", Object)
98
104
  ], InventoryCountOrderItemDto.prototype, "inspectionResult", void 0);
105
+ __decorate([
106
+ Field(() => Boolean, { nullable: true }),
107
+ __metadata("design:type", Object)
108
+ ], InventoryCountOrderItemDto.prototype, "requiresInspection", void 0);
99
109
  __decorate([
100
110
  Field(() => ID, { nullable: true }),
101
111
  __metadata("design:type", Object)
@@ -0,0 +1,22 @@
1
+ import { WmsOrderType } from '@rytass/wms-module-core';
2
+ /**
3
+ * A link from one of this module's orders to the document in the host system it
4
+ * was opened for. The module stores `referenceType` / `referenceId` verbatim
5
+ * and never resolves them — turning one into a link is the host's job (see
6
+ * `referenceLinkResolver` in `@rytass/wms-module-react`).
7
+ */
8
+ export declare class OrderReferenceDto {
9
+ id: string;
10
+ orderType: WmsOrderType;
11
+ orderId: string;
12
+ itemId: string | null;
13
+ referenceType: string;
14
+ referenceId: string;
15
+ referenceLine: string | null;
16
+ metadata: Record<string, unknown> | null;
17
+ createdAt: Date;
18
+ }
19
+ declare const OrderReferences_base: new () => import("./pagination.dto").PaginatedType<OrderReferenceDto>;
20
+ export declare class OrderReferences extends OrderReferences_base {
21
+ }
22
+ export {};
@@ -0,0 +1,73 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { registerEnumType, Field, ID, ObjectType } from '@nestjs/graphql';
3
+ import { WmsOrderType } from '@rytass/wms-module-core';
4
+ import { GraphQLJSONObject } from '../scalars/json-object.scalar.js';
5
+ import { PaginatedResponse } from './pagination.dto.js';
6
+
7
+ registerEnumType(WmsOrderType, {
8
+ name: 'WmsOrderType',
9
+ description: 'An order family in this module, named the same way `@WmsOperation` names it.',
10
+ });
11
+ /**
12
+ * A link from one of this module's orders to the document in the host system it
13
+ * was opened for. The module stores `referenceType` / `referenceId` verbatim
14
+ * and never resolves them — turning one into a link is the host's job (see
15
+ * `referenceLinkResolver` in `@rytass/wms-module-react`).
16
+ */
17
+ let OrderReferenceDto = class OrderReferenceDto {
18
+ id;
19
+ orderType;
20
+ orderId;
21
+ itemId;
22
+ referenceType;
23
+ referenceId;
24
+ referenceLine;
25
+ metadata;
26
+ createdAt;
27
+ };
28
+ __decorate([
29
+ Field(() => ID),
30
+ __metadata("design:type", String)
31
+ ], OrderReferenceDto.prototype, "id", void 0);
32
+ __decorate([
33
+ Field(() => WmsOrderType),
34
+ __metadata("design:type", String)
35
+ ], OrderReferenceDto.prototype, "orderType", void 0);
36
+ __decorate([
37
+ Field(() => ID),
38
+ __metadata("design:type", String)
39
+ ], OrderReferenceDto.prototype, "orderId", void 0);
40
+ __decorate([
41
+ Field(() => ID, { nullable: true }),
42
+ __metadata("design:type", Object)
43
+ ], OrderReferenceDto.prototype, "itemId", void 0);
44
+ __decorate([
45
+ Field(() => String),
46
+ __metadata("design:type", String)
47
+ ], OrderReferenceDto.prototype, "referenceType", void 0);
48
+ __decorate([
49
+ Field(() => String),
50
+ __metadata("design:type", String)
51
+ ], OrderReferenceDto.prototype, "referenceId", void 0);
52
+ __decorate([
53
+ Field(() => String, { nullable: true }),
54
+ __metadata("design:type", Object)
55
+ ], OrderReferenceDto.prototype, "referenceLine", void 0);
56
+ __decorate([
57
+ Field(() => GraphQLJSONObject, { nullable: true }),
58
+ __metadata("design:type", Object)
59
+ ], OrderReferenceDto.prototype, "metadata", void 0);
60
+ __decorate([
61
+ Field(() => Date),
62
+ __metadata("design:type", Date)
63
+ ], OrderReferenceDto.prototype, "createdAt", void 0);
64
+ OrderReferenceDto = __decorate([
65
+ ObjectType()
66
+ ], OrderReferenceDto);
67
+ let OrderReferences = class OrderReferences extends PaginatedResponse(OrderReferenceDto) {
68
+ };
69
+ OrderReferences = __decorate([
70
+ ObjectType()
71
+ ], OrderReferences);
72
+
73
+ export { OrderReferenceDto, OrderReferences };
@@ -23,6 +23,21 @@ export declare class AggregatedStockDto {
23
23
  customerId?: string | null;
24
24
  vendorId?: string | null;
25
25
  inspectionResult?: boolean;
26
+ /**
27
+ * Whether anyone asked for this batch to be inspected. Paired with
28
+ * `inspectionResult`, it is what separates "awaiting inspection" from
29
+ * "nobody ever intended to inspect this", which `inspectionResult` alone
30
+ * cannot say.
31
+ */
32
+ requiresInspection?: boolean;
33
+ /**
34
+ * Batch lineage and the host's own attributes, flattened onto the row the way
35
+ * every other batch column here already is. `batch` resolves to the batch
36
+ * *group*, which is what carries the human-readable key — these two live on
37
+ * the batch itself and would otherwise be unreachable from a stock list.
38
+ */
39
+ parentBatchId?: string | null;
40
+ attributes?: Record<string, unknown> | null;
26
41
  }
27
42
  declare const AggregatedStocks_base: new () => import("./pagination.dto").PaginatedType<AggregatedStockDto>;
28
43
  export declare class AggregatedStocks extends AggregatedStocks_base {
@@ -2,6 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Field, ID, Int, ObjectType, registerEnumType } from '@nestjs/graphql';
3
3
  import { PaginatedResponse } from './pagination.dto.js';
4
4
  import { StockStatus, ChangeType } from '@rytass/wms-module-core';
5
+ import { GraphQLJSONObject } from '../scalars/json-object.scalar.js';
5
6
 
6
7
  let StockDto = class StockDto {
7
8
  id;
@@ -48,6 +49,21 @@ let AggregatedStockDto = class AggregatedStockDto {
48
49
  customerId;
49
50
  vendorId;
50
51
  inspectionResult;
52
+ /**
53
+ * Whether anyone asked for this batch to be inspected. Paired with
54
+ * `inspectionResult`, it is what separates "awaiting inspection" from
55
+ * "nobody ever intended to inspect this", which `inspectionResult` alone
56
+ * cannot say.
57
+ */
58
+ requiresInspection;
59
+ /**
60
+ * Batch lineage and the host's own attributes, flattened onto the row the way
61
+ * every other batch column here already is. `batch` resolves to the batch
62
+ * *group*, which is what carries the human-readable key — these two live on
63
+ * the batch itself and would otherwise be unreachable from a stock list.
64
+ */
65
+ parentBatchId;
66
+ attributes;
51
67
  };
52
68
  __decorate([
53
69
  Field(() => Int),
@@ -89,6 +105,18 @@ __decorate([
89
105
  Field(() => Boolean, { nullable: true }),
90
106
  __metadata("design:type", Boolean)
91
107
  ], AggregatedStockDto.prototype, "inspectionResult", void 0);
108
+ __decorate([
109
+ Field(() => Boolean, { nullable: true }),
110
+ __metadata("design:type", Boolean)
111
+ ], AggregatedStockDto.prototype, "requiresInspection", void 0);
112
+ __decorate([
113
+ Field(() => ID, { nullable: true }),
114
+ __metadata("design:type", Object)
115
+ ], AggregatedStockDto.prototype, "parentBatchId", void 0);
116
+ __decorate([
117
+ Field(() => GraphQLJSONObject, { nullable: true }),
118
+ __metadata("design:type", Object)
119
+ ], AggregatedStockDto.prototype, "attributes", void 0);
92
120
  AggregatedStockDto = __decorate([
93
121
  ObjectType()
94
122
  ], AggregatedStockDto);
@@ -17,6 +17,8 @@ import type { MapDataDto } from '../dto/warehouse-map.dto';
17
17
  import type { MergeBatchOrderDto } from '../dto/merge-batch-order.dto';
18
18
  import type { ReclassifyInventoryOrderDto } from '../dto/reclassify-inventory-order.dto';
19
19
  import type { SplitBatchOrderDto } from '../dto/split-batch-order.dto';
20
+ import type { OrderReferenceDto } from '../dto/order-reference.dto';
21
+ import type { ConsumptionOrderDto } from '../dto/consumption-order.dto';
20
22
  /**
21
23
  * Maps every {@link WmsOperationEventName} to the concrete type returned by
22
24
  * the corresponding mutation resolver.
@@ -68,6 +70,17 @@ export interface WmsOperationResultMap extends Record<WmsOperationEventName, unk
68
70
  'batch.splitted': SplitBatchOrderDto;
69
71
  'scrape-order.scraped': ScrapeOrderDto;
70
72
  'quality-inspection-order.inspected': QualityInspectionOrderDto;
73
+ 'consumption-order.created': ConsumptionOrderDto;
74
+ 'consumption-order.updated': ConsumptionOrderDto;
75
+ /** Action mutation — result is a success flag; use args + stock.issued. */
76
+ 'consumption-order.issued': boolean;
77
+ /** Action mutation — result is a success flag; use args + stock.returned. */
78
+ 'consumption-order.returned': boolean;
79
+ /** Action mutation — result is a success flag; use args + stock.consumed. */
80
+ 'consumption-order.settled': boolean;
81
+ 'order-reference.attached': OrderReferenceDto[];
82
+ /** Action mutation — result is a success flag; the id is in `args`. */
83
+ 'order-reference.detached': boolean;
71
84
  'transfer-order.created': TransferOrderDto;
72
85
  'transfer-order.updated': TransferOrderDto;
73
86
  /** Action mutation — result is a success flag; use args + stock.transferred. */
@@ -37,17 +37,27 @@ export interface WmsTypedAfterEventContext<N extends WmsEventName> {
37
37
  }
38
38
  /**
39
39
  * Context passed to a before-hook. Runs *before* any DB work, so
40
- * `payload` / `result` are not yet available — only the raw GraphQL
41
- * arguments (`args`) and the resolved actor. Throwing from a before-hook
42
- * vetoes the mutation with zero side effects.
40
+ * `payload` / `result` are not yet available — only the raw arguments
41
+ * (`args`) and the resolved actor. Throwing from a before-hook vetoes the
42
+ * operation with zero side effects.
43
+ *
44
+ * Structurally identical to the core `WmsBeforeHookContext`; the two must stay
45
+ * in step, because a hook written against either is handed the same object.
43
46
  */
44
47
  export interface WmsTypedBeforeHookContext<N extends WmsEventName> {
45
48
  readonly event: N;
46
- /** Raw GraphQL arguments — the mutation intent (per §3.4 of the design doc). */
49
+ /** Raw arguments — the operation's intent (per §3.4 of the design doc). */
47
50
  readonly args: Readonly<Record<string, unknown>>;
48
- /** The NestJS execution context at the time of the mutation call. */
49
- readonly executionContext: ExecutionContext;
50
- /** Who performed the mutation; `null` when no `actorExtractor` is configured. */
51
+ /**
52
+ * The NestJS execution context, or `null` when the operation did not arrive
53
+ * through one — a host driving a domain service through
54
+ * `WmsOperationRunner`. Branch on {@link WmsTypedBeforeHookContext.source}
55
+ * rather than on this being present.
56
+ */
57
+ readonly executionContext: ExecutionContext | null;
58
+ /** Where the operation came in from. `'host'` means a direct service call. */
59
+ readonly source: 'graphql' | 'host';
60
+ /** Who performed the operation; `null` when no `actorExtractor` is configured. */
51
61
  readonly actor: WmsActor | null;
52
62
  }
53
63
  /**
@@ -1,21 +1,23 @@
1
1
  import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common';
2
2
  import { Reflector } from '@nestjs/core';
3
- import { WmsEventDispatcher, type WmsActorExtractor } from '@rytass/wms-module-core';
3
+ import { WmsOperationRunner, type WmsActorExtractor } from '@rytass/wms-module-core';
4
4
  import { type Observable } from 'rxjs';
5
5
  /**
6
- * Wraps each `@WmsMutationEvent` mutation in a dispatch scope:
7
- * 1. runs the before-hook (throw -> veto, before any transaction);
8
- * 2. executes the resolver (services collect stock events into the scope);
9
- * 3. emits the operation event after the handler resolves (post-commit);
10
- * 4. flushes the whole buffer to after-listeners + emitter bridge.
6
+ * Hands each `@WmsMutationEvent` mutation to {@link WmsOperationRunner}, which
7
+ * owns the before-hook / dispatch scope / post-commit flush sequence.
11
8
  *
12
- * When no hook/listener/bridge is configured it passes through untouched.
9
+ * All this adds on top is what only a GraphQL request can supply: the raw
10
+ * arguments and the actor. Keeping the sequence itself in core is what stops
11
+ * the GraphQL path and a host's direct service call from drifting apart.
12
+ *
13
+ * When no hook, listener or bridge is configured the runner passes through
14
+ * untouched.
13
15
  */
14
16
  export declare class WmsMutationInterceptor implements NestInterceptor {
15
17
  private readonly reflector;
16
- private readonly dispatcher;
18
+ private readonly runner;
17
19
  private readonly actorExtractor;
18
- constructor(reflector: Reflector, dispatcher: WmsEventDispatcher, actorExtractor?: WmsActorExtractor | null);
20
+ constructor(reflector: Reflector, runner: WmsOperationRunner, actorExtractor?: WmsActorExtractor | null);
19
21
  private resolveActor;
20
22
  intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<unknown>>;
21
23
  }
@@ -2,36 +2,28 @@ import { __decorate, __param, __metadata } from 'tslib';
2
2
  import { Injectable, Optional, Inject } from '@nestjs/common';
3
3
  import { Reflector } from '@nestjs/core';
4
4
  import { GqlExecutionContext } from '@nestjs/graphql';
5
- import { WMS_ACTOR_EXTRACTOR, WmsEventDispatcher, runInDispatchScope, collectToScope } from '@rytass/wms-module-core';
5
+ import { WMS_ACTOR_EXTRACTOR, WmsOperationRunner } from '@rytass/wms-module-core';
6
6
  import { firstValueFrom, of } from 'rxjs';
7
7
  import { WMS_MUTATION_EVENT_METADATA } from './wms-mutation-event.constants.js';
8
8
 
9
- const defaultResolveId = (result, args) => {
10
- if (result &&
11
- typeof result === 'object' &&
12
- 'id' in result &&
13
- typeof result.id === 'string') {
14
- return result.id;
15
- }
16
- const argId = args['id'];
17
- return typeof argId === 'string' ? argId : null;
18
- };
19
9
  /**
20
- * Wraps each `@WmsMutationEvent` mutation in a dispatch scope:
21
- * 1. runs the before-hook (throw -> veto, before any transaction);
22
- * 2. executes the resolver (services collect stock events into the scope);
23
- * 3. emits the operation event after the handler resolves (post-commit);
24
- * 4. flushes the whole buffer to after-listeners + emitter bridge.
10
+ * Hands each `@WmsMutationEvent` mutation to {@link WmsOperationRunner}, which
11
+ * owns the before-hook / dispatch scope / post-commit flush sequence.
25
12
  *
26
- * When no hook/listener/bridge is configured it passes through untouched.
13
+ * All this adds on top is what only a GraphQL request can supply: the raw
14
+ * arguments and the actor. Keeping the sequence itself in core is what stops
15
+ * the GraphQL path and a host's direct service call from drifting apart.
16
+ *
17
+ * When no hook, listener or bridge is configured the runner passes through
18
+ * untouched.
27
19
  */
28
20
  let WmsMutationInterceptor = class WmsMutationInterceptor {
29
21
  reflector;
30
- dispatcher;
22
+ runner;
31
23
  actorExtractor;
32
- constructor(reflector, dispatcher, actorExtractor = null) {
24
+ constructor(reflector, runner, actorExtractor = null) {
33
25
  this.reflector = reflector;
34
- this.dispatcher = dispatcher;
26
+ this.runner = runner;
35
27
  this.actorExtractor = actorExtractor;
36
28
  }
37
29
  resolveActor(context) {
@@ -48,34 +40,16 @@ let WmsMutationInterceptor = class WmsMutationInterceptor {
48
40
  }
49
41
  async intercept(context, next) {
50
42
  const config = this.reflector.get(WMS_MUTATION_EVENT_METADATA, context.getHandler());
51
- if (!config || !this.dispatcher.isActive()) {
43
+ if (!config) {
52
44
  return next.handle();
53
45
  }
54
- const args = GqlExecutionContext.create(context).getArgs() ??
55
- {};
56
- const actor = this.resolveActor(context);
57
- // Before-hook runs before any DB work; a throw vetoes with zero side effects.
58
- await this.dispatcher.runBeforeHook({
46
+ const result = await this.runner.run({
59
47
  event: config.event,
60
- args,
48
+ args: GqlExecutionContext.create(context).getArgs() ?? {},
49
+ actor: this.resolveActor(context),
50
+ resolveId: config.resolveId,
61
51
  executionContext: context,
62
- actor,
63
- });
64
- const { result, events } = await runInDispatchScope(async () => {
65
- const handlerResult = await firstValueFrom(next.handle());
66
- const id = config.resolveId
67
- ? config.resolveId(handlerResult, args)
68
- : defaultResolveId(handlerResult, args);
69
- const operationEvent = {
70
- name: config.event,
71
- payload: { id, result: handlerResult, args, actor },
72
- };
73
- collectToScope(operationEvent);
74
- return handlerResult;
75
- });
76
- if (events) {
77
- await this.dispatcher.flush(events);
78
- }
52
+ }, () => firstValueFrom(next.handle()));
79
53
  return of(result);
80
54
  }
81
55
  };
@@ -84,7 +58,7 @@ WmsMutationInterceptor = __decorate([
84
58
  __param(2, Optional()),
85
59
  __param(2, Inject(WMS_ACTOR_EXTRACTOR)),
86
60
  __metadata("design:paramtypes", [Reflector,
87
- WmsEventDispatcher, Object])
61
+ WmsOperationRunner, Object])
88
62
  ], WmsMutationInterceptor);
89
63
 
90
64
  export { WmsMutationInterceptor };
@@ -24,7 +24,7 @@ import { type WmsOperationRegistrationOptions } from './registry';
24
24
  * Everything is optional; with nothing configured the module behaves exactly as
25
25
  * before (no events emitted, fully permissive, every operation registered).
26
26
  */
27
- export type WmsModuleGraphqlModuleAsyncOptions = WmsModuleCoreModuleAsyncOptions & WmsAuthModuleOptions & WmsOperationRegistrationOptions & {
27
+ export type WmsModuleGraphqlModuleAsyncOptions = Omit<WmsModuleCoreModuleAsyncOptions, 'beforeHooks' | 'afterListeners'> & WmsAuthModuleOptions & WmsOperationRegistrationOptions & {
28
28
  readonly beforeHooks?: WmsTypedBeforeHookMap;
29
29
  readonly afterListeners?: WmsTypedAfterListenerMap;
30
30
  readonly actorExtractor?: WmsActorExtractor;
@@ -1,6 +1,6 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { Module } from '@nestjs/common';
3
- import { WmsModuleCoreModule, WMS_EVENT_OPTIONS, WMS_ACTOR_EXTRACTOR, WmsEventDispatcher } from '@rytass/wms-module-core';
3
+ import { WmsModuleCoreModule } from '@rytass/wms-module-core';
4
4
  import './helpers/loader.service.js';
5
5
  import { HelperModule } from './helpers/helper.module.js';
6
6
  import './helpers/query-path.js';
@@ -34,6 +34,11 @@ import { HoldInventoryOrderMutation } from './mutations/hold-inventory-order.mut
34
34
  import { HoldInventoryOrderQuery } from './queries/hold-inventory-order.query.js';
35
35
  import { HoldInventoryOrderResolver } from './resolvers/hold-inventory-order.resolver.js';
36
36
  import { BatchQuery } from './queries/batch.query.js';
37
+ import { OrderReferenceQuery } from './queries/order-reference.query.js';
38
+ import { OrderReferenceMutation } from './mutations/order-reference.mutation.js';
39
+ import { ConsumptionOrderQuery } from './queries/consumption-order.query.js';
40
+ import { ConsumptionOrderMutation } from './mutations/consumption-order.mutation.js';
41
+ import { ConsumptionOrderResolver, ConsumptionOrderItemResolver } from './resolvers/consumption-order.resolver.js';
37
42
  import { ChangeLogResolver } from './resolvers/change-log.resolver.js';
38
43
  import { ReceiveInventoryOrderResolver, ReceiveInventoryOrderItemResolver } from './resolvers/receive-inventory-order.resolver.js';
39
44
  import { AllocateInventoryOrderQuery } from './queries/allocate-inventory-order.query.js';
@@ -116,6 +121,12 @@ const exportDependencies = [
116
121
  InventoryCountOrderMutation,
117
122
  InventoryCountOrderResolver,
118
123
  InventoryCountOrderItemResolver,
124
+ OrderReferenceQuery,
125
+ OrderReferenceMutation,
126
+ ConsumptionOrderQuery,
127
+ ConsumptionOrderMutation,
128
+ ConsumptionOrderResolver,
129
+ ConsumptionOrderItemResolver,
119
130
  ];
120
131
  let WmsModuleGraphqlModule = WmsModuleGraphqlModule_1 = class WmsModuleGraphqlModule {
121
132
  static forRootAsync(options) {
@@ -129,25 +140,31 @@ let WmsModuleGraphqlModule = WmsModuleGraphqlModule_1 = class WmsModuleGraphqlMo
129
140
  disabledOperations,
130
141
  disabledFields,
131
142
  });
132
- // coreOptions still carries `enrichStockEvents`, forwarded to the core module.
133
- const coreModule = WmsModuleCoreModule.forRootAsync(coreOptions);
134
- const authOptions = { authChecker };
135
- // The typed hook maps are a compile-time refinement of the core maps; at
136
- // runtime the dispatched payload IS the concrete result type, so handing the
137
- // refined maps to the (looser) core option contract is sound.
138
- const eventOptions = {
143
+ /*
144
+ * The event wiring goes down to the core module rather than being bound
145
+ * here. `WmsOperationRunner` lives in core so a host calling a service
146
+ * directly gets the same guarantee, and binding the same tokens in both
147
+ * modules would leave two live bindings whose winner depends on which
148
+ * injector the consumer reached first.
149
+ *
150
+ * `coreOptions` still carries `enrichStockEvents`, also forwarded.
151
+ */
152
+ const coreModule = WmsModuleCoreModule.forRootAsync({
153
+ ...coreOptions,
154
+ // The typed hook maps are a compile-time refinement of the core maps; at
155
+ // runtime the dispatched payload IS the concrete result type, so handing
156
+ // the refined maps to the (looser) core option contract is sound.
139
157
  beforeHooks: beforeHooks,
140
158
  afterListeners: afterListeners,
141
- };
159
+ actorExtractor,
160
+ eventEmitterBridge,
161
+ });
162
+ const authOptions = { authChecker };
142
163
  const providers = [
143
164
  ...exportDependencies,
144
165
  WmsAuthGuard,
145
166
  { provide: WMS_AUTH_OPTIONS, useValue: authOptions },
146
- { provide: WMS_EVENT_OPTIONS, useValue: eventOptions },
147
- { provide: WMS_ACTOR_EXTRACTOR, useValue: actorExtractor ?? null },
148
- WmsEventDispatcher,
149
167
  WmsMutationInterceptor,
150
- ...(eventEmitterBridge ? [eventEmitterBridge] : []),
151
168
  ];
152
169
  return {
153
170
  module: WmsModuleGraphqlModule_1,