@rytass/wms-module-graphql 0.2.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 +75 -29
- package/adapters/member-base.d.ts +35 -0
- package/adapters/member-base.js +47 -0
- package/docs/README.md +6 -3
- package/docs/api-reference.md +143 -11
- package/docs/authorization.md +349 -0
- package/docs/integration-guide.md +155 -84
- package/index.cjs.js +177 -6
- package/index.d.ts +2 -0
- package/index.js +4 -0
- package/lib/auth/host-skip.constant.d.ts +27 -0
- package/lib/auth/host-skip.constant.js +29 -0
- package/lib/auth/index.d.ts +4 -0
- package/lib/auth/wms-auth.guard.d.ts +19 -0
- package/lib/auth/wms-auth.guard.js +41 -0
- package/lib/auth/wms-auth.types.d.ts +36 -0
- package/lib/auth/wms-auth.types.js +6 -0
- package/lib/auth/wms-operation.decorator.d.ts +23 -0
- package/lib/auth/wms-operation.decorator.js +29 -0
- package/lib/graphql.module.d.ts +8 -1
- package/lib/graphql.module.js +12 -3
- package/lib/helpers/create-wms-loaders.d.ts +3 -1
- package/lib/helpers/create-wms-loaders.js +5 -3
- package/lib/mutations/allocate-inventory-order.mutation.js +5 -0
- package/lib/mutations/hold-inventory-order.mutation.js +5 -0
- package/lib/mutations/loader.mutation.js +7 -0
- package/lib/mutations/location.mutation.js +4 -0
- package/lib/mutations/material.mutation.js +4 -0
- package/lib/mutations/merge-batch.mutation.js +3 -0
- package/lib/mutations/quality-inspection-order.mutation.js +3 -0
- package/lib/mutations/receive-inventory-order.mutation.js +5 -0
- package/lib/mutations/reclassify-inventory-order.mutation.js +3 -0
- package/lib/mutations/scrape-order.mutation.js +3 -0
- package/lib/mutations/ship-inventory-order.mutation.js +6 -0
- package/lib/mutations/split-batch.mutation.js +3 -0
- package/lib/mutations/transfer-customer-order.mutation.js +5 -0
- package/lib/mutations/transfer-order.mutation.js +6 -0
- package/lib/mutations/transfer-vendor-order.mutation.js +5 -0
- package/lib/mutations/warehouse-map.mutation.js +3 -0
- package/lib/queries/allocate-inventory-order.query.js +3 -0
- package/lib/queries/batch.query.js +3 -0
- package/lib/queries/hold-inventory-order.query.js +3 -0
- package/lib/queries/loader.query.js +8 -0
- package/lib/queries/location.query.js +4 -0
- package/lib/queries/material.query.js +4 -0
- package/lib/queries/recieve-inventory-order.query.js +4 -0
- package/lib/queries/sale-order.query.js +4 -0
- package/lib/queries/ship-inventory-order.query.js +4 -0
- package/lib/queries/stock.query.js +7 -0
- package/lib/queries/transfer-order.query.js +4 -0
- package/lib/queries/unit.query.js +3 -0
- package/lib/queries/warehouse-map.query.js +3 -0
- package/package.json +5 -1
|
@@ -40,8 +40,8 @@ WMS is packaged as three layered npm libraries:
|
|
|
40
40
|
v
|
|
41
41
|
+-------------------------------+
|
|
42
42
|
| wms-module-graphql | Resolvers, DTOs, DataLoader helpers
|
|
43
|
-
| (
|
|
44
|
-
|
|
|
43
|
+
| (composable providers + your | ---------------------------------------
|
|
44
|
+
| own GraphQLModule.forRoot) | Exposes resolvers; depends on core for
|
|
45
45
|
+--------------+----------------+ entities + services.
|
|
46
46
|
v
|
|
47
47
|
+-------------------------------+
|
|
@@ -138,13 +138,18 @@ bootstrap();
|
|
|
138
138
|
|
|
139
139
|
### 4.2 `apps/api/src/app/app.module.ts`
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
Two registrations: `WmsModuleGraphqlModule.forRootAsync(...)` wires the WMS resolvers, entities, services and `LoaderService`; your own `GraphQLModule.forRootAsync(...)` starts Apollo Server and owns the context factory. The two participate in **one** schema — NestJS's schema builder discovers every `@Resolver()` provider across all imported modules.
|
|
142
142
|
|
|
143
143
|
```ts
|
|
144
144
|
import { Module } from '@nestjs/common';
|
|
145
145
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
146
146
|
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
|
|
147
|
-
import {
|
|
147
|
+
import { GraphQLModule } from '@nestjs/graphql';
|
|
148
|
+
import {
|
|
149
|
+
WmsModuleGraphqlModule,
|
|
150
|
+
LoaderService,
|
|
151
|
+
createWmsLoaders,
|
|
152
|
+
} from '@rytass/wms-module-graphql';
|
|
148
153
|
import { ApolloDriver } from '@nestjs/apollo';
|
|
149
154
|
import {
|
|
150
155
|
ApolloServerPluginLandingPageLocalDefault,
|
|
@@ -173,40 +178,46 @@ import { resolve } from 'path';
|
|
|
173
178
|
}),
|
|
174
179
|
}),
|
|
175
180
|
|
|
176
|
-
// WMS
|
|
177
|
-
WmsModuleGraphqlModule.forRootAsync(
|
|
178
|
-
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
181
|
+
// WMS resolvers + LoaderService — no Apollo Server is started here
|
|
182
|
+
WmsModuleGraphqlModule.forRootAsync({
|
|
183
|
+
useFactory: async () => ({}),
|
|
184
|
+
// Module-init seed values; the keys you pass here are created
|
|
185
|
+
// on first boot for `location`, `loaderType`, and `loader`.
|
|
186
|
+
defaultLoaderSerialId: 'DEFAULT',
|
|
187
|
+
defaultLoaderTypeKey: 'DEFAULT',
|
|
188
|
+
defaultLocationKey: 'DEFAULT',
|
|
189
|
+
}),
|
|
190
|
+
|
|
191
|
+
// YOUR Apollo / Schema / Context registration
|
|
192
|
+
GraphQLModule.forRootAsync({
|
|
193
|
+
driver: ApolloDriver,
|
|
194
|
+
inject: [LoaderService],
|
|
195
|
+
useFactory: (loaderService: LoaderService) => ({
|
|
196
|
+
playground: false,
|
|
197
|
+
introspection: true,
|
|
198
|
+
cors: true,
|
|
199
|
+
csrfPrevention: false,
|
|
200
|
+
plugins: [ApolloServerPluginLandingPageLocalDefault()],
|
|
201
|
+
autoTransformHttpErrors: true,
|
|
202
|
+
autoSchemaFile: resolve(process.cwd(), 'schema.gql'),
|
|
203
|
+
context: ({ req }) => ({
|
|
204
|
+
...createWmsLoaders(loaderService), // per-request DataLoaders
|
|
205
|
+
// your own context fields — fully preserved
|
|
206
|
+
user: req.user,
|
|
196
207
|
}),
|
|
197
|
-
},
|
|
198
|
-
),
|
|
208
|
+
}),
|
|
209
|
+
}),
|
|
199
210
|
],
|
|
200
211
|
})
|
|
201
212
|
export class AppModule {}
|
|
202
213
|
```
|
|
203
214
|
|
|
204
|
-
What
|
|
215
|
+
What this registration wires:
|
|
205
216
|
|
|
206
217
|
- 50 TypeORM entities (material, batch, loader, location, every order kind, change logs, signatures, etc.)
|
|
207
218
|
- ~100 GraphQL types
|
|
208
219
|
- ~65 queries and mutations
|
|
209
|
-
- DataLoader N+1 prevention across every resolveField
|
|
220
|
+
- DataLoader N+1 prevention across every `resolveField` (via the `loaders` key in context)
|
|
210
221
|
- Default seed rows (DEFAULT location, DEFAULT loaderType, DEFAULT loader) on first boot
|
|
211
222
|
|
|
212
223
|
**`forRootAsync` TypeScript signature**:
|
|
@@ -214,21 +225,16 @@ What you get from this single `forRootAsync`:
|
|
|
214
225
|
```ts
|
|
215
226
|
WmsModuleGraphqlModule.forRootAsync(
|
|
216
227
|
options: WmsModuleCoreModuleAsyncOptions,
|
|
217
|
-
gqlOptions: GqlModuleAsyncOptions<ApolloDriverConfig>,
|
|
218
228
|
): DynamicModule
|
|
219
229
|
```
|
|
220
230
|
|
|
221
|
-
|
|
222
|
-
> (matching NestJS's typical convention) which produces a misleading
|
|
223
|
-
> `TypeError: Cannot read properties of undefined (reading 'imports')` from inside the lib.
|
|
224
|
-
> The first arg configures the WMS core module (seed defaults, async factory, etc.); the
|
|
225
|
-
> second arg configures the underlying NestJS GraphQL module (driver, autoSchemaFile, plugins).
|
|
231
|
+
A single argument — the WMS core module options (seed defaults, async factory). All GraphQL-server concerns (driver, schema file, context factory, plugins) live in your own `GraphQLModule.forRootAsync(...)` next to it.
|
|
226
232
|
|
|
227
|
-
See [API Reference - wms-module-graphql](./api-reference.md) for the full `
|
|
233
|
+
See [API Reference - wms-module-graphql](./api-reference.md) for the full export catalog including `LoaderService`, `createWmsLoaders`, `LoaderType<T>` and `WmsLoaders`.
|
|
228
234
|
|
|
229
235
|
### Adding your own resolvers alongside WMS
|
|
230
236
|
|
|
231
|
-
|
|
237
|
+
Your `GraphQLModule.forRootAsync(...)` registration **is** the single workspace-wide GraphQL module — no constraint from `WmsModuleGraphqlModule` (the lib intentionally does **not** call `GraphQLModule.forRoot` internally). Put your resolvers in normal NestJS modules and import them next to `WmsModuleGraphqlModule`:
|
|
232
238
|
|
|
233
239
|
```ts
|
|
234
240
|
// apps/api/src/modules/posts/posts.module.ts
|
|
@@ -246,14 +252,14 @@ export class PostsModule {}
|
|
|
246
252
|
// apps/api/src/app/app.module.ts
|
|
247
253
|
@Module({
|
|
248
254
|
imports: [
|
|
249
|
-
/* ... TypeOrm, Config, WmsModuleGraphqlModule ... */
|
|
255
|
+
/* ... TypeOrm, Config, WmsModuleGraphqlModule, GraphQLModule ... */
|
|
250
256
|
PostsModule, // your sibling module
|
|
251
257
|
],
|
|
252
258
|
})
|
|
253
259
|
export class AppModule {}
|
|
254
260
|
```
|
|
255
261
|
|
|
256
|
-
NestJS's GraphQL module discovers every `@Resolver()` class from every imported module via DI and merges them into the **same** schema. So your `Post`/`User` resolvers coexist in one schema with the WMS resolvers automatically — no extra wiring needed.
|
|
262
|
+
NestJS's GraphQL module discovers every `@Resolver()` class from every imported module via DI and merges them into the **same** schema. So your `Post`/`User` resolvers coexist in one schema with the WMS resolvers automatically — no extra wiring needed.
|
|
257
263
|
|
|
258
264
|
### 4.3 `.env`
|
|
259
265
|
|
|
@@ -735,7 +741,7 @@ The full list of generated `Document` constants and their types is in
|
|
|
735
741
|
|
|
736
742
|
## 8. Authentication / authorization
|
|
737
743
|
|
|
738
|
-
The lib
|
|
744
|
+
The lib ships **no frontend auth** — the page components assume they render in an authenticated context and call queries on mount without checking session state. On the **backend**, `@rytass/wms-module-graphql` ships an *opt-in, host-neutral authorization protocol* you wire to your own permission system (member-base / Casbin / JWT / anything). See [§8.5 Backend authorization](#85-backend-authorization-resolver-level).
|
|
739
745
|
|
|
740
746
|
### 8.1 Stub for demos
|
|
741
747
|
|
|
@@ -823,7 +829,43 @@ Replace the `AuthGuard` stub with your own logic that:
|
|
|
823
829
|
2. Provides member identity to GraphQL via the Apollo client's `context` link.
|
|
824
830
|
3. Handles 401 responses (logout / redirect).
|
|
825
831
|
|
|
826
|
-
|
|
832
|
+
### 8.5 Backend authorization (resolver-level)
|
|
833
|
+
|
|
834
|
+
> 📖 This is the condensed version. The full design — execution order, member-base / custom-JWT / no-guard recipes, the single coupling point, the exported API, and a troubleshooting FAQ — lives in [**`docs/authorization.md`**](./authorization.md).
|
|
835
|
+
|
|
836
|
+
Every WMS root `@Query` / `@Mutation` is annotated with `@WmsOperation({ resource, action })` — a host-neutral permission requirement. The library enforces it through its own route-level `WmsAuthGuard`, which delegates the actual allow/deny decision to an `authChecker` **you** supply at module registration. The library never imports your auth system; you map WMS's `resource`/`action` onto whatever your system understands.
|
|
837
|
+
|
|
838
|
+
> ⚠️ **The global-guard pitfall.** A deny-by-default global guard — e.g. the `CasbinGuard` that `@rytass/member-base-nestjs-module` registers as `APP_GUARD` — blankets *every* resolver in the compiled schema, including WMS's. Because WMS resolvers carry no host-specific permission metadata, such a guard rejects them all ("every WMS query/mutation is forbidden"). WMS solves this by stamping each operation with a host-skip marker (default: member-base's `IS_ROUTE_PUBLIC`) so the global guard defers, while `WmsAuthGuard` does the real enforcement. **You do not need to touch your global guard.**
|
|
839
|
+
|
|
840
|
+
#### Wire it up (member-base / Casbin)
|
|
841
|
+
|
|
842
|
+
```ts
|
|
843
|
+
// app.module.ts
|
|
844
|
+
import { WmsModuleGraphqlModule } from '@rytass/wms-module-graphql';
|
|
845
|
+
import { createMemberBaseWmsAuthChecker } from '@rytass/wms-module-graphql/adapters/member-base';
|
|
846
|
+
|
|
847
|
+
WmsModuleGraphqlModule.forRootAsync({
|
|
848
|
+
// ...existing core options (defaultLoaderSerialId, useFactory, etc.)...
|
|
849
|
+
authChecker: createMemberBaseWmsAuthChecker({
|
|
850
|
+
// Map WMS resource/action onto your Casbin [subject, action] tuples.
|
|
851
|
+
// Return multiple tuples to mean "allow if ANY passes" (OR semantics).
|
|
852
|
+
map: ({ resource, action }) => [[`wms:${resource}`, action]],
|
|
853
|
+
// e.g. material:read -> enforce(memberId, domain, 'wms:material', 'read')
|
|
854
|
+
}),
|
|
855
|
+
});
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
The member-base adapter reuses everything `CasbinGuard` already prepared on the request (the verified `payload`, the `enforcer`, and your possibly-customized `casbinPermissionChecker`), so WMS enforces with the **exact same** policy engine as your own resolvers — with zero member-base import on the WMS side. Requirement: keep member-base's global guard enabled (default) and expose the request on the GraphQL context as `req` (Apollo's default).
|
|
859
|
+
|
|
860
|
+
#### Other auth systems
|
|
861
|
+
|
|
862
|
+
`authChecker` is a plain function — `(execContext, { resource, action }) => boolean | Promise<boolean>`. For JWT/RBAC without Casbin, read your session off the `ExecutionContext` and decide there. If your global guard uses a different "public/skip" metadata key than member-base's `IS_ROUTE_PUBLIC`, change the single `HOST_SKIP_METADATA_KEY` constant in `libs/graphql/src/lib/auth/host-skip.constant.ts`.
|
|
863
|
+
|
|
864
|
+
#### No global guard at all
|
|
865
|
+
|
|
866
|
+
If you omit `authChecker`, the module stays fully permissive (handy for local dev). If you protect your own resolvers with explicit `@UseGuards(...)` instead of a global `APP_GUARD`, the host-skip marker is simply inert and WMS still self-enforces through `authChecker`.
|
|
867
|
+
|
|
868
|
+
The WMS `resource`/`action` strings are **internal metadata only** — they are not part of the GraphQL schema, so refining them later is not a breaking change for GraphQL consumers (it only affects your `map`).
|
|
827
869
|
|
|
828
870
|
---
|
|
829
871
|
|
|
@@ -960,37 +1002,59 @@ This section covers the real-world scenarios where the WMS modules are added to
|
|
|
960
1002
|
that already has its own NestJS backend, GraphQL setup, or Next.js frontend. The greenfield
|
|
961
1003
|
setup in sections 4-7 is the baseline; read this section for the delta.
|
|
962
1004
|
|
|
963
|
-
> **Scope**: 0.1.x.
|
|
964
|
-
>
|
|
1005
|
+
> **Scope**: 0.3.0+. Earlier 0.1.x / 0.2.0 limitations around `GraphQLModule` co-existence have
|
|
1006
|
+
> been removed by the user-driven composition refactor — see §13.1.
|
|
965
1007
|
|
|
966
1008
|
### 13.1 Coexisting with an existing `GraphQLModule`
|
|
967
1009
|
|
|
968
|
-
**Status**:
|
|
969
|
-
|
|
970
|
-
`WmsModuleGraphqlModule.forRootAsync(...)` internally calls `GraphQLModule.forRootAsync(...)`.
|
|
971
|
-
NestJS does not allow two `GraphQLModule` registrations in the same application — the second
|
|
972
|
-
registration throws `Error: Cannot register 2 GraphQL modules`. If your host app already
|
|
973
|
-
imports `GraphQLModule`, you cannot simply add `WmsModuleGraphqlModule` to the same
|
|
974
|
-
`imports: [...]` array.
|
|
1010
|
+
**Status**: Fully supported since 0.3.0.
|
|
975
1011
|
|
|
976
|
-
|
|
1012
|
+
`WmsModuleGraphqlModule.forRootAsync(...)` only registers providers (resolvers, `LoaderService`,
|
|
1013
|
+
core module) — it does **not** call `GraphQLModule.forRoot` internally. The host application
|
|
1014
|
+
registers a **single** `GraphQLModule.forRootAsync(...)` of its own. NestJS's schema builder
|
|
1015
|
+
walks the DI container at boot, collects every `@Resolver()` class from every imported module,
|
|
1016
|
+
and merges them into one schema.
|
|
977
1017
|
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1018
|
+
This means a host app with an existing GraphQL server just adds `WmsModuleGraphqlModule` next to
|
|
1019
|
+
its existing `GraphQLModule.forRootAsync(...)`. To preserve N+1 prevention for the WMS resolvers,
|
|
1020
|
+
the host must inject `LoaderService` into its own context factory and call `createWmsLoaders(...)`
|
|
1021
|
+
per request:
|
|
981
1022
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1023
|
+
```ts
|
|
1024
|
+
import {
|
|
1025
|
+
WmsModuleGraphqlModule,
|
|
1026
|
+
LoaderService,
|
|
1027
|
+
createWmsLoaders,
|
|
1028
|
+
} from '@rytass/wms-module-graphql';
|
|
985
1029
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1030
|
+
@Module({
|
|
1031
|
+
imports: [
|
|
1032
|
+
// ... your existing modules ...
|
|
1033
|
+
WmsModuleGraphqlModule.forRootAsync({
|
|
1034
|
+
useFactory: async () => ({}),
|
|
1035
|
+
defaultLoaderSerialId: 'DEFAULT',
|
|
1036
|
+
defaultLoaderTypeKey: 'DEFAULT',
|
|
1037
|
+
defaultLocationKey: 'DEFAULT',
|
|
1038
|
+
}),
|
|
1039
|
+
GraphQLModule.forRootAsync({
|
|
1040
|
+
driver: ApolloDriver,
|
|
1041
|
+
inject: [LoaderService, /* your existing deps */],
|
|
1042
|
+
useFactory: (loaderService: LoaderService /* , ... */) => ({
|
|
1043
|
+
autoSchemaFile: 'schema.gql',
|
|
1044
|
+
context: ({ req }) => ({
|
|
1045
|
+
...createWmsLoaders(loaderService), // WMS DataLoader trio
|
|
1046
|
+
user: req.user, // your existing context fields
|
|
1047
|
+
// ... any other context shape you already had ...
|
|
1048
|
+
}),
|
|
1049
|
+
}),
|
|
1050
|
+
}),
|
|
1051
|
+
],
|
|
1052
|
+
})
|
|
1053
|
+
export class AppModule {}
|
|
1054
|
+
```
|
|
990
1055
|
|
|
991
|
-
**
|
|
992
|
-
|
|
993
|
-
the same process.
|
|
1056
|
+
**Type name conflicts**: still a separate concern — see §13.14. The shared-schema model means
|
|
1057
|
+
your `type Material`, `type Location`, etc. must not collide with the WMS counterparts.
|
|
994
1058
|
|
|
995
1059
|
---
|
|
996
1060
|
|
|
@@ -1128,26 +1192,34 @@ export class AppModule {}
|
|
|
1128
1192
|
|
|
1129
1193
|
This applies your guard to every resolver, including WMS resolvers.
|
|
1130
1194
|
|
|
1131
|
-
**Option B**:
|
|
1132
|
-
object is spread directly into the GraphQL context by the lib's internal DataLoader injection
|
|
1133
|
-
logic. Any field set on `req` by a NestJS guard or Passport strategy (e.g. `req.user`) is
|
|
1134
|
-
therefore accessible from resolvers as `ctx.req.user`.
|
|
1195
|
+
**Option B**: Surface the authenticated user through your **own** GraphQL context factory. Since 0.3.0 you own the entire `GraphQLModule.forRootAsync(...)` registration, including `context`. Both `context.user` (returned directly from your factory) and `context.req.user` (set by a guard / Passport on Express) work — pick whichever your resolvers prefer:
|
|
1135
1196
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1197
|
+
```ts
|
|
1198
|
+
GraphQLModule.forRootAsync({
|
|
1199
|
+
driver: ApolloDriver,
|
|
1200
|
+
inject: [LoaderService],
|
|
1201
|
+
useFactory: (loaderService: LoaderService) => ({
|
|
1202
|
+
autoSchemaFile: 'schema.gql',
|
|
1203
|
+
context: ({ req }) => ({
|
|
1204
|
+
...createWmsLoaders(loaderService), // WMS DataLoader trio
|
|
1205
|
+
user: req.user, // directly accessible as ctx.user
|
|
1206
|
+
// ...any other fields you want on context
|
|
1207
|
+
}),
|
|
1208
|
+
}),
|
|
1209
|
+
})
|
|
1210
|
+
```
|
|
1211
|
+
|
|
1212
|
+
| Approach | Works? |
|
|
1213
|
+
|---------------------------------------------------------|--------|
|
|
1214
|
+
| Return `context: () => ({ user, ...createWmsLoaders(svc) })` | ✅ user fully controls context |
|
|
1215
|
+
| Populate `req.user` via NestJS guard / Passport | ✅ access via `context.req.user` |
|
|
1216
|
+
|
|
1217
|
+
> **0.1.x behavior gone**: earlier releases of this lib silently replaced any `context` factory
|
|
1218
|
+
> you supplied because `WmsModuleGraphqlModule` registered Apollo Server itself. Since 0.3.0,
|
|
1219
|
+
> the lib only exposes providers and your `GraphQLModule.forRootAsync(...)` is the single
|
|
1220
|
+
> registration — there is no internal override anymore.
|
|
1148
1221
|
|
|
1149
|
-
To access the authenticated user in a **custom** resolver,
|
|
1150
|
-
or middleware and read it from `ctx.req.user`:
|
|
1222
|
+
To access the authenticated user in a **custom** resolver, either read it directly from `ctx.user` (if you put it there in your factory) or from `ctx.req.user` (if a guard set it on the request):
|
|
1151
1223
|
|
|
1152
1224
|
```ts
|
|
1153
1225
|
// auth.guard.ts — populate req.user before the resolver runs
|
|
@@ -1631,8 +1703,7 @@ The viable options are the same as those described in §13.1:
|
|
|
1631
1703
|
3. **Wait for a future major release** — a type prefix configuration option is a candidate
|
|
1632
1704
|
for a future major version that introduces namespace support.
|
|
1633
1705
|
|
|
1634
|
-
|
|
1635
|
-
both APIs in the same process is not supported in 0.1.x.
|
|
1706
|
+
Unlike the §13.1 `GraphQLModule` co-existence story (fixed in 0.3.0), the type-name collision is a **shared-schema** problem: every `@Resolver()` provider in the DI container, WMS or host-app, contributes to the same `GraphQLSchema` instance. Renaming the host app's types away from WMS-occupied names is the only fix without splitting processes.
|
|
1636
1707
|
|
|
1637
1708
|
|
|
1638
1709
|
## 14. Reference implementation (`wms-standalone`)
|
|
@@ -1647,7 +1718,7 @@ wms-standalone/
|
|
|
1647
1718
|
api/
|
|
1648
1719
|
src/
|
|
1649
1720
|
main.ts 17 LOC NestJS bootstrap
|
|
1650
|
-
app/app.module.ts
|
|
1721
|
+
app/app.module.ts 60 LOC WmsModuleGraphqlModule + GraphQLModule.forRootAsync
|
|
1651
1722
|
.env 6 LOC PG credentials
|
|
1652
1723
|
package.json
|
|
1653
1724
|
client/
|