@coframe/sdk 1.1.59 → 1.1.60
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 +34 -6
- package/dist/pkg/cf.cjs.js +255 -31
- package/dist/pkg/cf.esm.mjs +255 -31
- package/dist/pkg/server.cjs.js +52 -13
- package/dist/pkg/server.esm.mjs +52 -14
- package/dist/pkg/types/index.d.ts +1 -0
- package/dist/pkg/types/react.d.ts +1 -0
- package/dist/pkg/types/server.d.ts +8 -3
- package/package.json +12 -14
package/dist/pkg/server.esm.mjs
CHANGED
|
@@ -234,6 +234,8 @@ const ID_FIELDS = ['projectId', 'experimentId', 'userToken'];
|
|
|
234
234
|
function invalidAssignmentIdField(body) {
|
|
235
235
|
for (const field of ID_FIELDS) {
|
|
236
236
|
const value = body[field];
|
|
237
|
+
if (field === 'experimentId' && value === undefined)
|
|
238
|
+
continue;
|
|
237
239
|
if (typeof value !== 'string' || !value) {
|
|
238
240
|
return { field, message: 'is required' };
|
|
239
241
|
}
|
|
@@ -513,6 +515,25 @@ async function flushFeatureFlagEvents() {
|
|
|
513
515
|
}
|
|
514
516
|
}
|
|
515
517
|
|
|
518
|
+
const IDLE_MS = 60000;
|
|
519
|
+
let dispatcher;
|
|
520
|
+
function runsOnNode() {
|
|
521
|
+
var _a;
|
|
522
|
+
return (typeof process !== 'undefined' &&
|
|
523
|
+
typeof ((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string' &&
|
|
524
|
+
!('EdgeRuntime' in globalThis));
|
|
525
|
+
}
|
|
526
|
+
function edgeDispatcher() {
|
|
527
|
+
if (!runsOnNode())
|
|
528
|
+
return Promise.resolve(undefined);
|
|
529
|
+
dispatcher !== null && dispatcher !== void 0 ? dispatcher : (dispatcher = import('undici').then(({ Agent }) => new Agent({ keepAliveTimeout: IDLE_MS, keepAliveMaxTimeout: IDLE_MS }), () => undefined));
|
|
530
|
+
return dispatcher;
|
|
531
|
+
}
|
|
532
|
+
async function edgeFetch(url, init = {}) {
|
|
533
|
+
const agent = await edgeDispatcher();
|
|
534
|
+
return fetch(url, agent ? { ...init, dispatcher: agent } : init);
|
|
535
|
+
}
|
|
536
|
+
|
|
516
537
|
const DEFAULT_ASSIGNMENT_TIMEOUT_MS = 1500;
|
|
517
538
|
function normalizeRequestHeaders(headers) {
|
|
518
539
|
const normalized = new Headers();
|
|
@@ -599,6 +620,13 @@ function effectiveVisitCount(headers) {
|
|
|
599
620
|
const next = nextVisitCount(existing, lastVisitTime, Date.now());
|
|
600
621
|
return Number.isSafeInteger(next) ? next : existing;
|
|
601
622
|
}
|
|
623
|
+
function isAssignedVariant(value) {
|
|
624
|
+
return (isRecord(value) &&
|
|
625
|
+
typeof value.id === 'string' &&
|
|
626
|
+
typeof value.slug === 'string' &&
|
|
627
|
+
typeof value.experimentId === 'string' &&
|
|
628
|
+
typeof value.iterationId === 'string');
|
|
629
|
+
}
|
|
602
630
|
function isExperimentAssignmentResult(value, experimentId) {
|
|
603
631
|
if (!isRecord(value) || !isRecord(value.projectData))
|
|
604
632
|
return false;
|
|
@@ -615,22 +643,32 @@ function isExperimentAssignmentResult(value, experimentId) {
|
|
|
615
643
|
context.userVisitCount < 0) {
|
|
616
644
|
return false;
|
|
617
645
|
}
|
|
646
|
+
if (value.variants !== undefined && !Array.isArray(value.variants))
|
|
647
|
+
return false;
|
|
648
|
+
if (Array.isArray(value.variants) && !value.variants.every(isAssignedVariant))
|
|
649
|
+
return false;
|
|
650
|
+
if (experimentId === undefined) {
|
|
651
|
+
return value.variant === null && Array.isArray(value.variants);
|
|
652
|
+
}
|
|
618
653
|
if (value.variant === null) {
|
|
619
654
|
return typeof value.reason === 'string';
|
|
620
655
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
return (typeof value.variant.id === 'string' &&
|
|
624
|
-
typeof value.variant.slug === 'string' &&
|
|
625
|
-
value.variant.experimentId === experimentId &&
|
|
626
|
-
typeof value.variant.iterationId === 'string');
|
|
656
|
+
return (isAssignedVariant(value.variant) &&
|
|
657
|
+
value.variant.experimentId === experimentId);
|
|
627
658
|
}
|
|
628
659
|
function generateUserToken() {
|
|
629
660
|
return generateUUID();
|
|
630
661
|
}
|
|
631
|
-
|
|
662
|
+
function getExperimentAssignment(options) {
|
|
663
|
+
var _a;
|
|
664
|
+
return fetchAssignment(options, (_a = options.experimentId) !== null && _a !== void 0 ? _a : '');
|
|
665
|
+
}
|
|
666
|
+
function getAssignments(options) {
|
|
667
|
+
return fetchAssignment(options, undefined);
|
|
668
|
+
}
|
|
669
|
+
async function fetchAssignment(options, experimentId) {
|
|
632
670
|
var _a, _b, _c, _d, _e, _f;
|
|
633
|
-
const idProblem = invalidAssignmentIdField(options);
|
|
671
|
+
const idProblem = invalidAssignmentIdField({ ...options, experimentId });
|
|
634
672
|
if (idProblem)
|
|
635
673
|
throw new Error(`${idProblem.field} ${idProblem.message}`);
|
|
636
674
|
if (options.timeoutMs !== undefined &&
|
|
@@ -656,7 +694,7 @@ async function getExperimentAssignment(options) {
|
|
|
656
694
|
: clampHeader(incoming.get('referer'), ASSIGNMENT_FIELD_LIMITS.referrer);
|
|
657
695
|
const requestBody = {
|
|
658
696
|
projectId: options.projectId,
|
|
659
|
-
experimentId:
|
|
697
|
+
...(experimentId !== undefined ? { experimentId } : {}),
|
|
660
698
|
userToken: options.userToken,
|
|
661
699
|
context: {
|
|
662
700
|
currentUrl: options.currentUrl,
|
|
@@ -670,7 +708,7 @@ async function getExperimentAssignment(options) {
|
|
|
670
708
|
userVisitCount,
|
|
671
709
|
},
|
|
672
710
|
};
|
|
673
|
-
const response = await
|
|
711
|
+
const response = await edgeFetch(`${edgeBaseUrl(options.edgeUrl)}/api/v1/assignment`, {
|
|
674
712
|
method: 'POST',
|
|
675
713
|
headers: createAssignmentHeaders(incoming),
|
|
676
714
|
signal: controller.signal,
|
|
@@ -679,7 +717,7 @@ async function getExperimentAssignment(options) {
|
|
|
679
717
|
if (!response.ok)
|
|
680
718
|
return undefined;
|
|
681
719
|
const result = await response.json();
|
|
682
|
-
return isExperimentAssignmentResult(result,
|
|
720
|
+
return isExperimentAssignmentResult(result, experimentId)
|
|
683
721
|
? result
|
|
684
722
|
: undefined;
|
|
685
723
|
}
|
|
@@ -695,7 +733,7 @@ async function requestFeatureFlags(options) {
|
|
|
695
733
|
const controller = new AbortController();
|
|
696
734
|
const timeout = setTimeout(() => controller.abort(), (_a = options.requestTimeoutMs) !== null && _a !== void 0 ? _a : 3000);
|
|
697
735
|
try {
|
|
698
|
-
const response = await
|
|
736
|
+
const response = await edgeFetch(`${edgeBaseUrl(options.edgeUrl)}/api/v1/flags?v=1`, {
|
|
699
737
|
method: 'POST',
|
|
700
738
|
headers: {
|
|
701
739
|
'Content-Type': 'application/json',
|
|
@@ -782,7 +820,7 @@ async function fetchAntiflickerFromEdge(projectId, currentUrl, referrer, userCon
|
|
|
782
820
|
const config = encodeURIComponent(JSON.stringify(payload));
|
|
783
821
|
const edgeUrl = new URL(`${"https://edge.cofra.me"}/cf.css`);
|
|
784
822
|
edgeUrl.searchParams.set('config', config);
|
|
785
|
-
const response = await
|
|
823
|
+
const response = await edgeFetch(edgeUrl, {
|
|
786
824
|
headers,
|
|
787
825
|
});
|
|
788
826
|
if (!response.ok)
|
|
@@ -831,4 +869,4 @@ async function getProjectData(options) {
|
|
|
831
869
|
return null;
|
|
832
870
|
}
|
|
833
871
|
|
|
834
|
-
export { evaluateFlags, flushFeatureFlagEvents, generateUserToken, getExperimentAssignment, getFeatureFlag, getFeatureFlagPayload, getFeatureFlagResult, getProjectData, getRemoteConfig, isFeatureEnabled };
|
|
872
|
+
export { evaluateFlags, flushFeatureFlagEvents, generateUserToken, getAssignments, getExperimentAssignment, getFeatureFlag, getFeatureFlagPayload, getFeatureFlagResult, getProjectData, getRemoteConfig, isFeatureEnabled };
|
|
@@ -68,6 +68,7 @@ type ModificationAddBanner = {
|
|
|
68
68
|
type ModificationExecuteJs = {
|
|
69
69
|
type: 'execute_js';
|
|
70
70
|
js: string;
|
|
71
|
+
css?: string | string[];
|
|
71
72
|
};
|
|
72
73
|
type ModalTrigger = 'exit' | 'scroll' | 'enter' | 'timer';
|
|
73
74
|
|
|
@@ -268,7 +269,7 @@ interface AssignedVariant$1 {
|
|
|
268
269
|
experimentId: string;
|
|
269
270
|
iterationId: string;
|
|
270
271
|
}
|
|
271
|
-
type AssignmentMissReason$1 = 'experiment_not_found' | 'not_assigned' | 'unsupported_experiment_type' | 'preview_active';
|
|
272
|
+
type AssignmentMissReason$1 = 'experiment_not_found' | 'not_assigned' | 'unsupported_experiment_type' | 'preview_active' | 'no_target_experiment';
|
|
272
273
|
type AssignmentOutcome<Reason extends string = AssignmentMissReason$1> = {
|
|
273
274
|
variant: AssignedVariant$1;
|
|
274
275
|
} | {
|
|
@@ -276,6 +277,7 @@ type AssignmentOutcome<Reason extends string = AssignmentMissReason$1> = {
|
|
|
276
277
|
reason: Reason;
|
|
277
278
|
};
|
|
278
279
|
type AssignmentResponse<Reason extends string = AssignmentMissReason$1> = AssignmentOutcome<Reason> & {
|
|
280
|
+
variants?: AssignedVariant$1[];
|
|
279
281
|
projectData: AssignmentProjectData;
|
|
280
282
|
};
|
|
281
283
|
|
|
@@ -307,6 +309,7 @@ interface FeatureFlagSelector {
|
|
|
307
309
|
|
|
308
310
|
declare function flushFeatureFlagEvents(): Promise<void>;
|
|
309
311
|
|
|
312
|
+
type AssignmentFetchOptions = Omit<GetExperimentAssignmentOptions, 'experimentId'>;
|
|
310
313
|
type RequestHeaders = Headers | Record<string, string | string[] | undefined>;
|
|
311
314
|
interface GetExperimentAssignmentOptions extends AssignmentContext {
|
|
312
315
|
projectId: string;
|
|
@@ -335,7 +338,9 @@ interface CoframeProjectPayload {
|
|
|
335
338
|
antiflickerCSS?: string;
|
|
336
339
|
}
|
|
337
340
|
declare function generateUserToken(): string;
|
|
341
|
+
type GetAssignmentsOptions = AssignmentFetchOptions;
|
|
338
342
|
declare function getExperimentAssignment(options: GetExperimentAssignmentOptions): Promise<ExperimentAssignmentResult | undefined>;
|
|
343
|
+
declare function getAssignments(options: GetAssignmentsOptions): Promise<ExperimentAssignmentResult | undefined>;
|
|
339
344
|
interface EvaluateFlagsOptions {
|
|
340
345
|
apiKey: string;
|
|
341
346
|
projectId: string;
|
|
@@ -365,5 +370,5 @@ declare const getRemoteConfig: typeof getFeatureFlagPayload;
|
|
|
365
370
|
|
|
366
371
|
declare function getProjectData(options: GetProjectDataOptions): Promise<CoframeProjectPayload | null>;
|
|
367
372
|
|
|
368
|
-
export { evaluateFlags, flushFeatureFlagEvents, generateUserToken, getExperimentAssignment, getFeatureFlag, getFeatureFlagPayload, getFeatureFlagResult, getProjectData, getRemoteConfig, isFeatureEnabled };
|
|
369
|
-
export type { AssignedVariant, AssignmentMissReason, CoframeProjectPayload, EvaluateFlagsOptions, ExperimentAssignmentResult, FeatureFlagServerReadOptions, GetExperimentAssignmentOptions, GetProjectDataOptions, RequestHeaders };
|
|
373
|
+
export { evaluateFlags, flushFeatureFlagEvents, generateUserToken, getAssignments, getExperimentAssignment, getFeatureFlag, getFeatureFlagPayload, getFeatureFlagResult, getProjectData, getRemoteConfig, isFeatureEnabled };
|
|
374
|
+
export type { AssignedVariant, AssignmentMissReason, CoframeProjectPayload, EvaluateFlagsOptions, ExperimentAssignmentResult, FeatureFlagServerReadOptions, GetAssignmentsOptions, GetExperimentAssignmentOptions, GetProjectDataOptions, RequestHeaders };
|
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coframe/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.60",
|
|
4
4
|
"description": "Coframe optimizes your website using generative AI to deliver maximum impact to your audience and allow your site to improve itself as you sleep. Learn more at coframe.com.",
|
|
5
5
|
"main": "dist/pkg/cf.cjs.js",
|
|
6
6
|
"module": "dist/pkg/cf.esm.mjs",
|
|
7
7
|
"types": "dist/pkg/types/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./dist/pkg/types/index.d.ts",
|
|
10
11
|
"import": "./dist/pkg/cf.esm.mjs",
|
|
11
|
-
"require": "./dist/pkg/cf.cjs.js"
|
|
12
|
-
"types": "./dist/pkg/types/index.d.ts"
|
|
12
|
+
"require": "./dist/pkg/cf.cjs.js"
|
|
13
13
|
},
|
|
14
14
|
"./server": {
|
|
15
|
+
"types": "./dist/pkg/types/server.d.ts",
|
|
15
16
|
"import": "./dist/pkg/server.esm.mjs",
|
|
16
|
-
"require": "./dist/pkg/server.cjs.js"
|
|
17
|
-
"types": "./dist/pkg/types/server.d.ts"
|
|
17
|
+
"require": "./dist/pkg/server.cjs.js"
|
|
18
18
|
},
|
|
19
19
|
"./feature-flags": {
|
|
20
|
+
"types": "./dist/pkg/types/feature-flags.d.ts",
|
|
20
21
|
"import": "./dist/pkg/feature-flags.esm.mjs",
|
|
21
|
-
"require": "./dist/pkg/feature-flags.cjs.js"
|
|
22
|
-
"types": "./dist/pkg/types/feature-flags.d.ts"
|
|
22
|
+
"require": "./dist/pkg/feature-flags.cjs.js"
|
|
23
23
|
},
|
|
24
24
|
"./react": {
|
|
25
|
+
"types": "./dist/pkg/types/react.d.ts",
|
|
25
26
|
"import": "./dist/pkg/react.esm.mjs",
|
|
26
|
-
"require": "./dist/pkg/react.cjs.js"
|
|
27
|
-
"types": "./dist/pkg/types/react.d.ts"
|
|
27
|
+
"require": "./dist/pkg/react.cjs.js"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist/pkg"
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
|
-
"test:jest": "jest --maxWorkers=2",
|
|
34
|
+
"test:jest": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --maxWorkers=2",
|
|
35
35
|
"test:playwright": "npx playwright test --retries=5 --reporter=list",
|
|
36
36
|
"test:package": "node ./tests/package/scripts/test-package.mjs",
|
|
37
37
|
"test:browserstack:full": "jest --config jest.browserstack.config.js --suite=full",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"dependencies": {
|
|
101
101
|
"@rrweb/record": "2.1.0",
|
|
102
102
|
"fflate": "0.8.3",
|
|
103
|
-
"
|
|
103
|
+
"undici": "7.30.1"
|
|
104
104
|
},
|
|
105
105
|
"devDependencies": {
|
|
106
106
|
"@babel/core": "^7.29.6",
|
|
@@ -122,9 +122,7 @@
|
|
|
122
122
|
"jest-expect-message": "^1.1.3",
|
|
123
123
|
"jest-localstorage-mock": "^2.4.26",
|
|
124
124
|
"jest-raw-loader": "^1.0.1",
|
|
125
|
-
"path-exists-cli": "^2.0.0",
|
|
126
125
|
"playwright": "1.58.2",
|
|
127
|
-
"prettier": "^3.8.1",
|
|
128
126
|
"rollup": "^4.60.0",
|
|
129
127
|
"rollup-plugin-dts": "^6.4.1",
|
|
130
128
|
"rollup-plugin-json": "^4.0.0",
|
|
@@ -132,9 +130,9 @@
|
|
|
132
130
|
"rollup-plugin-string": "^3.0.0",
|
|
133
131
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
134
132
|
"selenium-webdriver": "^4.41.0",
|
|
135
|
-
"terser": "^5.46.1",
|
|
136
133
|
"ts-jest": "^29.4.6",
|
|
137
134
|
"tslib": "^2.8.1",
|
|
135
|
+
"typescript": "^6.0.2",
|
|
138
136
|
"ua-parser-js": "^2.0.10"
|
|
139
137
|
},
|
|
140
138
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|