Skip to content

Commit 850f7d5

Browse files
committed
chore: consolidating shared implementation
1 parent 3bd329e commit 850f7d5

13 files changed

Lines changed: 131 additions & 128 deletions

File tree

.github/workflows/react.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@ jobs:
3737
run: |
3838
yarn workspaces foreach -pR --topological-dev --from 'browser-contract-test-adapter' install
3939
yarn workspaces foreach -pR --topological-dev --from "@launchdarkly/react-sdk-contract-tests" install
40-
yarn workspace @launchdarkly/js-contract-test-utils build:client
4140
yarn workspaces foreach -pR --topological-dev --from 'browser-contract-test-adapter' run build
4241
yarn workspaces foreach -pR --topological-dev --from "@launchdarkly/react-sdk-contract-tests" run build
43-
- name: Install Playwright browsers
44-
run: yarn workspace @launchdarkly/react-sdk-contract-tests install-playwright-browsers
42+
yarn workspace @launchdarkly/react-sdk-contract-tests install-playwright-browsers
4543
- name: Run test adapter
4644
run: |
4745
yarn workspace @launchdarkly/react-sdk-contract-tests run start:adapter > /tmp/adapter.log 2>&1 &

.github/workflows/shopify-oxygen.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- name: Install contract test service dependencies
3030
run: yarn workspace @launchdarkly/shopify-oxygen-contract-tests install --no-immutable
3131
- name: Build shared contract test utils
32-
run: yarn workspace @launchdarkly/js-contract-test-utils build
32+
run: yarn workspace @launchdarkly/js-contract-test-utils build:server
3333
- name: Build the test service
3434
run: yarn workspace @launchdarkly/shopify-oxygen-contract-tests build
3535
- name: Launch the test service in the background

packages/sdk/server-node/contract-tests/src/sdkClientEntity.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import got from 'got';
33
import {
44
CommandParams,
55
CreateInstanceParams,
6-
SDKConfigParams,
6+
ServerSDKConfigParams,
77
ServerSideTestHook as TestHook,
88
} from '@launchdarkly/js-contract-test-utils/server';
99
import ld, {
@@ -29,7 +29,7 @@ import { Log, sdkLogger } from './log.js';
2929
const badCommandError = new Error('unsupported command');
3030
export { badCommandError };
3131

32-
export function makeSdkConfig(options: SDKConfigParams, tag: string): LDOptions {
32+
export function makeSdkConfig(options: ServerSDKConfigParams, tag: string): LDOptions {
3333
const cf: LDOptions = {
3434
logger: sdkLogger(tag),
3535
diagnosticOptOut: true,
@@ -195,7 +195,11 @@ function contextOrUser(
195195
context: Record<string, any> | undefined,
196196
user: LDUser | undefined,
197197
): LDContext | LDUser {
198-
return (context as LDContext | undefined) || user!;
198+
const result = (context as LDContext | undefined) ?? user;
199+
if (!result) {
200+
throw new Error('Neither context nor user provided');
201+
}
202+
return result;
199203
}
200204

201205
export interface SdkClientEntity {
@@ -221,7 +225,7 @@ export async function newSdkClientEntity(options: CreateInstanceParams): Promise
221225
: 5000;
222226
const client: LDClient = ld.init(
223227
options.configuration.credential || 'unknown-sdk-key',
224-
makeSdkConfig(options.configuration, options.tag),
228+
makeSdkConfig(options.configuration as ServerSDKConfigParams, options.tag),
225229
);
226230
try {
227231
await client.waitForInitialization({ timeout });

packages/tooling/contract-test-utils/package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,21 @@
3333
}
3434
},
3535
"scripts": {
36-
"build": "tsc",
36+
"build": "tsc && tsc -p tsconfig.client.json && tsc -p tsconfig.server.json",
3737
"build:client": "tsc -p tsconfig.client.json",
3838
"build:server": "tsc -p tsconfig.server.json",
3939
"clean": "rimraf dist"
4040
},
41-
"dependencies": {
42-
"@launchdarkly/js-client-sdk-common": "workspace:^"
43-
},
4441
"peerDependencies": {
45-
"@launchdarkly/node-server-sdk": "workspace:^",
42+
"@launchdarkly/js-client-sdk-common": "workspace:^",
43+
"@launchdarkly/js-server-sdk-common": "workspace:^",
4644
"got": "14.4.7"
4745
},
4846
"peerDependenciesMeta": {
49-
"@launchdarkly/node-server-sdk": {
47+
"@launchdarkly/js-client-sdk-common": {
48+
"optional": true
49+
},
50+
"@launchdarkly/js-server-sdk-common": {
5051
"optional": true
5152
},
5253
"got": {
@@ -55,6 +56,7 @@
5556
},
5657
"devDependencies": {
5758
"@types/node": "^18.11.9",
59+
"got": "14.4.7",
5860
"typescript": "^4.9.0"
5961
}
6062
}

packages/tooling/contract-test-utils/src/client-side/TestHook.ts

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,10 @@ import {
66
LDEvaluationDetail,
77
TrackSeriesContext,
88
} from '@launchdarkly/js-client-sdk-common';
9+
import { BaseTestHook } from '../shared/BaseTestHook.js';
910

10-
export interface HookData {
11-
beforeEvaluation?: Record<string, unknown>;
12-
afterEvaluation?: Record<string, unknown>;
13-
}
14-
15-
export interface HookErrors {
16-
beforeEvaluation?: string;
17-
afterEvaluation?: string;
18-
afterTrack?: string;
19-
}
20-
21-
export default class TestHook implements Hook {
22-
private _name: string;
23-
private _endpoint: string;
24-
private _data?: HookData;
25-
private _errors?: HookErrors;
26-
27-
constructor(name: string, endpoint: string, data?: HookData, errors?: HookErrors) {
28-
this._name = name;
29-
this._endpoint = endpoint;
30-
this._data = data;
31-
this._errors = errors;
32-
}
33-
34-
private async _safePost(body: unknown): Promise<void> {
11+
export default class TestHook extends BaseTestHook implements Hook {
12+
protected async _safePost(body: unknown): Promise<void> {
3513
try {
3614
await fetch(this._endpoint, {
3715
method: 'POST',
@@ -43,43 +21,30 @@ export default class TestHook implements Hook {
4321
}
4422
}
4523

46-
getMetadata(): HookMetadata {
47-
return {
48-
name: this._name,
49-
};
24+
override getMetadata(): HookMetadata {
25+
return super.getMetadata();
5026
}
5127

5228
beforeEvaluation(
5329
hookContext: EvaluationSeriesContext,
5430
data: EvaluationSeriesData,
5531
): EvaluationSeriesData {
56-
if (this._errors?.beforeEvaluation) {
57-
throw new Error(this._errors.beforeEvaluation);
58-
}
59-
this._safePost({
60-
evaluationSeriesContext: hookContext,
61-
evaluationSeriesData: data,
62-
stage: 'beforeEvaluation',
63-
});
64-
return { ...data, ...(this._data?.beforeEvaluation || {}) };
32+
return this._beforeEvaluationImpl(
33+
hookContext as unknown as Record<string, unknown>,
34+
data,
35+
) as EvaluationSeriesData;
6536
}
6637

6738
afterEvaluation(
6839
hookContext: EvaluationSeriesContext,
6940
data: EvaluationSeriesData,
7041
detail: LDEvaluationDetail,
7142
): EvaluationSeriesData {
72-
if (this._errors?.afterEvaluation) {
73-
throw new Error(this._errors.afterEvaluation);
74-
}
75-
this._safePost({
76-
evaluationSeriesContext: hookContext,
77-
evaluationSeriesData: data,
78-
stage: 'afterEvaluation',
79-
evaluationDetail: detail,
80-
});
81-
82-
return { ...data, ...(this._data?.afterEvaluation || {}) };
43+
return this._afterEvaluationImpl(
44+
hookContext as unknown as Record<string, unknown>,
45+
data,
46+
detail,
47+
) as EvaluationSeriesData;
8348
}
8449

8550
afterTrack(hookContext: TrackSeriesContext): void {

packages/tooling/contract-test-utils/src/client.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,3 @@ export * from './index.js';
33

44
// Client-side exports
55
export { default as ClientSideTestHook } from './client-side/TestHook.js';
6-
export type {
7-
HookData as ClientSideHookData,
8-
HookErrors as ClientSideHookErrors,
9-
} from './client-side/TestHook.js';
Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,9 @@
11
import got from 'got';
2+
import { integrations, LDEvaluationDetail } from '@launchdarkly/js-server-sdk-common';
3+
import { BaseTestHook } from '../shared/BaseTestHook.js';
24

3-
import { integrations, LDEvaluationDetail } from '@launchdarkly/node-server-sdk';
4-
5-
export interface HookData {
6-
beforeEvaluation?: Record<string, unknown>;
7-
afterEvaluation?: Record<string, unknown>;
8-
}
9-
10-
export interface HookErrors {
11-
beforeEvaluation?: string;
12-
afterEvaluation?: string;
13-
}
14-
15-
export default class TestHook implements integrations.Hook {
16-
private _name: string;
17-
private _endpoint: string;
18-
private _data?: HookData;
19-
private _errors?: HookErrors;
20-
21-
constructor(name: string, endpoint: string, data?: HookData, errors?: HookErrors) {
22-
this._name = name;
23-
this._endpoint = endpoint;
24-
this._data = data;
25-
this._errors = errors;
26-
}
27-
28-
private async _safePost(body: unknown): Promise<void> {
5+
export default class TestHook extends BaseTestHook implements integrations.Hook {
6+
protected async _safePost(body: unknown): Promise<void> {
297
try {
308
await got.post(this._endpoint, { json: body });
319
} catch {
@@ -34,42 +12,29 @@ export default class TestHook implements integrations.Hook {
3412
}
3513
}
3614

37-
getMetadata(): integrations.HookMetadata {
38-
return {
39-
name: this._name,
40-
};
15+
override getMetadata(): integrations.HookMetadata {
16+
return super.getMetadata();
4117
}
4218

4319
beforeEvaluation(
4420
hookContext: integrations.EvaluationSeriesContext,
4521
data: integrations.EvaluationSeriesData,
4622
): integrations.EvaluationSeriesData {
47-
if (this._errors?.beforeEvaluation) {
48-
throw new Error(this._errors.beforeEvaluation);
49-
}
50-
this._safePost({
51-
evaluationSeriesContext: hookContext,
52-
evaluationSeriesData: data,
53-
stage: 'beforeEvaluation',
54-
});
55-
return { ...data, ...(this._data?.beforeEvaluation || {}) };
23+
return this._beforeEvaluationImpl(
24+
hookContext as unknown as Record<string, unknown>,
25+
data,
26+
) as integrations.EvaluationSeriesData;
5627
}
5728

5829
afterEvaluation(
5930
hookContext: integrations.EvaluationSeriesContext,
6031
data: integrations.EvaluationSeriesData,
6132
detail: LDEvaluationDetail,
6233
): integrations.EvaluationSeriesData {
63-
if (this._errors?.afterEvaluation) {
64-
throw new Error(this._errors.afterEvaluation);
65-
}
66-
this._safePost({
67-
evaluationSeriesContext: hookContext,
68-
evaluationSeriesData: data,
69-
stage: 'afterEvaluation',
70-
evaluationDetail: detail,
71-
});
72-
73-
return { ...data, ...(this._data?.afterEvaluation || {}) };
34+
return this._afterEvaluationImpl(
35+
hookContext as unknown as Record<string, unknown>,
36+
data,
37+
detail,
38+
) as integrations.EvaluationSeriesData;
7439
}
7540
}

packages/tooling/contract-test-utils/src/server.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,4 @@ export * from './index.js';
33

44
// Server-side exports
55
export { default as ServerSideTestHook } from './server-side/TestHook.js';
6-
export type {
7-
HookData as ServerSideHookData,
8-
HookErrors as ServerSideHookErrors,
9-
} from './server-side/TestHook.js';
6+
export type { ServerSDKConfigParams } from './types/ConfigParams.js';
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { HookData, HookErrors } from '../types/CommandParams.js';
2+
3+
export abstract class BaseTestHook {
4+
protected readonly _name: string;
5+
protected readonly _endpoint: string;
6+
protected readonly _data?: HookData;
7+
protected readonly _errors?: HookErrors;
8+
9+
constructor(name: string, endpoint: string, data?: HookData, errors?: HookErrors) {
10+
this._name = name;
11+
this._endpoint = endpoint;
12+
this._data = data;
13+
this._errors = errors;
14+
}
15+
16+
protected abstract _safePost(body: unknown): Promise<void>;
17+
18+
getMetadata() {
19+
return { name: this._name };
20+
}
21+
22+
protected _beforeEvaluationImpl(
23+
hookContext: Record<string, unknown>,
24+
data: Record<string, unknown>,
25+
): Record<string, unknown> {
26+
if (this._errors?.beforeEvaluation) {
27+
throw new Error(this._errors.beforeEvaluation);
28+
}
29+
this._safePost({
30+
evaluationSeriesContext: hookContext,
31+
evaluationSeriesData: data,
32+
stage: 'beforeEvaluation',
33+
});
34+
return { ...data, ...(this._data?.beforeEvaluation ?? {}) };
35+
}
36+
37+
protected _afterEvaluationImpl(
38+
hookContext: Record<string, unknown>,
39+
data: Record<string, unknown>,
40+
detail: unknown,
41+
): Record<string, unknown> {
42+
if (this._errors?.afterEvaluation) {
43+
throw new Error(this._errors.afterEvaluation);
44+
}
45+
this._safePost({
46+
evaluationSeriesContext: hookContext,
47+
evaluationSeriesData: data,
48+
stage: 'afterEvaluation',
49+
evaluationDetail: detail,
50+
});
51+
return { ...data, ...(this._data?.afterEvaluation ?? {}) };
52+
}
53+
}

packages/tooling/contract-test-utils/src/types/CommandParams.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export const CommandType = {
1111
ContextConvert: 'contextConvert',
1212
ContextComparison: 'contextComparison',
1313
SecureModeHash: 'secureModeHash',
14+
// Server-specific commands
15+
GetBigSegmentStoreStatus: 'getBigSegmentStoreStatus',
16+
MigrationVariation: 'migrationVariation',
17+
MigrationOperation: 'migrationOperation',
18+
RegisterFlagChangeListener: 'registerFlagChangeListener',
19+
UnregisterListener: 'unregisterListener',
1420
} as const;
1521
// eslint-disable-next-line @typescript-eslint/no-redeclare
1622
export type CommandType = (typeof CommandType)[keyof typeof CommandType];
@@ -26,7 +32,7 @@ export const ValueType = {
2632
export type ValueType = (typeof ValueType)[keyof typeof ValueType];
2733

2834
export interface CommandParams {
29-
command: CommandType | string;
35+
command: CommandType;
3036
evaluate?: EvaluateFlagParams;
3137
evaluateAll?: EvaluateAllFlagsParams;
3238
customEvent?: CustomEventParams;
@@ -167,6 +173,17 @@ export interface HookExecutionPayload {
167173
stage?: HookStage;
168174
}
169175

176+
export interface HookData {
177+
beforeEvaluation?: Record<string, unknown>;
178+
afterEvaluation?: Record<string, unknown>;
179+
}
180+
181+
export interface HookErrors {
182+
beforeEvaluation?: string;
183+
afterEvaluation?: string;
184+
afterTrack?: string; // client-only; server ignores this field
185+
}
186+
170187
// Server-specific command parameter types
171188

172189
export interface MigrationVariationParams {

0 commit comments

Comments
 (0)