@rytass/wms-module-graphql 0.1.3 → 0.1.5
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/docs/integration-guide.md +116 -7
- package/package.json +3 -3
|
@@ -68,6 +68,24 @@ The reference consumer ([`wms-standalone`](#13-reference-implementation-wms-stan
|
|
|
68
68
|
|
|
69
69
|
The frontend package (`wms-module-react`) is **ESM-only** (`"type": "module"`). Bundlers that target Next.js / Vite / webpack 5 handle this transparently; classic CJS-only Node tools do not.
|
|
70
70
|
|
|
71
|
+
### 2.1 pnpm build-script approval
|
|
72
|
+
|
|
73
|
+
If you are on **pnpm 9 or newer**, the first `pnpm install` will refuse to run native build scripts for several transitive dependencies and surface `ERR_PNPM_IGNORED_BUILDS`. This is pnpm's supply-chain protection, not a WMS issue, but it is the very first error a fresh integrator hits.
|
|
74
|
+
|
|
75
|
+
Resolve it once by approving the packages WMS transitively needs to build:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm approve-builds
|
|
79
|
+
# Or, in pnpm-workspace.yaml:
|
|
80
|
+
# allowBuilds:
|
|
81
|
+
# '@apollo/protobufjs': true
|
|
82
|
+
# '@nestjs/core': true
|
|
83
|
+
# '@parcel/watcher': true
|
|
84
|
+
# sharp: true
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
After approval, `pnpm install` completes cleanly. The exact list pnpm asks you to approve depends on your other dependencies; the four above are the ones triggered by WMS's NestJS + Apollo + native-image stack.
|
|
88
|
+
|
|
71
89
|
---
|
|
72
90
|
|
|
73
91
|
## 3. Quick start (60 seconds)
|
|
@@ -78,7 +96,7 @@ mkdir my-wms && cd my-wms
|
|
|
78
96
|
pnpm init
|
|
79
97
|
pnpm add @rytass/wms-module-core @rytass/wms-module-graphql @rytass/wms-module-react
|
|
80
98
|
pnpm add @nestjs/common @nestjs/core @nestjs/graphql @nestjs/typeorm \
|
|
81
|
-
@nestjs/apollo @nestjs/config @nestjs/platform-express @apollo/server@^4 \
|
|
99
|
+
@nestjs/apollo@~13.1.0 @nestjs/config @nestjs/platform-express @apollo/server@^4 \
|
|
82
100
|
typeorm pg reflect-metadata graphql rxjs \
|
|
83
101
|
class-transformer class-validator \
|
|
84
102
|
@as-integrations/express5
|
|
@@ -191,8 +209,52 @@ What you get from this single `forRootAsync`:
|
|
|
191
209
|
- DataLoader N+1 prevention across every resolveField
|
|
192
210
|
- Default seed rows (DEFAULT location, DEFAULT loaderType, DEFAULT loader) on first boot
|
|
193
211
|
|
|
212
|
+
**`forRootAsync` TypeScript signature**:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
WmsModuleGraphqlModule.forRootAsync(
|
|
216
|
+
options: WmsModuleCoreModuleAsyncOptions,
|
|
217
|
+
gqlOptions: GqlModuleAsyncOptions<ApolloDriverConfig>,
|
|
218
|
+
): DynamicModule
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> Note the **two positional arguments**. A common mistake is to pass a single options object
|
|
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).
|
|
226
|
+
|
|
194
227
|
See [API Reference - wms-module-graphql](./api-reference.md) for the full `forRootAsync` signature.
|
|
195
228
|
|
|
229
|
+
### Adding your own resolvers alongside WMS
|
|
230
|
+
|
|
231
|
+
`WmsModuleGraphqlModule` calls `GraphQLModule.forRootAsync(...)` internally — that registration is workspace-global, so you cannot register a second `GraphQLModule` (see §13.1). What you **can** do is put your own resolvers in **sibling NestJS modules** imported in `AppModule`:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
// apps/api/src/modules/posts/posts.module.ts
|
|
235
|
+
import { Module } from '@nestjs/common';
|
|
236
|
+
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
237
|
+
import { Post } from './post.entity';
|
|
238
|
+
import { PostResolver } from './post.resolver';
|
|
239
|
+
|
|
240
|
+
@Module({
|
|
241
|
+
imports: [TypeOrmModule.forFeature([Post])],
|
|
242
|
+
providers: [PostResolver],
|
|
243
|
+
})
|
|
244
|
+
export class PostsModule {}
|
|
245
|
+
|
|
246
|
+
// apps/api/src/app/app.module.ts
|
|
247
|
+
@Module({
|
|
248
|
+
imports: [
|
|
249
|
+
/* ... TypeOrm, Config, WmsModuleGraphqlModule ... */
|
|
250
|
+
PostsModule, // your sibling module
|
|
251
|
+
],
|
|
252
|
+
})
|
|
253
|
+
export class AppModule {}
|
|
254
|
+
```
|
|
255
|
+
|
|
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. The §13.1 "one GraphQLModule" constraint only forbids a second `GraphQLModule.forRoot(...)` registration, not additional resolvers.
|
|
257
|
+
|
|
196
258
|
### 4.3 `.env`
|
|
197
259
|
|
|
198
260
|
Keep DB credentials in `.env` (and add it to `.gitignore`).
|
|
@@ -284,7 +346,7 @@ Tested combinations as of 0.1.2:
|
|
|
284
346
|
|----------------------------------|-------------------------|--------------------------------------------------------------------|
|
|
285
347
|
| NestJS (`@nestjs/*`) | 11.x | 10.x untested; some Express-5-related APIs differ |
|
|
286
348
|
| `@nestjs/graphql` | 13.x | Required for `@nestjs/apollo@13` |
|
|
287
|
-
| `@nestjs/apollo` | 13.x
|
|
349
|
+
| `@nestjs/apollo` | 13.0.x – 13.1.x | 13.2+ requires @apollo/server@^5 which breaks lib's v4 plugin usage |
|
|
288
350
|
| `@apollo/server` | 4.x | v5 is breaking; not supported |
|
|
289
351
|
| `@as-integrations/express5` | 1.x | Required runtime peer |
|
|
290
352
|
| TypeORM | 0.3.x | 0.2.x not supported (different DataSource API) |
|
|
@@ -1072,11 +1134,17 @@ logic. Any field set on `req` by a NestJS guard or Passport strategy (e.g. `req.
|
|
|
1072
1134
|
therefore accessible from resolvers as `ctx.req.user`.
|
|
1073
1135
|
|
|
1074
1136
|
> **Why returning `context` from `gqlOptions.useFactory` does not work**: the lib's
|
|
1075
|
-
>
|
|
1076
|
-
>
|
|
1077
|
-
>
|
|
1078
|
-
>
|
|
1079
|
-
>
|
|
1137
|
+
> internal context factory replaces any `context` key you return from `gqlOptions.useFactory`,
|
|
1138
|
+
> but it spreads the raw `contextArg` (the `{ req, res }` provided by Apollo Server). So:
|
|
1139
|
+
>
|
|
1140
|
+
> | Approach | Works? |
|
|
1141
|
+
> |----------------------------------------------------|--------|
|
|
1142
|
+
> | Return `context: () => ({ user })` from useFactory | ❌ overridden |
|
|
1143
|
+
> | Populate `req.user` via NestJS guard / Passport | ✅ access via `context.req.user` |
|
|
1144
|
+
>
|
|
1145
|
+
> Always populate identity onto `req` (via a guard) and read it as `context.req.user` in
|
|
1146
|
+
> your resolvers. The resulting GraphQL context is `{ req, res, loaders }` — `req.user` IS
|
|
1147
|
+
> accessible as long as a guard or middleware has set it on the request object.
|
|
1080
1148
|
|
|
1081
1149
|
To access the authenticated user in a **custom** resolver, populate `req.user` in a guard
|
|
1082
1150
|
or middleware and read it from `ctx.req.user`:
|
|
@@ -1267,6 +1335,13 @@ function WmsLayout({ children }: { children: ReactNode }): ReactNode {
|
|
|
1267
1335
|
}
|
|
1268
1336
|
```
|
|
1269
1337
|
|
|
1338
|
+
> **Critical constraint**: WMS page components use the `NextPath` enum for all internal
|
|
1339
|
+
> navigation (`router.push(NextPath.MATERIALSMANAGEMENT)` etc.). Enum values are hardcoded
|
|
1340
|
+
> root-level paths (`/materials-management`, `/inventory-list`, etc.). **WMS pages cannot be
|
|
1341
|
+
> mounted under a custom path prefix like `/wms/*`** — internal links will break even though
|
|
1342
|
+
> the pages initially render. If your existing project requires path prefixing, you must mount
|
|
1343
|
+
> WMS at the root of a separate domain or subdomain.
|
|
1344
|
+
|
|
1270
1345
|
The lib's page components do not require the WMS navigation shell to be present — they only
|
|
1271
1346
|
require the three providers (§13.7) and an Apollo client (§13.6). You can completely replace
|
|
1272
1347
|
the navigation chrome with your own.
|
|
@@ -1495,6 +1570,40 @@ creating a new monorepo. Key points:
|
|
|
1495
1570
|
`@rytass/wms-module-*` package names, ensure they point to `node_modules` (the installed
|
|
1496
1571
|
package), not local source, to avoid confusion.
|
|
1497
1572
|
|
|
1573
|
+
### 13.13.1 pnpm peer-dep multi-instantiation hazard
|
|
1574
|
+
|
|
1575
|
+
When a pnpm workspace contains apps that resolve `@nestjs/core` (or other peers
|
|
1576
|
+
of `@rytass/wms-module-core`) to different major versions, pnpm creates one
|
|
1577
|
+
**instance** of `@rytass/wms-module-core` per unique peer resolution. Both
|
|
1578
|
+
instances register their TypeORM entity decorators against the same global
|
|
1579
|
+
`getMetadataArgsStorage()`, producing:
|
|
1580
|
+
|
|
1581
|
+
```
|
|
1582
|
+
TypeError: Cannot read properties of undefined (reading 'ownColumns')
|
|
1583
|
+
at EntityMetadataBuilder.ts:548
|
|
1584
|
+
```
|
|
1585
|
+
|
|
1586
|
+
**Required workaround**: every workspace app that imports `@rytass/wms-module-core`
|
|
1587
|
+
(directly or transitively via `@rytass/wms-module-graphql`) must resolve to the
|
|
1588
|
+
same `@nestjs/*` major version. Options:
|
|
1589
|
+
|
|
1590
|
+
1. Upgrade the entire workspace to a single NestJS major (preferred)
|
|
1591
|
+
2. Force pnpm to deduplicate the WMS module instance:
|
|
1592
|
+
|
|
1593
|
+
```yaml
|
|
1594
|
+
# pnpm-workspace.yaml
|
|
1595
|
+
overrides:
|
|
1596
|
+
'@rytass/wms-module-core': '0.1.4'
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
3. Apply `public-hoist-pattern[]` for `@rytass/wms-module-*` in `.npmrc`
|
|
1600
|
+
|
|
1601
|
+
This is a structural limitation of the pnpm peer-resolution model combined
|
|
1602
|
+
with TypeORM's global metadata storage; the WMS lib cannot deduplicate
|
|
1603
|
+
itself without rewriting TypeORM's entity registry. Yarn 4 and npm 10 do not
|
|
1604
|
+
hit this because their hoisting strategies differ — pnpm with strict mode is
|
|
1605
|
+
the only affected case.
|
|
1606
|
+
|
|
1498
1607
|
---
|
|
1499
1608
|
|
|
1500
1609
|
### 13.14 GraphQL Type Name Conflicts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rytass/wms-module-graphql",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Rytass WMS Module — GraphQL schema, resolvers and DTOs for warehouse management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rytass",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@as-integrations/express5": "^1.0.0",
|
|
49
|
-
"@nestjs/apollo": "
|
|
49
|
+
"@nestjs/apollo": ">=13.0.0 <13.2.0",
|
|
50
50
|
"@nestjs/common": "^11.0.0",
|
|
51
51
|
"@nestjs/graphql": "^13.0.0",
|
|
52
|
-
"@rytass/wms-module-core": "^0.1.
|
|
52
|
+
"@rytass/wms-module-core": "^0.1.5",
|
|
53
53
|
"graphql": "^16.0.0",
|
|
54
54
|
"reflect-metadata": "^0.1.13 || ^0.2.0",
|
|
55
55
|
"rxjs": "^7.8.0"
|