@rytass/wms-module-graphql 0.8.0 → 0.9.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 (42) hide show
  1. package/README.md +83 -1
  2. package/docs/api-reference.md +76 -1
  3. package/docs/events.md +23 -4
  4. package/index.cjs.js +779 -1
  5. package/index.d.ts +3 -1
  6. package/index.js +2 -0
  7. package/lib/dto/index.d.ts +1 -0
  8. package/lib/dto/inventory-count-order.dto.d.ts +49 -0
  9. package/lib/dto/inventory-count-order.dto.js +146 -0
  10. package/lib/events/operation-result-map.d.ts +8 -0
  11. package/lib/graphql.module.d.ts +6 -2
  12. package/lib/graphql.module.js +18 -1
  13. package/lib/inputs/inventory-count-order.args.d.ts +55 -0
  14. package/lib/inputs/inventory-count-order.args.js +196 -0
  15. package/lib/mutations/inventory-count-order.mutation.d.ts +19 -0
  16. package/lib/mutations/inventory-count-order.mutation.js +138 -0
  17. package/lib/mutations/loader.mutation.js +1 -0
  18. package/lib/mutations/material.mutation.js +1 -0
  19. package/lib/mutations/receive-inventory-order.mutation.js +1 -0
  20. package/lib/mutations/ship-inventory-order.mutation.js +1 -0
  21. package/lib/queries/inventory-count-order.query.d.ts +9 -0
  22. package/lib/queries/inventory-count-order.query.js +44 -0
  23. package/lib/queries/loader.query.js +1 -0
  24. package/lib/queries/material.query.js +1 -0
  25. package/lib/queries/recieve-inventory-order.query.js +1 -0
  26. package/lib/queries/ship-inventory-order.query.js +1 -0
  27. package/lib/queries/stock.query.js +1 -0
  28. package/lib/registry/index.d.ts +1 -0
  29. package/lib/registry/operation-registry.d.ts +59 -0
  30. package/lib/registry/operation-registry.js +136 -0
  31. package/lib/resolvers/aggregated-stock.resolver.js +1 -0
  32. package/lib/resolvers/change-log.resolver.js +1 -0
  33. package/lib/resolvers/inventory-count-order.resolver.d.ts +34 -0
  34. package/lib/resolvers/inventory-count-order.resolver.js +148 -0
  35. package/lib/resolvers/loader-type.resolver.js +1 -0
  36. package/lib/resolvers/loader.resolver.js +1 -0
  37. package/lib/resolvers/material.resolver.js +1 -0
  38. package/lib/resolvers/receive-inventory-order.resolver.js +1 -0
  39. package/lib/resolvers/ship-inventory-order.resolver.js +1 -0
  40. package/lib/resolvers/stock.resolver.js +1 -0
  41. package/lib/resolvers/transfer-order.resolver.js +1 -0
  42. package/package.json +2 -2
@@ -0,0 +1,138 @@
1
+ import { __decorate, __param, __metadata } from 'tslib';
2
+ import { Injectable } from '@nestjs/common';
3
+ import { Mutation, Args } from '@nestjs/graphql';
4
+ import { InventoryCountOrderService } from '@rytass/wms-module-core';
5
+ import { InventoryCountOrderDto, InventoryCountOrderItemDto } from '../dto/inventory-count-order.dto.js';
6
+ import { CreateInventoryCountOrderArgs, UpdateInventoryCountOrderArgs, InventoryCountOrderIdArgs, CountInventoryArgs, AddInventoryCountItemArgs, RemoveInventoryCountItemArgs } from '../inputs/inventory-count-order.args.js';
7
+ import '../auth/wms-auth.guard.js';
8
+ import { WmsOperation } from '../auth/wms-operation.decorator.js';
9
+ import { WmsMutationEvent } from '../events/wms-mutation-event.decorator.js';
10
+ import '../events/wms-mutation.interceptor.js';
11
+
12
+ let InventoryCountOrderMutation = class InventoryCountOrderMutation {
13
+ inventoryCountOrderService;
14
+ constructor(inventoryCountOrderService) {
15
+ this.inventoryCountOrderService = inventoryCountOrderService;
16
+ }
17
+ async createInventoryCountOrder(args) {
18
+ return this.inventoryCountOrderService.create(args);
19
+ }
20
+ async updateInventoryCountOrder({ id, ...input }) {
21
+ return this.inventoryCountOrderService.update(id, input);
22
+ }
23
+ async startInventoryCount({ id }) {
24
+ return this.inventoryCountOrderService.start(id);
25
+ }
26
+ /** "暫存結果" — record what was counted without touching stock. */
27
+ async countInventory({ id, items }) {
28
+ return this.inventoryCountOrderService.count(id, items.map((item) => ({
29
+ itemId: item.itemId,
30
+ countedQuantity: item.countedQuantity ?? null,
31
+ unitId: item.unitId,
32
+ })));
33
+ }
34
+ async addInventoryCountItem({ id, ...input }) {
35
+ return this.inventoryCountOrderService.addItem(id, input);
36
+ }
37
+ async removeInventoryCountItem({ id, itemId }) {
38
+ return this.inventoryCountOrderService.removeItem(id, itemId);
39
+ }
40
+ /** "清空重填" — discard the counting, keep the lock and the status. */
41
+ async resetInventoryCount({ id }) {
42
+ return this.inventoryCountOrderService.reset(id);
43
+ }
44
+ async cancelInventoryCount({ id }) {
45
+ return this.inventoryCountOrderService.cancel(id);
46
+ }
47
+ /** "執行盤差" — the only mutation here that changes stock. */
48
+ async settleInventoryCount({ id }) {
49
+ return this.inventoryCountOrderService.settle(id);
50
+ }
51
+ };
52
+ __decorate([
53
+ Mutation(() => InventoryCountOrderDto),
54
+ WmsOperation({ resource: 'inventory-count-order', action: 'create' }),
55
+ WmsMutationEvent({ event: 'inventory-count-order.created' }),
56
+ __param(0, Args()),
57
+ __metadata("design:type", Function),
58
+ __metadata("design:paramtypes", [CreateInventoryCountOrderArgs]),
59
+ __metadata("design:returntype", Promise)
60
+ ], InventoryCountOrderMutation.prototype, "createInventoryCountOrder", null);
61
+ __decorate([
62
+ Mutation(() => InventoryCountOrderDto),
63
+ WmsOperation({ resource: 'inventory-count-order', action: 'update' }),
64
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
65
+ __param(0, Args()),
66
+ __metadata("design:type", Function),
67
+ __metadata("design:paramtypes", [UpdateInventoryCountOrderArgs]),
68
+ __metadata("design:returntype", Promise)
69
+ ], InventoryCountOrderMutation.prototype, "updateInventoryCountOrder", null);
70
+ __decorate([
71
+ Mutation(() => InventoryCountOrderDto),
72
+ WmsOperation({ resource: 'inventory-count-order', action: 'start' }),
73
+ WmsMutationEvent({ event: 'inventory-count-order.started' }),
74
+ __param(0, Args()),
75
+ __metadata("design:type", Function),
76
+ __metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
77
+ __metadata("design:returntype", Promise)
78
+ ], InventoryCountOrderMutation.prototype, "startInventoryCount", null);
79
+ __decorate([
80
+ Mutation(() => InventoryCountOrderDto),
81
+ WmsOperation({ resource: 'inventory-count-order', action: 'count' }),
82
+ WmsMutationEvent({ event: 'inventory-count-order.counted' }),
83
+ __param(0, Args()),
84
+ __metadata("design:type", Function),
85
+ __metadata("design:paramtypes", [CountInventoryArgs]),
86
+ __metadata("design:returntype", Promise)
87
+ ], InventoryCountOrderMutation.prototype, "countInventory", null);
88
+ __decorate([
89
+ Mutation(() => InventoryCountOrderItemDto),
90
+ WmsOperation({ resource: 'inventory-count-order', action: 'add-item' }),
91
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
92
+ __param(0, Args()),
93
+ __metadata("design:type", Function),
94
+ __metadata("design:paramtypes", [AddInventoryCountItemArgs]),
95
+ __metadata("design:returntype", Promise)
96
+ ], InventoryCountOrderMutation.prototype, "addInventoryCountItem", null);
97
+ __decorate([
98
+ Mutation(() => InventoryCountOrderDto),
99
+ WmsOperation({ resource: 'inventory-count-order', action: 'remove-item' }),
100
+ WmsMutationEvent({ event: 'inventory-count-order.updated' }),
101
+ __param(0, Args()),
102
+ __metadata("design:type", Function),
103
+ __metadata("design:paramtypes", [RemoveInventoryCountItemArgs]),
104
+ __metadata("design:returntype", Promise)
105
+ ], InventoryCountOrderMutation.prototype, "removeInventoryCountItem", null);
106
+ __decorate([
107
+ Mutation(() => InventoryCountOrderDto),
108
+ WmsOperation({ resource: 'inventory-count-order', action: 'reset' }),
109
+ WmsMutationEvent({ event: 'inventory-count-order.reset' }),
110
+ __param(0, Args()),
111
+ __metadata("design:type", Function),
112
+ __metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
113
+ __metadata("design:returntype", Promise)
114
+ ], InventoryCountOrderMutation.prototype, "resetInventoryCount", null);
115
+ __decorate([
116
+ Mutation(() => InventoryCountOrderDto),
117
+ WmsOperation({ resource: 'inventory-count-order', action: 'cancel' }),
118
+ WmsMutationEvent({ event: 'inventory-count-order.cancelled' }),
119
+ __param(0, Args()),
120
+ __metadata("design:type", Function),
121
+ __metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
122
+ __metadata("design:returntype", Promise)
123
+ ], InventoryCountOrderMutation.prototype, "cancelInventoryCount", null);
124
+ __decorate([
125
+ Mutation(() => InventoryCountOrderDto),
126
+ WmsOperation({ resource: 'inventory-count-order', action: 'settle' }),
127
+ WmsMutationEvent({ event: 'inventory-count-order.settled' }),
128
+ __param(0, Args()),
129
+ __metadata("design:type", Function),
130
+ __metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
131
+ __metadata("design:returntype", Promise)
132
+ ], InventoryCountOrderMutation.prototype, "settleInventoryCount", null);
133
+ InventoryCountOrderMutation = __decorate([
134
+ Injectable(),
135
+ __metadata("design:paramtypes", [InventoryCountOrderService])
136
+ ], InventoryCountOrderMutation);
137
+
138
+ export { InventoryCountOrderMutation };
@@ -25,6 +25,7 @@ import '../dto/scrape-order.dto.js';
25
25
  import '../dto/scrape-order-item.dto.js';
26
26
  import '../dto/quality-inspection-order.dto.js';
27
27
  import '../dto/quality-inspection-order-item.dto.js';
28
+ import '../dto/inventory-count-order.dto.js';
28
29
  import { Mutation, Args } from '@nestjs/graphql';
29
30
  import { CreateLoaderTypeArgs, UpdateLoaderTypeArgs } from '../inputs/create-loader-type.args.js';
30
31
  import { CreateLoaderArgs, CreateLoadersArgs, UpdateLoaderArgs } from '../inputs/create-loader.args.js';
@@ -25,6 +25,7 @@ import '../dto/scrape-order.dto.js';
25
25
  import '../dto/scrape-order-item.dto.js';
26
26
  import '../dto/quality-inspection-order.dto.js';
27
27
  import '../dto/quality-inspection-order-item.dto.js';
28
+ import '../dto/inventory-count-order.dto.js';
28
29
  import { CreateMaterialArgs, UpdateMaterialArgs } from '../inputs/create-material.args.js';
29
30
  import { MaterialService } from '@rytass/wms-module-core';
30
31
  import '../auth/wms-auth.guard.js';
@@ -26,6 +26,7 @@ import '../dto/scrape-order.dto.js';
26
26
  import '../dto/scrape-order-item.dto.js';
27
27
  import '../dto/quality-inspection-order.dto.js';
28
28
  import '../dto/quality-inspection-order-item.dto.js';
29
+ import '../dto/inventory-count-order.dto.js';
29
30
  import { CreateReceiveInventoryOrderArgs, UpdateReceiveInventoryOrderArgs } from '../inputs/create-receive-inventory-order.args.js';
30
31
  import { DataSource } from 'typeorm';
31
32
  import { ReceiveOrderArgs } from '../inputs/receive-order.args.js';
@@ -25,6 +25,7 @@ import '../dto/scrape-order.dto.js';
25
25
  import '../dto/scrape-order-item.dto.js';
26
26
  import '../dto/quality-inspection-order.dto.js';
27
27
  import '../dto/quality-inspection-order-item.dto.js';
28
+ import '../dto/inventory-count-order.dto.js';
28
29
  import { Mutation, Args } from '@nestjs/graphql';
29
30
  import { CreateShipInventoryOrderArgs, UpdateShipInventoryOrderArgs } from '../inputs/create-ship-inventory-order.args.js';
30
31
  import { ShipOrderArgs } from '../inputs/ship-order.args.js';
@@ -0,0 +1,9 @@
1
+ import { InventoryCountOrderService } from '@rytass/wms-module-core';
2
+ import { InventoryCountOrderDto, InventoryCountOrders } from '../dto/inventory-count-order.dto';
3
+ import { FindInventoryCountOrderArgs, InventoryCountOrderIdArgs } from '../inputs/inventory-count-order.args';
4
+ export declare class InventoryCountOrderQuery {
5
+ private readonly inventoryCountOrderService;
6
+ constructor(inventoryCountOrderService: InventoryCountOrderService);
7
+ inventoryCountOrders(args: FindInventoryCountOrderArgs): Promise<InventoryCountOrders>;
8
+ inventoryCountOrder({ id }: InventoryCountOrderIdArgs): Promise<InventoryCountOrderDto>;
9
+ }
@@ -0,0 +1,44 @@
1
+ import { __decorate, __param, __metadata } from 'tslib';
2
+ import { Injectable } from '@nestjs/common';
3
+ import { Query, Args } from '@nestjs/graphql';
4
+ import { InventoryCountOrderService } from '@rytass/wms-module-core';
5
+ import { InventoryCountOrders, InventoryCountOrderDto } from '../dto/inventory-count-order.dto.js';
6
+ import { FindInventoryCountOrderArgs, InventoryCountOrderIdArgs } from '../inputs/inventory-count-order.args.js';
7
+ import '../auth/wms-auth.guard.js';
8
+ import { WmsOperation } from '../auth/wms-operation.decorator.js';
9
+
10
+ let InventoryCountOrderQuery = class InventoryCountOrderQuery {
11
+ inventoryCountOrderService;
12
+ constructor(inventoryCountOrderService) {
13
+ this.inventoryCountOrderService = inventoryCountOrderService;
14
+ }
15
+ async inventoryCountOrders(args) {
16
+ const [items, total] = await this.inventoryCountOrderService.findMany(args);
17
+ return { items, total };
18
+ }
19
+ async inventoryCountOrder({ id }) {
20
+ return this.inventoryCountOrderService.findOne(id);
21
+ }
22
+ };
23
+ __decorate([
24
+ Query(() => InventoryCountOrders),
25
+ WmsOperation({ resource: 'inventory-count-order', action: 'read' }),
26
+ __param(0, Args()),
27
+ __metadata("design:type", Function),
28
+ __metadata("design:paramtypes", [FindInventoryCountOrderArgs]),
29
+ __metadata("design:returntype", Promise)
30
+ ], InventoryCountOrderQuery.prototype, "inventoryCountOrders", null);
31
+ __decorate([
32
+ Query(() => InventoryCountOrderDto),
33
+ WmsOperation({ resource: 'inventory-count-order', action: 'read' }),
34
+ __param(0, Args()),
35
+ __metadata("design:type", Function),
36
+ __metadata("design:paramtypes", [InventoryCountOrderIdArgs]),
37
+ __metadata("design:returntype", Promise)
38
+ ], InventoryCountOrderQuery.prototype, "inventoryCountOrder", null);
39
+ InventoryCountOrderQuery = __decorate([
40
+ Injectable(),
41
+ __metadata("design:paramtypes", [InventoryCountOrderService])
42
+ ], InventoryCountOrderQuery);
43
+
44
+ export { InventoryCountOrderQuery };
@@ -26,6 +26,7 @@ import '../dto/scrape-order.dto.js';
26
26
  import '../dto/scrape-order-item.dto.js';
27
27
  import '../dto/quality-inspection-order.dto.js';
28
28
  import '../dto/quality-inspection-order-item.dto.js';
29
+ import '../dto/inventory-count-order.dto.js';
29
30
  import { FindLoaderArgs } from '../inputs/find-loader.args.js';
30
31
  import { FindLoaderTypeArgs } from '../inputs/find-loader-type.args.js';
31
32
  import { LoaderUnitDto, LoaderUnit } from '../dto/loader-unit.dto.js';
@@ -25,6 +25,7 @@ import '../dto/scrape-order.dto.js';
25
25
  import '../dto/scrape-order-item.dto.js';
26
26
  import '../dto/quality-inspection-order.dto.js';
27
27
  import '../dto/quality-inspection-order-item.dto.js';
28
+ import '../dto/inventory-count-order.dto.js';
28
29
  import { MaterialService } from '@rytass/wms-module-core';
29
30
  import { FindMaterialArgs } from '../inputs/find-material.args.js';
30
31
  import '../auth/wms-auth.guard.js';
@@ -26,6 +26,7 @@ import '../dto/scrape-order.dto.js';
26
26
  import '../dto/scrape-order-item.dto.js';
27
27
  import '../dto/quality-inspection-order.dto.js';
28
28
  import '../dto/quality-inspection-order-item.dto.js';
29
+ import '../dto/inventory-count-order.dto.js';
29
30
  import { FindReceiveInventoryOrderArgs } from '../inputs/find-receive-inventory-order.args.js';
30
31
  import '../auth/wms-auth.guard.js';
31
32
  import { WmsOperation } from '../auth/wms-operation.decorator.js';
@@ -26,6 +26,7 @@ import '../dto/scrape-order.dto.js';
26
26
  import '../dto/scrape-order-item.dto.js';
27
27
  import '../dto/quality-inspection-order.dto.js';
28
28
  import '../dto/quality-inspection-order-item.dto.js';
29
+ import '../dto/inventory-count-order.dto.js';
29
30
  import { FindShipInventoryOrderArgs } from '../inputs/find-ship-inventory-order.args.js';
30
31
  import '../auth/wms-auth.guard.js';
31
32
  import { WmsOperation } from '../auth/wms-operation.decorator.js';
@@ -26,6 +26,7 @@ import '../dto/scrape-order.dto.js';
26
26
  import '../dto/scrape-order-item.dto.js';
27
27
  import '../dto/quality-inspection-order.dto.js';
28
28
  import '../dto/quality-inspection-order-item.dto.js';
29
+ import '../dto/inventory-count-order.dto.js';
29
30
  import { FindStockArgs } from '../inputs/find-stock.args.js';
30
31
  import '../auth/wms-auth.guard.js';
31
32
  import { WmsOperation } from '../auth/wms-operation.decorator.js';
@@ -0,0 +1 @@
1
+ export { pruneDisabledOperations, resolveDisabled, type PrunedOperations, type WmsOperationRegistrationOptions, } from './operation-registry';
@@ -0,0 +1,59 @@
1
+ import { Type } from '@nestjs/common';
2
+ import type { WmsOperationName } from '@rytass/wms-module-core';
3
+ /**
4
+ * Deployment-level switches deciding which root operations get registered.
5
+ *
6
+ * `authChecker` and `beforeHooks` can already *refuse* an operation, but the
7
+ * resolver stays in the compiled schema — so introspection, the consumer's
8
+ * frontend codegen and any security audit still see a mutation that is
9
+ * guaranteed to fail. These options remove it instead.
10
+ */
11
+ export interface WmsOperationRegistrationOptions {
12
+ /**
13
+ * Allow-list of `${resource}:${action}` names. Only these are registered.
14
+ * Mutually exclusive with {@link disabledOperations}.
15
+ */
16
+ readonly enabledOperations?: readonly WmsOperationName[];
17
+ /** Deny-list of `${resource}:${action}` names. */
18
+ readonly disabledOperations?: readonly WmsOperationName[];
19
+ /**
20
+ * Escape hatch by GraphQL field name, for when a requirement is too coarse.
21
+ * Several queries share one requirement — `loader:read` alone covers 6 fields
22
+ * — so disabling the name would take all of them. Name the field instead.
23
+ */
24
+ readonly disabledFields?: readonly string[];
25
+ }
26
+ /** What a pruning pass removed, keyed by root type. */
27
+ export interface PrunedOperations {
28
+ readonly queries: readonly string[];
29
+ readonly mutations: readonly string[];
30
+ }
31
+ export declare function resolveDisabled(options: WmsOperationRegistrationOptions): {
32
+ readonly hasSwitches: boolean;
33
+ readonly isOperationDisabled: (name: string) => boolean;
34
+ readonly disabledFields: ReadonlySet<string>;
35
+ };
36
+ /**
37
+ * Remove the switched-off root operations before the schema is built.
38
+ *
39
+ * Two edits are needed, at two different moments, and they must happen together:
40
+ *
41
+ * 1. **now** — `delete Resolver.prototype[method]`, because
42
+ * `ResolversExplorerService.explore()` walks the prototype with
43
+ * `MetadataScanner` and runs *before* the schema builder loads the lazy
44
+ * metadata. Leaving the method in place would put `Query.foo` in the resolver
45
+ * map with no matching field in the typeDefs, and `makeExecutableSchema`
46
+ * rejects the whole schema (`requireResolversToMatchSchema`).
47
+ * 2. **at load time** — drop the metadata entry ({@link installMetadataFilter}),
48
+ * or the SDL would still declare a field that resolves to `null`: present,
49
+ * but dead.
50
+ *
51
+ * Deleting the prototype method does not disturb step 2's type reflection:
52
+ * `design:returntype` is stored against the prototype and property key, not
53
+ * against the function object, so it survives the delete.
54
+ *
55
+ * This runs synchronously from `forRootAsync`, i.e. while `AppModule` is still
56
+ * being defined. Both the classes and the storage are process-global, so a
57
+ * process may register `WmsModuleGraphqlModule` only once.
58
+ */
59
+ export declare function pruneDisabledOperations(resolverClasses: readonly Type<unknown>[], options: WmsOperationRegistrationOptions): PrunedOperations;
@@ -0,0 +1,136 @@
1
+ import { RESOLVER_TYPE_METADATA, TypeMetadataStorage, RESOLVER_NAME_METADATA } from '@nestjs/graphql';
2
+ import { WMS_OPERATION_METADATA } from '../auth/wms-auth.types.js';
3
+
4
+ function resolveDisabled(options) {
5
+ const { enabledOperations, disabledOperations, disabledFields } = options;
6
+ if (enabledOperations && disabledOperations) {
7
+ throw new Error('[wms-module-graphql] `enabledOperations` and `disabledOperations` are mutually exclusive — pass one or the other, not both.');
8
+ }
9
+ const enabled = enabledOperations ? new Set(enabledOperations) : null;
10
+ const disabled = disabledOperations
11
+ ? new Set(disabledOperations)
12
+ : null;
13
+ const fields = new Set(disabledFields ?? []);
14
+ return {
15
+ hasSwitches: enabled !== null || disabled !== null || fields.size > 0,
16
+ isOperationDisabled: (name) => {
17
+ if (enabled) {
18
+ return !enabled.has(name);
19
+ }
20
+ if (disabled) {
21
+ return disabled.has(name);
22
+ }
23
+ return false;
24
+ },
25
+ disabledFields: fields,
26
+ };
27
+ }
28
+ /** Methods already pruned, so the metadata filter can drop their entries. */
29
+ const prunedMethods = new WeakMap();
30
+ let metadataFilterInstalled = false;
31
+ /**
32
+ * Stop the pruned operations from ever entering `TypeMetadataStorage`.
33
+ *
34
+ * The resolver metadata is **lazy**: `@Query()` / `@Mutation()` only register a
35
+ * thunk with `LazyMetadataStorage`, and the thunk calls `add*Metadata` when
36
+ * `GraphQLSchemaBuilder.build()` loads it. At `forRootAsync` time the storage
37
+ * arrays are therefore still empty, and filtering them then would remove
38
+ * nothing — so the filter has to sit on the writes instead.
39
+ */
40
+ function installMetadataFilter() {
41
+ if (metadataFilterInstalled) {
42
+ return;
43
+ }
44
+ const storage = TypeMetadataStorage;
45
+ const addQuery = storage.addQueryMetadata.bind(storage);
46
+ const addMutation = storage.addMutationMetadata.bind(storage);
47
+ const isPruned = (metadata) => prunedMethods.get(metadata.target)?.has(metadata.methodName) === true;
48
+ storage.addQueryMetadata = (metadata) => {
49
+ if (isPruned(metadata)) {
50
+ return;
51
+ }
52
+ addQuery(metadata);
53
+ };
54
+ storage.addMutationMetadata = (metadata) => {
55
+ if (isPruned(metadata)) {
56
+ return;
57
+ }
58
+ addMutation(metadata);
59
+ };
60
+ metadataFilterInstalled = true;
61
+ }
62
+ /** The GraphQL field name a root handler ends up under. */
63
+ function schemaNameOf(handler, methodName) {
64
+ const explicit = Reflect.getMetadata(RESOLVER_NAME_METADATA, handler);
65
+ return explicit || methodName;
66
+ }
67
+ /**
68
+ * Remove the switched-off root operations before the schema is built.
69
+ *
70
+ * Two edits are needed, at two different moments, and they must happen together:
71
+ *
72
+ * 1. **now** — `delete Resolver.prototype[method]`, because
73
+ * `ResolversExplorerService.explore()` walks the prototype with
74
+ * `MetadataScanner` and runs *before* the schema builder loads the lazy
75
+ * metadata. Leaving the method in place would put `Query.foo` in the resolver
76
+ * map with no matching field in the typeDefs, and `makeExecutableSchema`
77
+ * rejects the whole schema (`requireResolversToMatchSchema`).
78
+ * 2. **at load time** — drop the metadata entry ({@link installMetadataFilter}),
79
+ * or the SDL would still declare a field that resolves to `null`: present,
80
+ * but dead.
81
+ *
82
+ * Deleting the prototype method does not disturb step 2's type reflection:
83
+ * `design:returntype` is stored against the prototype and property key, not
84
+ * against the function object, so it survives the delete.
85
+ *
86
+ * This runs synchronously from `forRootAsync`, i.e. while `AppModule` is still
87
+ * being defined. Both the classes and the storage are process-global, so a
88
+ * process may register `WmsModuleGraphqlModule` only once.
89
+ */
90
+ function pruneDisabledOperations(resolverClasses, options) {
91
+ const { hasSwitches, isOperationDisabled, disabledFields } = resolveDisabled(options);
92
+ if (!hasSwitches) {
93
+ return { queries: [], mutations: [] };
94
+ }
95
+ installMetadataFilter();
96
+ const queries = [];
97
+ const mutations = [];
98
+ for (const resolverClass of resolverClasses) {
99
+ const prototype = resolverClass.prototype;
100
+ if (!prototype) {
101
+ continue;
102
+ }
103
+ for (const methodName of Object.getOwnPropertyNames(prototype)) {
104
+ if (methodName === 'constructor') {
105
+ continue;
106
+ }
107
+ const handler = prototype[methodName];
108
+ if (typeof handler !== 'function') {
109
+ continue;
110
+ }
111
+ const resolverType = Reflect.getMetadata(RESOLVER_TYPE_METADATA, handler);
112
+ // Only root operations are switchable. `@ResolveField` handlers are
113
+ // reached exclusively through an already-registered root field, so
114
+ // removing one would break the type rather than the deployment surface.
115
+ if (resolverType !== 'Query' && resolverType !== 'Mutation') {
116
+ continue;
117
+ }
118
+ const schemaName = schemaNameOf(handler, methodName);
119
+ const requirement = Reflect.getMetadata(WMS_OPERATION_METADATA, handler);
120
+ const disabled = disabledFields.has(schemaName) ||
121
+ (requirement !== undefined &&
122
+ isOperationDisabled(`${requirement.resource}:${requirement.action}`));
123
+ if (!disabled) {
124
+ continue;
125
+ }
126
+ const alreadyPruned = prunedMethods.get(resolverClass) ?? new Set();
127
+ alreadyPruned.add(methodName);
128
+ prunedMethods.set(resolverClass, alreadyPruned);
129
+ delete prototype[methodName];
130
+ (resolverType === 'Query' ? queries : mutations).push(schemaName);
131
+ }
132
+ }
133
+ return { queries, mutations };
134
+ }
135
+
136
+ export { pruneDisabledOperations, resolveDisabled };
@@ -24,6 +24,7 @@ import '../dto/scrape-order.dto.js';
24
24
  import '../dto/scrape-order-item.dto.js';
25
25
  import '../dto/quality-inspection-order.dto.js';
26
26
  import '../dto/quality-inspection-order-item.dto.js';
27
+ import '../dto/inventory-count-order.dto.js';
27
28
  import { StockService, WmsEntities, BatchGroupEntityClass, LoadersEntityClass } from '@rytass/wms-module-core';
28
29
  import { BatchDto } from '../dto/batch.dto.js';
29
30
  import { LocationDto } from '../dto/location.dto.js';
@@ -24,6 +24,7 @@ import '../dto/scrape-order.dto.js';
24
24
  import '../dto/scrape-order-item.dto.js';
25
25
  import '../dto/quality-inspection-order.dto.js';
26
26
  import '../dto/quality-inspection-order-item.dto.js';
27
+ import '../dto/inventory-count-order.dto.js';
27
28
  import { StockEntityClass, WmsEntities, BatchGroupEntityClass } from '@rytass/wms-module-core';
28
29
  import { LocationDto } from '../dto/location.dto.js';
29
30
  import { BatchDto } from '../dto/batch.dto.js';
@@ -0,0 +1,34 @@
1
+ import { BatchEntityClass, InventoryCountOrderItemEntityClass, InventoryCountOrderLocationEntityClass, LoadersEntityClass, LocationEntityClass, MaterialEntityClass, WmsEntities } from '@rytass/wms-module-core';
2
+ import { InventoryCountOrderDto, InventoryCountOrderItemDto } from '../dto/inventory-count-order.dto';
3
+ import { BatchDto } from '../dto/batch.dto';
4
+ import { LoaderDto } from '../dto/loader.dto';
5
+ import { LocationDto } from '../dto/location.dto';
6
+ import { MaterialDto } from '../dto/material.dto';
7
+ import { type LoaderType } from '../helpers';
8
+ export declare class InventoryCountOrderResolver {
9
+ private readonly entities;
10
+ constructor(entities: WmsEntities);
11
+ items({ id }: InventoryCountOrderDto, { loaders }: LoaderType<InventoryCountOrderItemEntityClass>): Promise<InventoryCountOrderItemDto[]>;
12
+ /**
13
+ * The locations the user picked.
14
+ *
15
+ * Only the roots: the scope table also holds every descendant the backend
16
+ * expanded into, and listing a whole aisle's shelves as chips would bury the
17
+ * one thing the operator actually chose. The expansion still exists in the
18
+ * database — it is what the lock reads — it just is not this field.
19
+ */
20
+ locations({ id }: InventoryCountOrderDto, { loaders }: LoaderType<InventoryCountOrderLocationEntityClass>): Promise<LocationDto[]>;
21
+ }
22
+ export declare class InventoryCountOrderItemResolver {
23
+ private readonly entities;
24
+ /**
25
+ * The configured entities, not the built-in classes: `__entity` decides which
26
+ * repository the DataLoader opens, so it has to follow whatever the consumer
27
+ * passed to `WMSBaseModuleOptions`.
28
+ */
29
+ constructor(entities: WmsEntities);
30
+ material({ materialId }: InventoryCountOrderItemDto, { loaders }: LoaderType<MaterialEntityClass>): Promise<MaterialDto>;
31
+ batch({ batchId }: InventoryCountOrderItemDto, { loaders }: LoaderType<BatchEntityClass>): Promise<BatchDto>;
32
+ location({ locationId }: InventoryCountOrderItemDto, { loaders }: LoaderType<LocationEntityClass>): Promise<LocationDto> | null;
33
+ loader({ loaderId }: InventoryCountOrderItemDto, { loaders }: LoaderType<LoadersEntityClass>): Promise<LoaderDto> | null;
34
+ }