Commit 327a7f7
feat: add server-side TestHook and migrate server-node/shopify-oxygen to shared utils [SDK-2009] (#1168)
**Requirements**
- [ ] I have added test coverage for new or changed functionality
- [ ] I have followed the repository's [pull request submission
guidelines](../blob/main/CONTRIBUTING.md#submitting-pull-requests)
- [ ] I have validated my changes against all supported platform
versions
**Related issues**
- [SDK-2009](https://launchdarkly.atlassian.net/browse/SDK-2009) — Add
server-side TestHook and ClientPool to contract-test-utils
- Subtask 2 of
[SDK-1866](https://launchdarkly.atlassian.net/browse/SDK-1866)
**Describe the solution you've provided**
Moves the server-node `TestHook` (which uses `got` for HTTP callbacks)
into the shared `@launchdarkly/js-contract-test-utils` package and
migrates both server-node and Shopify Oxygen contract tests to use
shared infrastructure. Also deduplicates shared types (command params,
config params) so both client and server contract tests consume them
from the shared package.
**Changes to `packages/tooling/contract-test-utils/`:**
- `src/server-side/TestHook.ts` — moved from server-node contract tests
(exact rename, no content changes)
- `src/server.ts` — barrel re-exporting from `./index.js` plus
`ServerSideTestHook` (mirrors `client.ts` pattern)
- `src/client.ts` / `src/index.ts` — barrel exports using `.js`
extensions (required for compiled ESM output)
- `src/types/compat.ts` — minimal `LDContext`, `LDEvaluationReason`, and
`LDLogger` type definitions compatible with both client and server SDKs,
allowing shared code to avoid importing from either SDK directly
- `src/types/CommandParams.ts` — imports from `compat.ts`; includes both
client and server command fields (e.g. `migrationVariation`,
`registerFlagChangeListener`)
- `src/types/ConfigParams.ts` — same pattern; includes both `clientSide`
and server-specific fields (`bigSegments`, `dataSystem`)
- `src/logging/makeLogger.ts` — now imports `LDLogger` from `compat.ts`
instead of `@launchdarkly/js-client-sdk-common`
- `package.json`:
- All three subpath exports (`.`, `./client`, `./server`) point to
compiled `dist/` output
- Three build scripts: `build` (universal only), `build:client` (client
+ universal), `build:server` (server + universal)
- `got` and `@launchdarkly/node-server-sdk` added as **optional peer
dependencies**
**Three-tier TypeScript build configuration:**
- `tsconfig.json` (base) — excludes **both** TestHook files and barrel
files (`client.ts`, `server.ts`). Compiles only universal code with zero
SDK dependencies. Used by `build` script.
- `tsconfig.client.json` — extends base, re-includes client files,
excludes server files. Requires `@launchdarkly/js-client-sdk-common`.
Used by `build:client` script.
- `tsconfig.server.json` — extends base, re-includes server files,
excludes client files. Requires `@launchdarkly/node-server-sdk` + `got`.
Used by `build:server` script.
**Migrations:**
- **server-node**:
- Deleted local `TestHook.ts`; imports `ServerSideTestHook` from shared
package
- Replaced inline `clientCounter` + `Record<string, SdkClientEntity>` in
`index.ts` with shared `ClientPool<SdkClientEntity>`
- Imported `CommandParams`, `CreateInstanceParams`, `SDKConfigParams`
from shared package (~130 lines of duplicated local type definitions
removed)
- Added type casts where shared types use `unknown` or `string` but SDK
expects specific types (e.g., `pe.defaultValue as boolean`,
`migrationVariation.context as LDContext`,
`migrationVariation.defaultStage as LDMigrationStage`)
- **Shopify Oxygen**:
- Replaced inline `Record<string, LDClient>` + counter with shared
`ClientPool<LDClient>`
- Updated JSDoc comment to be more general (not Shopify-specific)
- Added `noExternal` to `tsup.config.ts` to bundle shared package inline
- Client IDs changed from `"client-1"` to `"1"` (auto-generated by
`ClientPool.add()`)
**CI Workflow Updates:**
- `.github/workflows/browser.yml` — added `build:client` step before
contract test adapter build
- `.github/workflows/electron.yaml` — added `build:client` step before
contract tests entity build
- `.github/workflows/react-native-contract-tests.yml` — added
`build:client` step before contract test adapter build
- `.github/workflows/react.yaml` — added `build:client` step **before**
topological build (must run before Next.js/Turbopack resolves imports)
- `.github/workflows/server-node.yml` — added `build:server` step before
contract test build
- `.github/workflows/shopify-oxygen.yml` — added `build` step before
contract test build
**Build command matrix by CI environment:**
- **Universal only** (`build`): shopify-oxygen — has no SDK dependencies
- **Client + universal** (`build:client`): browser, electron,
react-native, react — have `@launchdarkly/js-client-sdk-common` but not
`got`/`node-server-sdk`
- **Server + universal** (`build:server`): server-node — has
`@launchdarkly/node-server-sdk` + `got` but may lack client SDK
**Updates since last revision:**
Implemented three-tier TypeScript build configuration to handle
different SDK dependency profiles across CI environments:
1. **Split `tsconfig.json` into three configs**: Base config now
excludes both client and server TestHook files, making it universal-only
(zero SDK dependencies). New `tsconfig.client.json` and
`tsconfig.server.json` extend base and selectively re-include their
respective files.
2. **Added `build:client` script**: Browser/Electron/React-Native/React
CI workflows now explicitly run `build:client` to compile
`dist/client.js`, which was missing when they ran the default `build`
script (universal only).
3. **Shopify Oxygen uses universal build**: Changed from `build:server`
to `build` since Shopify Oxygen only imports from the base package (no
subpath), not `/server`.
4. **Fixed React workflow build ordering**: Moved `build:client` to run
**before** the topological `yarn workspaces foreach ... run build`
because the React contract tests' Next.js/Turbopack build happens during
that step and needs `dist/client.js` to already exist when resolving
`@launchdarkly/js-contract-test-utils/client` imports.
This fixes CI failures where different environments tried to compile
code that imported SDKs not installed in their focused dependency trees
(e.g., React CI trying to compile server-side TestHook which imports
`got`).
**1 parent 9756e75 commit 327a7f7
27 files changed
Lines changed: 367 additions & 355 deletions
File tree
- .github/workflows
- packages
- sdk
- server-node/contract-tests
- src
- shopify-oxygen/contract-tests
- src/utils
- tooling/contract-test-utils
- src
- client-side
- logging
- server-side
- types
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
53 | 56 | | |
54 | 57 | | |
55 | 58 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
43 | | - | |
| 42 | + | |
44 | 43 | | |
45 | 44 | | |
46 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
31 | 33 | | |
32 | 34 | | |
33 | 35 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
| |||
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
13 | | - | |
14 | | - | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | 70 | | |
74 | 71 | | |
75 | | - | |
| 72 | + | |
76 | 73 | | |
77 | 74 | | |
78 | | - | |
| 75 | + | |
79 | 76 | | |
80 | 77 | | |
81 | 78 | | |
| |||
86 | 83 | | |
87 | 84 | | |
88 | 85 | | |
89 | | - | |
| 86 | + | |
90 | 87 | | |
91 | 88 | | |
92 | 89 | | |
| |||
113 | 110 | | |
114 | 111 | | |
115 | 112 | | |
116 | | - | |
| 113 | + | |
117 | 114 | | |
118 | 115 | | |
119 | 116 | | |
120 | 117 | | |
121 | 118 | | |
122 | | - | |
| 119 | + | |
123 | 120 | | |
124 | 121 | | |
125 | 122 | | |
| |||
0 commit comments