From be0d4c8fc3feaab7cfef3a40a1e9bfc2bf5fc186 Mon Sep 17 00:00:00 2001 From: "Castro, Mario" Date: Fri, 27 Feb 2026 17:36:26 -0300 Subject: [PATCH 1/5] Fix pagination issues with Cosmos DB --- .../src/helpers/query-helper.ts | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/packages/framework-provider-azure/src/helpers/query-helper.ts b/packages/framework-provider-azure/src/helpers/query-helper.ts index 21d1a9240..7726928ea 100644 --- a/packages/framework-provider-azure/src/helpers/query-helper.ts +++ b/packages/framework-provider-azure/src/helpers/query-helper.ts @@ -29,6 +29,8 @@ export async function replaceOrDeleteItem( } } +const DEFAULT_PAGE_SIZE = 100 + export async function search( cosmosDb: CosmosClient, config: BoosterConfig, @@ -43,9 +45,7 @@ export async function search( const logger = getLogger(config, 'query-helper#search') const filterExpression = buildFilterExpression(filters) const projectionsExpression = buildProjections(projections) - const queryDefinition = `SELECT ${projectionsExpression} FROM c ${ - filterExpression !== '' ? `WHERE ${filterExpression}` : filterExpression - }` + const queryDefinition = `SELECT ${projectionsExpression} FROM c ${filterExpression !== '' ? `WHERE ${filterExpression}` : filterExpression}` const finalQuery = queryDefinition + buildOrderExpression(order) const querySpec: SqlQuerySpec = { @@ -69,19 +69,24 @@ export async function search( // Use Cosmos DB's continuation token pagination const feedOptions: FeedOptions = {} - if (limit) { - feedOptions.maxItemCount = limit - } + // Extract continuation token from the cursor (backward compatibility) if (afterCursor?.continuationToken) { feedOptions.continuationToken = afterCursor.continuationToken - } else if (!canUseContinuationToken || hasLegacyCursor) { + } + + // Azure Cosmos DB requires maxItemCount when using continuation tokens + // Always set maxItemCount when limit is provided or when using continuation token + if (limit || afterCursor?.continuationToken) { + feedOptions.maxItemCount = limit ?? DEFAULT_PAGE_SIZE + } + + if (!afterCursor?.continuationToken && (!canUseContinuationToken || hasLegacyCursor)) { // Legacy cursor format - fallback to OFFSET for backward compatibility const offset = afterCursor?.id ? parseInt(afterCursor.id) : 0 - let legacyQuery = `${finalQuery} OFFSET ${offset}` - if (limit) { - legacyQuery += ` LIMIT ${limit} ` - } + // Azure Cosmos DB requires LIMIT when using OFFSET + const effectiveLimit = limit ?? DEFAULT_PAGE_SIZE + const legacyQuery = `${finalQuery} OFFSET ${offset} LIMIT ${effectiveLimit} ` const legacyQuerySpec = { ...querySpec, query: legacyQuery } const { resources } = await container.items.query(legacyQuerySpec).fetchAll() @@ -91,7 +96,7 @@ export async function search( items: processedResources ?? [], count: processedResources.length, cursor: { - id: (offset + processedResources.length).toString(), + id: (offset + effectiveLimit).toString(), }, } } @@ -101,12 +106,16 @@ export async function search( const finalResources = processResources(resources || []) + // cursor.id advances by the page size (limit) to maintain consistent page-based offsets + // that frontends rely on (e.g., limit=5 produces cursors 5, 10 ,15, ...) + const previousOffset = afterCursor?.id ? parseInt(afterCursor.id) : 0 + const effectiveLimit = limit ?? DEFAULT_PAGE_SIZE + let cursor: Record | undefined if (continuationToken) { - cursor = { continuationToken } + cursor = { continuationToken, id: (previousOffset + effectiveLimit).toString() } } else if (finalResources.length > 0) { - const currentOffset = afterCursor?.id && !isNaN(parseInt(afterCursor.id)) ? parseInt(afterCursor.id) : 0 - cursor = { id: (currentOffset + finalResources.length).toString() } // Use the length of the results to calculate the next id + cursor = { id: (previousOffset + effectiveLimit).toString() } } return { From 395e5504634b9467b42474b61bd6e3ffe96e470d Mon Sep 17 00:00:00 2001 From: "Castro, Mario" Date: Fri, 27 Feb 2026 18:11:02 -0300 Subject: [PATCH 2/5] Add rush change file --- .../fix-cosmos-pagination_2026-02-27-21-10.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@boostercloud/framework-core/fix-cosmos-pagination_2026-02-27-21-10.json diff --git a/common/changes/@boostercloud/framework-core/fix-cosmos-pagination_2026-02-27-21-10.json b/common/changes/@boostercloud/framework-core/fix-cosmos-pagination_2026-02-27-21-10.json new file mode 100644 index 000000000..085a97bd2 --- /dev/null +++ b/common/changes/@boostercloud/framework-core/fix-cosmos-pagination_2026-02-27-21-10.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@boostercloud/framework-core", + "comment": "Fix pagination issues with Cosmos DB", + "type": "patch" + } + ], + "packageName": "@boostercloud/framework-core" +} \ No newline at end of file From 04d10e1fcc515080f5e97c39fb72b31135335d82 Mon Sep 17 00:00:00 2001 From: Mario Castro Squella Date: Mon, 2 Mar 2026 16:56:06 -0300 Subject: [PATCH 3/5] Update lock file --- common/config/rush/pnpm-lock.yaml | 347 ++++++++++++++++++------------ 1 file changed, 205 insertions(+), 142 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 7676f4fbb..1ba9293cf 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: specifier: 3.7.13 version: 3.7.13(graphql@16.12.0)(react@17.0.2)(subscriptions-transport-ws@0.11.0(graphql@16.12.0)) '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -47,7 +47,7 @@ importers: version: 8.18.0 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/jsonwebtoken': specifier: 9.0.8 @@ -104,10 +104,10 @@ importers: ../../packages/cli: dependencies: '@boostercloud/framework-core': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-core '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -150,10 +150,10 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/application-tester': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../application-tester '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@oclif/test': specifier: ^4.1.10 @@ -264,7 +264,7 @@ importers: ../../packages/framework-common-helpers: dependencies: '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -280,7 +280,7 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/chai': specifier: 4.2.18 @@ -370,10 +370,10 @@ importers: ../../packages/framework-core: dependencies: '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect/cli': specifier: 0.56.2 @@ -437,10 +437,10 @@ importers: version: 8.18.0 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@boostercloud/metadata-booster': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../metadata-booster '@types/chai': specifier: 4.2.18 @@ -545,22 +545,22 @@ importers: ../../packages/framework-integration-tests: dependencies: '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-core': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-core '@boostercloud/framework-provider-aws': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-aws '@boostercloud/framework-provider-azure': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-azure '@boostercloud/framework-provider-local': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-local '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -618,25 +618,25 @@ importers: specifier: 3.7.13 version: 3.7.13(graphql@16.12.0)(react@17.0.2)(subscriptions-transport-ws@0.11.0(graphql@16.12.0)) '@boostercloud/application-tester': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../application-tester '@boostercloud/cli': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../cli '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@boostercloud/framework-provider-aws-infrastructure': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-aws-infrastructure '@boostercloud/framework-provider-azure-infrastructure': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-azure-infrastructure '@boostercloud/framework-provider-local-infrastructure': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-local-infrastructure '@boostercloud/metadata-booster': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../metadata-booster '@seald-io/nedb': specifier: 4.0.2 @@ -777,10 +777,10 @@ importers: ../../packages/framework-provider-aws: dependencies: '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -790,7 +790,7 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/aws-lambda': specifier: 8.10.48 @@ -943,13 +943,13 @@ importers: specifier: ^1.170.0 version: 1.204.0 '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-provider-aws': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-aws '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -983,7 +983,7 @@ importers: version: 1.10.2 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/archiver': specifier: 5.1.0 @@ -1097,10 +1097,10 @@ importers: specifier: ~1.1.0 version: 1.1.4 '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -1110,7 +1110,7 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/chai': specifier: 4.2.18 @@ -1206,16 +1206,16 @@ importers: specifier: ~4.7.0 version: 4.7.0 '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-core': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-core '@boostercloud/framework-provider-azure': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-azure '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@cdktf/provider-azurerm': specifier: 14.23.1 @@ -1285,7 +1285,7 @@ importers: version: 11.0.5 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/chai': specifier: 4.2.18 @@ -1366,10 +1366,10 @@ importers: ../../packages/framework-provider-local: dependencies: '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -1385,7 +1385,7 @@ importers: version: 8.18.0 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/chai': specifier: 4.2.18 @@ -1481,13 +1481,13 @@ importers: ../../packages/framework-provider-local-infrastructure: dependencies: '@boostercloud/framework-common-helpers': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-common-helpers '@boostercloud/framework-provider-local': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-provider-local '@boostercloud/framework-types': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../framework-types '@effect-ts/core': specifier: ^0.60.4 @@ -1506,7 +1506,7 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/chai': specifier: 4.2.18 @@ -1642,10 +1642,10 @@ importers: version: 8.18.0 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@boostercloud/metadata-booster': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../metadata-booster '@types/chai': specifier: 4.2.18 @@ -1739,7 +1739,7 @@ importers: version: 2.8.1 devDependencies: '@boostercloud/eslint-config': - specifier: workspace:^3.4.3 + specifier: workspace:^4.0.0 version: link:../../tools/eslint-config '@types/node': specifier: ^20.17.17 @@ -3102,6 +3102,10 @@ packages: resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@istanbuljs/load-nyc-config@1.1.0': resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -3262,6 +3266,10 @@ packages: resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} engines: {node: '>= 10.0.0'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -3686,6 +3694,10 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -3694,6 +3706,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + ansis@3.17.0: resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} engines: {node: '>=14'} @@ -3864,36 +3880,6 @@ packages: bare-abort-controller: optional: true - bare-fs@4.5.3: - resolution: {integrity: sha512-9+kwVx8QYvt3hPWnmb19tPnh38c6Nihz8Lx3t0g9+4GoIf3/fTgYwM4Z6NxgI+B9elLQA7mLE9PpqcWtOMRDiQ==} - engines: {bare: '>=1.16.0'} - peerDependencies: - bare-buffer: '*' - peerDependenciesMeta: - bare-buffer: - optional: true - - bare-os@3.6.2: - resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} - engines: {bare: '>=1.14.0'} - - bare-path@3.0.0: - resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} - - bare-stream@2.7.0: - resolution: {integrity: sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==} - peerDependencies: - bare-buffer: '*' - bare-events: '*' - peerDependenciesMeta: - bare-buffer: - optional: true - bare-events: - optional: true - - bare-url@2.3.2: - resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==} - base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -4096,6 +4082,9 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -4560,6 +4549,9 @@ packages: duration@0.2.2: resolution: {integrity: sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -4583,6 +4575,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -5028,6 +5023,10 @@ packages: resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} engines: {node: '>=8.0.0'} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -5168,6 +5167,11 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + glob@13.0.0: resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} engines: {node: 20 || >=22} @@ -5689,6 +5693,9 @@ packages: iterall@1.3.0: resolution: {integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jake@10.9.4: resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} engines: {node: '>=10'} @@ -5805,6 +5812,9 @@ packages: just-extend@6.2.0: resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} + jwa@1.4.2: + resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + jwa@2.0.1: resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} @@ -5812,6 +5822,9 @@ packages: resolution: {integrity: sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==} engines: {node: '>=14'} + jws@3.2.3: + resolution: {integrity: sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==} + jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} @@ -5963,6 +5976,9 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.5: resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} @@ -6453,6 +6469,9 @@ packages: resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} engines: {node: '>=8'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -6505,6 +6524,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.1: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} @@ -7184,6 +7207,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -7213,6 +7240,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -7295,8 +7326,8 @@ packages: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - tar-fs@3.1.1: - resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} tar-stream@1.6.2: resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} @@ -7676,6 +7707,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -9034,7 +9069,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - bare-abort-controller - - bare-buffer - bufferutil - debug - encoding @@ -9078,7 +9112,7 @@ snapshots: cdktf: 0.21.0(constructs@10.4.2) codemaker: 1.112.0 deep-equal: 2.2.3 - glob: 13.0.0 + glob: 10.5.0 graphology: 0.26.0(graphology-types@0.24.7) graphology-types: 0.24.7 jsii-rosetta: 5.8.8 @@ -9098,10 +9132,6 @@ snapshots: dependencies: nan: 2.25.0 prebuild-install: 7.1.3 - transitivePeerDependencies: - - bare-abort-controller - - bare-buffer - - react-native-b4a '@cdktf/provider-azurerm@14.23.1(cdktf@0.21.0(constructs@10.4.5))(constructs@10.4.5)': dependencies: @@ -9115,7 +9145,7 @@ snapshots: '@types/node': 18.19.101 codemaker: 1.112.0 fs-extra: 8.1.0 - glob: 13.0.0 + glob: 10.5.0 transitivePeerDependencies: - constructs - debug @@ -9368,6 +9398,15 @@ snapshots: dependencies: '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 @@ -9535,6 +9574,9 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.6 '@parcel/watcher-win32-x64': 2.5.6 + '@pkgjs/parseargs@0.11.0': + optional: true + '@rtsao/scc@1.1.0': {} '@seald-io/binary-search-tree@1.0.3': {} @@ -10105,6 +10147,8 @@ snapshots: ansi-regex@5.0.1: {} + ansi-regex@6.2.2: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -10113,6 +10157,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.3: {} + ansis@3.17.0: {} anymatch@3.1.3: @@ -10156,7 +10202,7 @@ snapshots: archiver-utils@5.0.2: dependencies: - glob: 13.0.0 + glob: 10.5.0 graceful-fs: 4.2.11 is-stream: 2.0.1 lazystream: 1.0.1 @@ -10334,41 +10380,6 @@ snapshots: bare-events@2.8.2: {} - bare-fs@4.5.3: - dependencies: - bare-events: 2.8.2 - bare-path: 3.0.0 - bare-stream: 2.7.0(bare-events@2.8.2) - bare-url: 2.3.2 - fast-fifo: 1.3.2 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - optional: true - - bare-os@3.6.2: - optional: true - - bare-path@3.0.0: - dependencies: - bare-os: 3.6.2 - optional: true - - bare-stream@2.7.0(bare-events@2.8.2): - dependencies: - streamx: 2.23.0 - optionalDependencies: - bare-events: 2.8.2 - transitivePeerDependencies: - - bare-abort-controller - - react-native-b4a - optional: true - - bare-url@2.3.2: - dependencies: - bare-path: 3.0.0 - optional: true - base64-js@1.5.1: {} base64-url@2.3.3: {} @@ -10559,7 +10570,6 @@ snapshots: transitivePeerDependencies: - '@types/react' - bare-abort-controller - - bare-buffer - bufferutil - debug - encoding @@ -10654,6 +10664,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chownr@1.1.4: {} + chownr@2.0.0: {} ci-info@2.0.0: {} @@ -11144,6 +11156,8 @@ snapshots: d: 1.0.2 es5-ext: 0.10.64 + eastasianwidth@0.2.0: {} + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 @@ -11165,6 +11179,8 @@ snapshots: emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + encodeurl@2.0.0: {} end-of-stream@1.4.5: @@ -11812,6 +11828,11 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 3.0.7 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -11965,6 +11986,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@13.0.0: dependencies: minimatch: 10.1.1 @@ -12517,6 +12547,12 @@ snapshots: iterall@1.3.0: {} + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jake@10.9.4: dependencies: async: 3.2.6 @@ -12651,7 +12687,7 @@ snapshots: jsonwebtoken@9.0.2: dependencies: - jws: 4.0.1 + jws: 3.2.3 lodash.includes: 4.3.0 lodash.isboolean: 3.0.3 lodash.isinteger: 4.0.4 @@ -12675,6 +12711,12 @@ snapshots: just-extend@6.2.0: {} + jwa@1.4.2: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 @@ -12692,6 +12734,11 @@ snapshots: transitivePeerDependencies: - supports-color + jws@3.2.3: + dependencies: + jwa: 1.4.2 + safe-buffer: 5.2.1 + jws@4.0.1: dependencies: jwa: 2.0.1 @@ -12839,6 +12886,8 @@ snapshots: lowercase-keys@2.0.0: {} + lru-cache@10.4.3: {} + lru-cache@11.2.5: {} lru-cache@5.1.1: @@ -13379,6 +13428,8 @@ snapshots: lodash.flattendeep: 4.4.0 release-zalgo: 1.0.0 + package-json-from-dist@1.0.1: {} + pako@1.0.11: {} parent-module@1.0.1: @@ -13419,6 +13470,11 @@ snapshots: path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-scurry@2.0.1: dependencies: lru-cache: 11.2.5 @@ -13488,12 +13544,8 @@ snapshots: pump: 3.0.3 rc: 1.2.8 simple-get: 4.0.1 - tar-fs: 3.1.1 + tar-fs: 2.1.4 tunnel-agent: 0.6.0 - transitivePeerDependencies: - - bare-abort-controller - - bare-buffer - - react-native-b4a prelude-ls@1.1.2: {} @@ -13776,7 +13828,7 @@ snapshots: rimraf@5.0.10: dependencies: - glob: 13.0.0 + glob: 10.5.0 run-applescript@7.1.0: {} @@ -14222,6 +14274,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -14263,6 +14321,10 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + strip-bom@3.0.0: {} strip-bom@4.0.0: {} @@ -14355,17 +14417,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - tar-fs@3.1.1: + tar-fs@2.1.4: dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 pump: 3.0.3 - tar-stream: 3.1.7 - optionalDependencies: - bare-fs: 4.5.3 - bare-path: 3.0.0 - transitivePeerDependencies: - - bare-abort-controller - - bare-buffer - - react-native-b4a + tar-stream: 2.2.0 tar-stream@1.6.2: dependencies: @@ -14795,6 +14852,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + wrappy@1.0.2: {} write-file-atomic@3.0.3: From 589add385df9ab3f6d9b9289cae1de9a841ebe44 Mon Sep 17 00:00:00 2001 From: "Castro, Mario" Date: Tue, 3 Mar 2026 12:17:41 -0300 Subject: [PATCH 4/5] Fix integration tests --- .../end-to-end/read-models.integration.ts | 58 +++---------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/packages/framework-integration-tests/integration/provider-unaware/end-to-end/read-models.integration.ts b/packages/framework-integration-tests/integration/provider-unaware/end-to-end/read-models.integration.ts index a383469ae..469d609af 100644 --- a/packages/framework-integration-tests/integration/provider-unaware/end-to-end/read-models.integration.ts +++ b/packages/framework-integration-tests/integration/provider-unaware/end-to-end/read-models.integration.ts @@ -1548,23 +1548,7 @@ describe('Read models end-to-end tests', () => { if (cursor) { if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { - // Cursor can be either continuation token format or legacy offset format - if (cursor.continuationToken) { - // New continuation token format - expect(cursor.continuationToken).to.be.a('string') - expect(cursor.continuationToken).to.not.be.empty - expect(cursor.id).to.be.undefined - } else if (cursor.id) { - expect(cursor.id).to.be.a('string') - expect(cursor.id).to.not.be.empty - expect(cursor.continuationToken).to.be.undefined - // If it's a numeric string (legacy format), verify it matches the expected sequence - if (/^\d+$/.test(cursor.id)) { - expect(cursor.id).to.equal((i + 1).toString()) - } - } else { - throw new Error('Cursor must have either continuationToken or id field') - } + expect(cursor.id).to.equal((i + 1).toString()) } else { expect(cursor.id).to.equal(currentPageCartData[0].id) } @@ -1621,7 +1605,7 @@ describe('Read models end-to-end tests', () => { if (result.cursor) { expect(result.cursor.id).to.be.a('string') expect(result.cursor.id).to.not.be.empty - // Should be '2' (1 + 1 result returned) based on our fixed logic: currentOffset + finalResources.length + // Should be '2' (offset 1 + limit 1) based page-based offset logic: offset + effectiveLimit expect(result.cursor.id).to.equal('2') // Legacy cursors don't have continuation tokens expect(result.cursor.continuationToken).to.be.undefined @@ -1751,16 +1735,8 @@ describe('Read models end-to-end tests', () => { }, ]) expect(cartShippingAddress.count).to.equal(1) - // Cursor may be undefined when there are no more pages (continuation token approach) - if (cartShippingAddress.cursor) { - expect(cartShippingAddress.cursor.id).to.be.a('string') - expect(cartShippingAddress.cursor.id).to.not.be.empty - // For Azure/Local with legacy pagination, verify it's "1" for the first page - if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { - if (/^\d+$/.test(cartShippingAddress.cursor.id)) { - expect(cartShippingAddress.cursor.id).to.equal('1') - } - } + if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { + expect(cartShippingAddress.cursor.id).to.equal('100') } }) @@ -1903,19 +1879,7 @@ describe('Read models end-to-end tests', () => { if (cursor) { if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { - // With continuation token, cursor.id can be either the legacy format (i + 1).toString() or a continuation token - // For legacy format, verify it matches the expected sequence; for continuation token, just verify it's valid - expect(cursor.id).to.be.a('string') - expect(cursor.id).to.not.be.empty - // If it's a numeric string (legacy format), verify it matches the expected sequence - if (/^\d+$/.test(cursor.id)) { - expect(cursor.id).to.equal((i + 1).toString()) - } - // If it has continuationToken property, it's the new format - verify it advances - if (cursor.continuationToken) { - expect(cursor.continuationToken).to.be.a('string') - expect(cursor.continuationToken).to.not.be.empty - } + expect(cursor.id).to.equal('100') } else { expect(cursor.id).to.equal(currentPageCartData[0].id) } @@ -2087,16 +2051,8 @@ describe('Read models end-to-end tests', () => { }, ]) expect(cartMyAddress.count).to.equal(1) - // Cursor may be undefined when there are no more pages (continuation token approach) - if (cartMyAddress.cursor) { - expect(cartMyAddress.cursor.id).to.be.a('string') - expect(cartMyAddress.cursor.id).to.not.be.empty - // For Azure/Local with legacy pagination, verify it's "1" for the first page - if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { - if (/^\d+$/.test(cartMyAddress.cursor.id)) { - expect(cartMyAddress.cursor.id).to.equal('1') - } - } + if (process.env.TESTED_PROVIDER === 'AZURE' || process.env.TESTED_PROVIDER === 'LOCAL') { + expect(cartMyAddress.cursor.id).to.equal('100') } }) }) From 50d87eb7267f12ae3face6c49881d4c41256fb2a Mon Sep 17 00:00:00 2001 From: "Castro, Mario" Date: Fri, 13 Mar 2026 18:08:17 -0300 Subject: [PATCH 5/5] Fix potential bugs --- .../src/helpers/query-helper.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/framework-provider-azure/src/helpers/query-helper.ts b/packages/framework-provider-azure/src/helpers/query-helper.ts index 7726928ea..30852a5ee 100644 --- a/packages/framework-provider-azure/src/helpers/query-helper.ts +++ b/packages/framework-provider-azure/src/helpers/query-helper.ts @@ -76,14 +76,15 @@ export async function search( } // Azure Cosmos DB requires maxItemCount when using continuation tokens - // Always set maxItemCount when limit is provided or when using continuation token - if (limit || afterCursor?.continuationToken) { + // Always set maxItemCount in the continuation token path to ensure consistent page sizes + if (limit || afterCursor?.continuationToken || canUseContinuationToken) { feedOptions.maxItemCount = limit ?? DEFAULT_PAGE_SIZE } if (!afterCursor?.continuationToken && (!canUseContinuationToken || hasLegacyCursor)) { // Legacy cursor format - fallback to OFFSET for backward compatibility - const offset = afterCursor?.id ? parseInt(afterCursor.id) : 0 + const parsedLegacyId = afterCursor?.id ? parseInt(afterCursor.id, 10) : NaN + const offset = Number.isFinite(parsedLegacyId) ? parsedLegacyId : 0 // Azure Cosmos DB requires LIMIT when using OFFSET const effectiveLimit = limit ?? DEFAULT_PAGE_SIZE const legacyQuery = `${finalQuery} OFFSET ${offset} LIMIT ${effectiveLimit} ` @@ -108,7 +109,8 @@ export async function search( // cursor.id advances by the page size (limit) to maintain consistent page-based offsets // that frontends rely on (e.g., limit=5 produces cursors 5, 10 ,15, ...) - const previousOffset = afterCursor?.id ? parseInt(afterCursor.id) : 0 + const parsedId = afterCursor?.id ? parseInt(afterCursor.id, 10) : NaN + const previousOffset = Number.isFinite(parsedId) ? parsedId : 0 const effectiveLimit = limit ?? DEFAULT_PAGE_SIZE let cursor: Record | undefined