Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
892ff4c
feat: automated TS Serving API update
hassaantahir0 Apr 3, 2026
9f981db
Merge branch 'main-convert' into api-serving-update-6390
JosephSamirL Apr 6, 2026
1178fb5
chore(ci): migrate remaining workflows from Node 18 to Node 22
abbaseya Apr 6, 2026
420a408
Merge pull request #370 from convertcom/api-serving-update-6390
JosephSamirL Apr 6, 2026
72c286d
Merge branch 'main-convert' into chore/sync-main
abbaseya Apr 6, 2026
34984d3
Merge pull request #374 from convertcom/chore/sync-main
abbaseya Apr 6, 2026
273990d
feat: automated TS Serving API update
hassaantahir0 Apr 8, 2026
934d12c
Merge pull request #375 from convertcom/api-serving-update-6424
JosephSamirL Apr 15, 2026
8183b67
feat: adding cookie (exist , not exist) conditions
JosephSamirL Apr 15, 2026
f5529c3
Merge pull request #376 from convertcom/feat/adding-exist-not-exist-c…
JosephSamirL Apr 15, 2026
023151d
chore: trigger QA workflow for release PR
abbaseya Apr 6, 2026
4f3f41f
chore(deps): sync workspace peer dep ranges to latest published
abbaseya May 18, 2026
a85ad99
chore: update yarn lock
abbaseya May 18, 2026
1ab9afe
fix(ci): pin Playwright browsers to project's installed version
abbaseya May 18, 2026
6df91f4
Merge pull request #378 from convertcom/fix/config-types
JosephSamirL May 18, 2026
c379e1d
feat: automated TS Serving API update
abbaseya May 19, 2026
3657ed4
Merge pull request #379 from convertcom/api-serving-update-6604
JosephSamirL May 19, 2026
38cc9a9
fix(ci): pin yarn to 4.10.3 and regenerate lockfile
abbaseya May 20, 2026
d4e3ef4
Merge pull request #381 from convertcom/fix/yarn-lock-version-mismatch
JosephSamirL May 20, 2026
90e4730
fix(context): forward all BucketingAttributes to ExperienceManager
abbaseya May 21, 2026
b215167
Merge pull request #382 from convertcom/fix/context-forward-bucketing…
JosephSamirL May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18]
node: [22]
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/setup-node@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v4
with:
node-version: '18.x'
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- name: Resolve tag
run: echo "RELEASE_TAG=${{ github.event.release.tag_name || inputs.tag }}" >> $GITHUB_ENV
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ jobs:
corepack enable
corepack prepare yarn@stable --activate

- name: Install dependencies
run: yarn

- name: Install Playwright browsers
run: |
cd packages/js-sdk
npx playwright install --with-deps chromium
yarn playwright install --with-deps chromium

- name: Runs the SDK QA checks
env:
CONVERT_STAGING_SDK_KEY: ${{ secrets.CONVERT_STAGING_SDK_KEY }}
CONVERT_STAGING_SDK_KEY2: ${{ secrets.CONVERT_STAGING_SDK_KEY2 }}
CONVERT_STAGING_SDK_KEY2_SECRET: ${{ secrets.CONVERT_STAGING_SDK_KEY2_SECRET }}
run: |
yarn
cd packages/js-sdk
yarn lint
yarn build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
registry-url: https://registry.npmjs.org
- name: Install deps
run: |
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"demo:cloudflare:start": "cd demo/cloudflare-workers && yarn dev"
},
"private": true,
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f",
"workspaces": [
"packages/*",
"demo/*"
Expand Down
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-event": ">=2.1.3",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0",
"@convertcom/js-sdk-types": ">=3.11.0",
"@convertcom/js-sdk-utils": ">=2.2.3"
}
}
2 changes: 1 addition & 1 deletion packages/bucketing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"peerDependencies": {
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0",
"@convertcom/js-sdk-types": ">=3.11.0",
"@convertcom/js-sdk-utils": ">=2.2.3"
}
}
4 changes: 2 additions & 2 deletions packages/data/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-event": ">=2.1.3",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-rules": ">=2.1.3",
"@convertcom/js-sdk-types": ">=3.9.0",
"@convertcom/js-sdk-rules": ">=2.1.4",
"@convertcom/js-sdk-types": ">=3.11.0",
"@convertcom/js-sdk-utils": ">=2.2.3"
}
}
2 changes: 1 addition & 1 deletion packages/event/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,6 @@
"peerDependencies": {
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0"
"@convertcom/js-sdk-types": ">=3.11.0"
}
}
2 changes: 1 addition & 1 deletion packages/experience/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,6 @@
"@convertcom/js-sdk-data": ">=3.3.3",
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0"
"@convertcom/js-sdk-types": ">=3.11.0"
}
}
4 changes: 2 additions & 2 deletions packages/js-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@
"@convertcom/js-sdk-event": ">=2.1.3",
"@convertcom/js-sdk-experience": ">=2.3.2",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-rules": ">=2.1.3",
"@convertcom/js-sdk-rules": ">=2.1.4",
"@convertcom/js-sdk-segments": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0",
"@convertcom/js-sdk-types": ">=3.11.0",
"@convertcom/js-sdk-utils": ">=2.2.3"
}
}
6 changes: 2 additions & 4 deletions packages/js-sdk/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,8 @@ export class Context implements ContextInterface {
this._visitorId,
experienceKey,
{
...attributes,
visitorProperties, // represents audiences
locationProperties: attributes?.locationProperties, // represents site_area/locations
updateVisitorProperties: attributes?.updateVisitorProperties,
environment: attributes?.environment || this._environment
}
);
Expand Down Expand Up @@ -190,9 +189,8 @@ export class Context implements ContextInterface {
const bucketedVariations = this._experienceManager.selectVariations(
this._visitorId,
{
...attributes,
visitorProperties, // represents audiences
locationProperties: attributes?.locationProperties, // represents site_area/locations
updateVisitorProperties: attributes?.updateVisitorProperties,
environment: attributes?.environment || this._environment
}
);
Expand Down
72 changes: 72 additions & 0 deletions packages/js-sdk/tests/context.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,78 @@ describe('Context tests', function () {
done
);
});
it('Should forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperience', function () {
const experienceKey = 'test-experience-ab-fullstack-2';
const originalSelectVariation =
experienceManager.selectVariation.bind(experienceManager);
let capturedAttributes;
experienceManager.selectVariation = function (
capturedVisitorId,
capturedExperienceKey,
attributes
) {
capturedAttributes = attributes;
return originalSelectVariation(
capturedVisitorId,
capturedExperienceKey,
attributes
);
};
try {
context.runExperience(experienceKey, {
locationProperties: {url: 'https://convert.com/'},
visitorProperties: {varName3: 'something'},
enableTracking: false,
forceVariationId: '100299461',
ignoreLocationProperties: true,
updateVisitorProperties: true
});
expect(capturedAttributes).to.include({
enableTracking: false,
forceVariationId: '100299461',
ignoreLocationProperties: true,
updateVisitorProperties: true
});
expect(capturedAttributes.locationProperties).to.deep.equal({
url: 'https://convert.com/'
});
} finally {
experienceManager.selectVariation = originalSelectVariation;
}
});
it('Should forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperiences', function () {
const originalSelectVariations =
experienceManager.selectVariations.bind(experienceManager);
let capturedAttributes;
experienceManager.selectVariations = function (
capturedVisitorId,
attributes
) {
capturedAttributes = attributes;
return originalSelectVariations(capturedVisitorId, attributes);
};
try {
context.runExperiences({
locationProperties: {url: 'https://convert.com/'},
visitorProperties: {varName3: 'something'},
enableTracking: false,
forceVariationId: '100299461',
ignoreLocationProperties: true,
updateVisitorProperties: true
});
expect(capturedAttributes).to.include({
enableTracking: false,
forceVariationId: '100299461',
ignoreLocationProperties: true,
updateVisitorProperties: true
});
expect(capturedAttributes.locationProperties).to.deep.equal({
url: 'https://convert.com/'
});
} finally {
experienceManager.selectVariations = originalSelectVariations;
}
});
it('Shoud successfully get a single feature and its status', function (done) {
this.timeout(test_timeout);
getSingleFeatureWithStatus(
Expand Down
2 changes: 1 addition & 1 deletion packages/rules/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"peerDependencies": {
"@convertcom/js-sdk-enums": ">=2.3.0",
"@convertcom/js-sdk-logger": ">=2.1.2",
"@convertcom/js-sdk-types": ">=3.9.0",
"@convertcom/js-sdk-types": ">=3.11.0",
"@convertcom/js-sdk-utils": ">=2.2.3"
}
}
29 changes: 23 additions & 6 deletions packages/rules/src/rule-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {RuleManagerInterface} from './interfaces/rule-manager';

import {
Config,
CookieMatchingOptions,
RuleElement,
RuleAnd,
RuleOrWhen,
Expand Down Expand Up @@ -165,15 +166,19 @@ export class RuleManager implements RuleManagerInterface {
rule: rule
})
);
return (
const hasMatching =
Object.prototype.hasOwnProperty.call(rule, 'matching') &&
typeof rule.matching === 'object' &&
Object.prototype.hasOwnProperty.call(rule.matching, 'match_type') &&
typeof rule.matching.match_type === 'string' &&
Object.prototype.hasOwnProperty.call(rule.matching, 'negated') &&
typeof rule.matching.negated === 'boolean' &&
Object.prototype.hasOwnProperty.call(rule, 'value')
);
typeof rule.matching.negated === 'boolean';
if (!hasMatching) return false;
const matchType = rule.matching.match_type as string;
if (matchType === CookieMatchingOptions.EXISTS || matchType === CookieMatchingOptions.DOES_NOT_EXIST) {
return true;
}
return Object.prototype.hasOwnProperty.call(rule, 'value');
}

/**
Expand Down Expand Up @@ -263,7 +268,7 @@ export class RuleManager implements RuleManagerInterface {
if (this.isValidRule(rule)) {
try {
const negation = rule.matching.negated || false;
const matching = rule.matching.match_type;
const matching = rule.matching.match_type as string;
if (this.getComparisonProcessorMethods().indexOf(matching) !== -1) {
if (data && typeof data === 'object') {
// Validate data key-value set.
Expand Down Expand Up @@ -314,7 +319,19 @@ export class RuleManager implements RuleManagerInterface {
);
}
}
} else {
}
// Key not found or data empty — for existence operators, evaluate with undefined
if (
matching === CookieMatchingOptions.EXISTS ||
matching === CookieMatchingOptions.DOES_NOT_EXIST
) {
return this._comparisonProcessor[matching](
undefined,
rule.value,
negation
);
}
if (!objectNotEmpty(data) && !this.isUsingCustomInterface(data)) {
this._loggerManager?.trace?.('RuleManager._processRuleItem()', {
warn: ERROR_MESSAGES.RULE_DATA_NOT_VALID,
data
Expand Down
Loading
Loading