Skip to content

Node 22 and Azure Functions v4 migration#1593

Merged
MarcAstr0 merged 27 commits intoboostercloud:mainfrom
Optum:node_22
Feb 17, 2026
Merged

Node 22 and Azure Functions v4 migration#1593
MarcAstr0 merged 27 commits intoboostercloud:mainfrom
Optum:node_22

Conversation

@MarcAstr0
Copy link
Collaborator

@MarcAstr0 MarcAstr0 commented Jan 30, 2026

Description

This PR adds Node 22 support for Booster. Booster 3.x works with Node 20, which is reaching EOL in April 2026. In the case of Azure, switching to Node 22 requires upgrading the Azure Functions runtime from v3 to v4. Version 4 introduces an imperative approach instead of a declarative one—functions are now defined programmatically in a functions.js file rather than the function.json files used in v3.

Another major change in the v4 @azure/functions SDK is the context type used in function requests (ContextInvocationContext). Wrappers were created for the different types of function requests.

Changes

  • Updated framework-provider-azure-infrastructure package to generate v4-compatible Azure Functions
  • Updated framework-provider-azure to work with the v4 @azure/functions SDK
  • Updated dependencies across all packages to support Node 22
  • Updated CI/CD actions and workflows for Node 22 compatibility
  • Added migration guide to documentation

Checks

  • Project Builds
  • Project passes tests and checks
  • Updated documentation accordingly

Additional information

Rockets targeting Azure infrastructure must be updated to implement mountFunctionsV4 instead of the now-deprecated mountCode and mountFunctions methods. See the migration guide for details.

Castro, Mario added 10 commits January 29, 2026 12:10
- Bump Node.js from v20 (Iron) to v22 (Jod) LTS
- Update Rush from 5.133.4 to 5.166.0
- Update nodeSupportedVersionRange to >=22.0.0 <23.0.0
- Update engine requirements across all packages
- Define type wrappers, guards, and helpers for v4 programming
model (HTTP, CosmosDB, EventHub, Timer, Web PubSub)
- Export types
from main package entry point
- Update adapters to use v4 InvocationContext and HttpResponseInit
- Add type definitions, guards, and helpers for all trigger types
- Fix parameter property syntax in tests for Node 22 compatibility
@MarcAstr0
Copy link
Collaborator Author

/integration sha=22a37ba

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

@github-actions
Copy link
Contributor

❌ Oh no! Integration tests have failed

@MarcAstr0
Copy link
Collaborator Author

/integration sha=39b572a

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

@github-actions
Copy link
Contributor

❌ Oh no! Integration tests have failed

@MarcAstr0
Copy link
Collaborator Author

/integration sha=9d6ec78

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

Castro, Mario and others added 2 commits January 30, 2026 15:59
- Bump validator 13.12.0 → 13.15.26, mock-jwks 1.0.3 → 1.0.10
- Add pnpm overrides in .pnpmfile.cjs for transitive vulns
- Fix TS7053 in http-service.ts (RequestOptions.headers union type)
- Update token verifier tests for jsonwebtoken 9.x iat claim
@github-actions
Copy link
Contributor

❌ Oh no! Integration tests have failed

@MarcAstr0
Copy link
Collaborator Author

/integration sha=9235aca

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

@github-actions
Copy link
Contributor

✅ Integration tests have finished successfully!

@MarcAstr0
Copy link
Collaborator Author

/integration sha=ca63936

@MarcAstr0
Copy link
Collaborator Author

/integration sha=2899da1

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 72 changed files in this pull request and generated 14 comments.

Files not reviewed (1)
  • website/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Contributor

✅ Integration tests have finished successfully!

Copy link
Contributor

@alvaroloes alvaroloes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude: ## Node 22 + Azure Functions v4 Migration — Code Review Summary

Overall, this is a solid and well-structured migration. The v3→v4 adapter rewrites are clean, the new type guards in azure-func-types.ts are well-written, and the rocket backward-compat via mountFunctionsV4 alongside deprecated mountCode/mountFunctions is thoughtful. The Web PubSub hub post-deploy update (replacing shell-based curl/az CLI with Azure SDK) is a good improvement.

🔴 Issues to address before merge

  1. .mocharc.yml — missing -- prefix (see inline comment)
  2. no-experimental-strip-types needs to be --no-experimental-strip-types. Without the prefix, Node ignores it and the experimental TS stripping stays active — tests may pass for wrong reasons.
  3. scheduled-adapter.tsisScheduledCommandInput doesn't validate typeName (see inline comment)
  4. The type guard only checks isTimerFunctionInput() but ScheduledCommandInput extends it with a typeName field. Any timer input will pass, even if it's missing typeName.
  5. pnpmfile.cjs — unbounded security overrides (see inline comment)
  6. minSafe ranges like '>=4.0.4' are unbounded upward and will match future major versions — contradicting the intent on L38.
  7. rocket-builder.tsfunctionAppName sanitization may break Kudu deploy URLs
  8. .replace(/(\W+)/gi, '_') converts dashes to underscores, but Azure Function App names use dashes. The sanitized name is used for Kudu deployment URLs (https://${functionAppName}.scm.azurewebsites.net), which would target a non-existent app if the real name has dashes.
  9. booster-token-verifier.test.tsdeepEqualinclude weakens assertions
  10. Changing .to.deep.equals() to .to.deep.include() means the test will pass even if user.claims has extra unexpected properties. If the migration doesn't change claim shapes, the original strict assertion should be preserved. If Node 22 adds extra claim fields, prefer updating the expected object rather than loosening the check.

🟡 Minor issues

  1. events-adapter.ts — typo in error message (see inline comment): AzureCosmosDBFunctioninputAzureCosmosDBFunctionInput
  2. azure-func-types.ts — JSDoc typo (see inline comment): objetcobject on L11

✅ What looks good

  • Type guards (isHttpFunctionInput, isCosmosDBFunctionInput, etc.) are well-implemented with proper null checks and property existence validation
    • Adapter rewrites (api-adapter.ts, health-adapter.ts, read-model-adapter.ts, subscription-model.ts) correctly migrate from Context to InvocationContext + typed inputs
      • booster-graphql-dispatcher.ts — the X-Booster-WebSocket-Message header addition is clean and backward-compatible
        • http-service.ts — conditional Content-Length header is correct
          • upgrade-v4.md migration guide is helpful
            • Terraform Web PubSub hub lifecycle.ignoreChanges pattern is appropriate for post-deploy managed resources
              • Rush/pnpm tooling version bumps look correct

Copy link
Contributor

@alvaroloes alvaroloes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codex: Revisión completada. He dejado 3 comentarios inline enfocados en riesgos no cubiertos por revisiones previas: 1) deploy que puede terminar en verde con subscriptions rotas si no aparece webpubsub_extension; 2) inconsistencia disconnect/disconnected que puede impedir el path correcto de desconexión; 3) logging excesivo de payload/metadata en connect con riesgo de exponer datos sensibles y aumentar ruido operativo. Recomiendo resolverlos antes de merge.

@MarcAstr0
Copy link
Collaborator Author

@alvaroloes about this comment: the suggested check is redundant because TypeScript already knows that typeName is a string based on the type narrowing from isTimerFunctionInput.

@MarcAstr0
Copy link
Collaborator Author

/integration sha=1185227c

@github-actions
Copy link
Contributor

⌛ Integration tests are running...

Check their status here 👈

@github-actions
Copy link
Contributor

✅ Integration tests have finished successfully!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 72 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • website/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MarcAstr0 MarcAstr0 merged commit fcbae22 into boostercloud:main Feb 17, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants