Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
da6b735 to
ad57b3e
Compare
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
f6daead to
7d7f0c1
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces an initial “Canvas App” (Salesforce Canvas / managed package) delivery path alongside the existing web app, desktop app, and browser extension flows, including environment detection, embedded-mode UI behavior, and Canvas-specific OAuth + routing.
Changes:
- Add a new
jetstream-canvasNx/Vite application and a Canvas-aware client routing/axios adapter layer. - Extend shared UI + jobs + download + permissions/ability logic to support
isCanvasApp()/ single-org embedded mode behaviors. - Add Salesforce managed-package (SFDX) assets + docs + CI workflow, and add API
/canvas/*routes for serving the Canvas app and handling OAuth callbacks.
Reviewed changes
Copilot reviewed 125 out of 137 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Bumps @testing-library/react lock entry. |
| package.json | Adds canvas build scripts + includes jetstream-canvas in CI build; bumps @testing-library/react. |
| libs/ui/src/lib/layout/Header.tsx | Renames isChromeExtension prop to isEmbeddedApp and updates conditional rendering. |
| libs/ui/src/lib/file-download-modal/options/FileDownloadGoogle.tsx | Treats Canvas app as “external Google picker” environment. |
| libs/ui/src/lib/file-download-modal/RecordDownloadModal.tsx | Allows Google download/upload flow in Canvas app. |
| libs/ui/src/lib/file-download-modal/FileFauxDownloadModal.tsx | Allows Google download/upload flow in Canvas app. |
| libs/ui/src/lib/file-download-modal/FileDownloadModal.tsx | Allows Google download/upload flow in Canvas app. |
| libs/shared/utils/src/lib/utils.ts | Adds urlSearchParamsToJson helper. |
| libs/shared/ui-utils/src/lib/shared-canvas-helpers.ts | Adds isCanvasApp() helper. |
| libs/shared/ui-utils/src/lib/hooks/useDriveExternalPicker.ts | Adds BroadcastChannel fallback and treats Canvas as popup-based picker flow. |
| libs/shared/ui-utils/src/index.ts | Re-exports new canvas helpers. |
| libs/shared/ui-core/src/state-management/load-records.state.ts | Gives Canvas app “unlimited” API limits similar to desktop/extension. |
| libs/shared/ui-core/src/jobs/Jobs.tsx | Uses external Google token store in Canvas app. |
| libs/shared/ui-core/src/jobs/JobWorker.ts | Treats Canvas app like extension for non-streaming bulk downloads. |
| libs/shared/ui-core/src/app/HeaderNavbar.tsx | Adds embedded-mode prop, fullscreen link handling for Canvas, and selected-org usage. |
| libs/shared/ui-app-state/src/lib/ui-app-state.ts | Adds Canvas-specific appInfo/serverUrl handling and single-org mode behavior. |
| libs/shared/data/src/lib/client-data.ts | Adds Canvas-specific preference getters/setters passing org context. |
| libs/features/platform-event-monitor/src/usePlatformEvent.ts | Adds subscribe/unsubscribe override hooks for non-CometD environments (Canvas). |
| libs/features/platform-event-monitor/src/index.ts | Re-exports override-related types. |
| libs/features/platform-event-monitor/src/PlatformEventMonitor.tsx | Accepts override fns and renames internal “chromeExtension” state. |
| libs/features/load-records/src/steps/SelectObjectAndFile.tsx | Enables Google picker + unlimited file size in Canvas app. |
| libs/features/load-records-multi-object/src/LoadRecordsMultiObject.tsx | Enables Google picker support in Canvas app. |
| libs/features/deploy/src/view-or-compare-metadata/ViewOrCompareMetadataSidebar.tsx | Renames extension-only flag to generic single-org mode flag. |
| libs/features/deploy/src/view-or-compare-metadata/ViewOrCompareMetadataModalFooter.tsx | Renames extension-only flag to generic single-org mode flag. |
| libs/features/deploy/src/view-or-compare-metadata/ViewOrCompareMetadataModal.tsx | Treats Canvas app as single-org mode for UI labels/behavior. |
| libs/features/deploy/src/DeployMetadataDeploymentTable.tsx | Treats Canvas app as single-org mode for button copy. |
| libs/features/deploy/src/DeployMetadataDeployment.tsx | Hides “deploy to different org” in single-org (extension/canvas) mode. |
| libs/auth/salesforce-oauth/src/lib/salesforce-oauth.ts | Adds Canvas OAuth init/callback with signed state payload. |
| libs/auth/acl/src/lib/acl.ts | Adds isCanvasApp to ability derivation and “web app” classification. |
| custom-typings/index.d.ts | Declares global __IS_CANVAS_APP__. |
| apps/landing/pages/web-extension/google-picker/index.tsx | Switches to shared “external picker” state hook. |
| apps/landing/pages/oauth-link/index.tsx | Refactors postMessage handling and minor JSX spacing tweak. |
| apps/landing/pages/canvas-auth/index.tsx | Adds Canvas OAuth “close window / return to app” landing page. |
| apps/landing/hooks/external-google-picker.hooks.ts | Generalizes picker hook for extension/canvas + adds BroadcastChannel fallback. |
| apps/jetstream-web-extension/src/utils/api-client.ts | Fixes double await. |
| apps/jetstream-web-extension/src/pages/app/App.tsx | Uses isEmbeddedApp prop instead of isChromeExtension. |
| apps/jetstream-web-extension/src/controllers/sf-misc.web-ext.controller.ts | Fixes HTTP error threshold (>= 300). |
| apps/jetstream-desktop/src/controllers/sf-misc.desktop.controller.ts | Fixes HTTP error threshold (>= 300). |
| apps/jetstream-canvas/vite.plugins.ts | Adds Vite plugin utilities for base href and file replacement. |
| apps/jetstream-canvas/vite.config.mts | Adds Vite config for Canvas app build/dev/test. |
| apps/jetstream-canvas/tsconfig.spec.json | Adds spec TS config for Canvas app. |
| apps/jetstream-canvas/tsconfig.json | Adds base TS config for Canvas app. |
| apps/jetstream-canvas/tsconfig.app.json | Adds app TS config for Canvas app. |
| apps/jetstream-canvas/src/utils/zip.ts | Adds ZIP streaming/creation utilities for Canvas downloads. |
| apps/jetstream-canvas/src/utils/canvas.utils.ts | Builds a SalesforceOrgUi from Canvas signed request context. |
| apps/jetstream-canvas/src/utils/canvas.types.ts | Adds Canvas org/api-connection type. |
| apps/jetstream-canvas/src/utils/canvas-axios-adapter.ts | Adds axios adapter that routes requests to in-app Canvas controllers. |
| apps/jetstream-canvas/src/utils/api-client.ts | Adds Canvas API client using Canvas SDK ajax bridge + org initialization. |
| apps/jetstream-canvas/src/main.tsx | Boots Canvas app, installs axios adapter, validates iframe context, initializes Canvas SDK. |
| apps/jetstream-canvas/src/main.scss | Adds Canvas app styling overrides. |
| apps/jetstream-canvas/src/environments/environment.ts | Adds Canvas dev environment config. |
| apps/jetstream-canvas/src/environments/environment.staging.ts | Adds Canvas staging environment config. |
| apps/jetstream-canvas/src/environments/environment.prod.ts | Adds Canvas prod environment config. |
| apps/jetstream-canvas/src/controllers/user.canvas.controller.ts | Adds (placeholder) feedback route wiring. |
| apps/jetstream-canvas/src/controllers/sf-record.canvas.controller.ts | Adds record APIs (binary upload, CRUD ops) for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/sf-query.canvas.controller.ts | Adds describe/query/queryMore routes for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/sf-misc.canvas.controller.ts | Adds misc routes (downloads, manual requests) for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/sf-metadata-tooling.canvas.controller.ts | Adds metadata tooling endpoints for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/sf-bulk-query-20-api.canvas.controller.ts | Adds Bulk Query 2.0 endpoints for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/sf-bulk-api.canvas.controller.ts | Adds Bulk API endpoints for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/route.utils.ts | Adds lightweight route creation/validation and response helpers for Canvas adapter routing. |
| apps/jetstream-canvas/src/controllers/preferences.canvas.controller.ts | Implements preference read/write via custom setting in Salesforce. |
| apps/jetstream-canvas/src/controllers/jetstream-data-sync.canvas.controller.ts | Adds placeholder data-sync routes. |
| apps/jetstream-canvas/src/controllers/canvas.routes.ts | Registers the Canvas app’s internal “API” routes. |
| apps/jetstream-canvas/src/assets/.gitkeep | Keeps assets directory in repo. |
| apps/jetstream-canvas/src/app/core/monaco-loader.ts | Configures Monaco loader paths and custom configuration. |
| apps/jetstream-canvas/src/app/core/config.ts | Adds Canvas router config/basename. |
| apps/jetstream-canvas/src/app/core/Login.tsx | Adds Canvas-specific auth/authorize UX and OAuth popup flow. |
| apps/jetstream-canvas/src/app/core/LazyLoad.tsx | Adds lazy-with-preload helper (ported). |
| apps/jetstream-canvas/src/app/core/AppInitializer.tsx | Initializes org state, DB, and Canvas preference sync. |
| apps/jetstream-canvas/src/app/app.tsx | Wires core providers, embedded header, and routes for Canvas app. |
| apps/jetstream-canvas/src/app/AppRoutes.tsx | Defines Canvas app route tree and platform-event overrides using Canvas SDK streaming. |
| apps/jetstream-canvas/project.json | Adds Nx targets for build/serve/test for Canvas app. |
| apps/jetstream-canvas/index.html | Adds Canvas app HTML template with injected Canvas SDK + signed request. |
| apps/jetstream-canvas/eslint.config.cjs | Adds eslint config for Canvas app project. |
| apps/docs/sidebars.ts | Adds managed-package doc page to docs sidebar. |
| apps/docs/docs/getting-started/managed-package/managed-package.mdx | Adds documentation for managed package / Canvas app usage. |
| apps/api/src/main.ts | Registers /canvas route with CSP frame-ancestors and router. |
| apps/api/src/app/routes/index.ts | Exports new canvasRoutes. |
| apps/api/src/app/routes/canvas.routes.ts | Adds API routes to serve Canvas app + static assets. |
| apps/api/src/app/controllers/sf-misc.controller.ts | Fixes HTTP error threshold (>= 300). |
| apps/api/src/app/controllers/sf-bulk-api.controller.ts | Fixes validator params for bulk zip upload. |
| apps/api/src/app/controllers/canvas.controller.ts | Implements Canvas signed_request verification + user-approval OAuth flow + HTML injection. |
| apps-sfdx/sfdx-project.json | Adds SFDX project config for managed package assets and replacements. |
| apps-sfdx/scripts/soql/.gitkeep | Adds placeholder scripts folder. |
| apps-sfdx/scripts/sfdx/create-scratch-org.mjs | Adds scratch org creation/deploy helper script. |
| apps-sfdx/scripts/apex/.gitkeep | Adds placeholder apex scripts folder. |
| apps-sfdx/package.json | Adds SFDX project scripts/deps for lint/test/scratch org tasks. |
| apps-sfdx/jest.config.js | Adds Jest config for LWC tests. |
| apps-sfdx/eslint.config.js | Adds ESLint flat config for SFDX Aura/LWC + Jest mocks. |
| apps-sfdx/config/project-scratch-def.json | Adds default scratch org definition for Canvas package. |
| apps-sfdx/config/project-scratch-def-professional.json | Adds Professional scratch org definition. |
| apps-sfdx/canvas-app/untracked/main/default/extlClntAppGlobalOauthSets/Jetstream_Canvas_glbloauth.ecaGlblOauth-meta.xml | Adds global OAuth settings metadata (untracked). |
| apps-sfdx/canvas-app/untracked/main/default/.gitkeep | Keeps untracked metadata folder. |
| apps-sfdx/canvas-app/unpackaged/main/default/.gitkeep | Keeps unpackaged metadata folder. |
| apps-sfdx/canvas-app/jetstream/main/default/tabs/JetstreamAppTab.tab-meta.xml | Adds Jetstream custom tab. |
| apps-sfdx/canvas-app/jetstream/main/default/permissionsets/Jetstream.permissionset-meta.xml | Adds permission set for Canvas app + custom setting fields. |
| apps-sfdx/canvas-app/jetstream/main/default/pages/JetstreamPage.page-meta.xml | Adds VF page metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/pages/JetstreamPage.page | Adds VF page embedding the Canvas app with resizing script. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/WhereClauseOpsIndented__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/SubqueryParensOnOwnLine__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/SkipFrontdoorLogin__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/RecordSyncEnabled__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/NumIndent__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/NewLineAfterKeywords__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/fields/FieldMaxLineLength__c.field-meta.xml | Adds preferences custom setting field. |
| apps-sfdx/canvas-app/jetstream/main/default/objects/UserPreferences__c/UserPreferences__c.object-meta.xml | Adds hierarchy custom setting for user preferences. |
| apps-sfdx/canvas-app/jetstream/main/default/extlClntAppPolicies/Jetstream_Canvas_plcy.ecaPlcy-meta.xml | Adds external client app policies metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/extlClntAppOauthSettings/Jetstream_Canvas_oauth.ecaOauth-meta.xml | Adds external client app OAuth settings metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/extlClntAppOauthPolicies/Jetstream_Canvas_oauthPlcy.ecaOauthPlcy-meta.xml | Adds external client app OAuth policies metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/extlClntAppCanvasSettings/Jetstream_Canvas_canvasSettings.ecaCanvas-meta.xml | Adds external client app Canvas settings metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/externalClientApps/Jetstream_Canvas_Dev.eca-meta.xml | Adds external client app definition metadata. |
| apps-sfdx/canvas-app/jetstream/main/default/contentassets/jetstreamiconpro128.asset-meta.xml | Adds content asset metadata for branding. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/UserPreferencesTest.cls-meta.xml | Adds Apex test metadata for preferences. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/UserPreferencesTest.cls | Adds Apex tests for preference custom setting behavior. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/JetstreamPageControllerTest.cls-meta.xml | Adds Apex test metadata for page controller. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/JetstreamPageControllerTest.cls | Adds Apex tests for fullscreen parameter logic. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/JetstreamPageController.cls-meta.xml | Adds Apex class metadata for page controller. |
| apps-sfdx/canvas-app/jetstream/main/default/classes/JetstreamPageController.cls | Adds page controller providing isFullScreen canvas parameters. |
| apps-sfdx/canvas-app/jetstream/main/default/applications/Jetstream.app-meta.xml | Adds Lightning app definition for Jetstream. |
| apps-sfdx/canvas-app/jetstream/main/default/appMenus/AppSwitcher.appMenu-meta.xml | Adds app menu metadata entries. |
| apps-sfdx/README.md | Adds minimal SFDX readme. |
| apps-sfdx/.vscode/settings.json | Adds SFDX workspace VS Code settings. |
| apps-sfdx/.prettierrc | Adds Prettier config for SFDX assets (Apex/XML). |
| apps-sfdx/.prettierignore | Adds ignore rules for SFDX workspace. |
| apps-sfdx/.gitignore | Adds SFDX-specific ignores. |
| apps-sfdx/.forceignore | Adds Salesforce source tracking ignore rules. |
| .vscode/settings.json | Excludes SFDX folders from search/watcher. |
| .vscode/launch.json | Adds Apex Replay Debugger launch configuration. |
| .github/workflows/sfdx-ci.yml | Adds CI workflow to deploy to scratch org and run Apex tests. |
| .github/workflows/release.yml | Fixes Rollbar env var name for deploy creation step. |
Comments suppressed due to low confidence (2)
apps/landing/hooks/external-google-picker.hooks.ts:98
- This hook logs nonce/origin and picker result params via
console.log/console.warn. These values can include sensitive auth artifacts and are likely to leak in production (browser logs, support screenshots, etc.). Please remove these logs or guard them behind an explicit dev/debug flag.
apps/landing/hooks/external-google-picker.hooks.ts:61 isTrustedOrigincurrently allows anyhttps://origin. BecauseopenerOriginis read from query params, an attacker can open this page with their ownopenerOriginand receive Google picker results (tokens / file metadata) viapostMessage. Please restrict allowed origins to a known allowlist (e.g., your app domains +*.force.com/*.salesforce.com+ extension origins) and treatopenerOriginas untrusted input.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7d7f0c1 to
eb86661
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 125 out of 137 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
apps/landing/hooks/external-google-picker.hooks.ts:62
openerOriginis taken directly from query params, andisTrustedOrigin()currently allows anyhttps://origin. That means any arbitrary website can open this page, setopenerOriginto itself, and receive Google Picker results viapostMessage(the nonce does not prevent this because the attacker controls the nonce too). Please restrictopenerOriginto a tight allowlist (e.g., known Jetstream origins and extension origins) and/or derive the target origin from a trusted source instead of URL params.
apps/landing/hooks/external-google-picker.hooks.ts:76- This introduces a number of
console.log/console.warnstatements that will run in production for every picker completion. This can leak details to logs and adds noise for users. Consider removing these, gating behind a debug flag, or routing through the existing logger with an environment-controlled log level.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b278f6a to
21ade01
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 128 out of 141 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (2)
apps/landing/hooks/external-google-picker.hooks.ts:61
isTrustedOrigincurrently returns true for anyhttps://origin derived from a query param (openerOrigin/targetOrigin). This allows any arbitrary HTTPS site to open this picker page and receive the Google picker result (including access token) viapostMessage, which is a token exfiltration risk. Restrict allowed origins to a hardcoded allowlist (e.g., Jetstream domains and extension origins) and/or derive the target origin from a server-signed value rather than trusting a URL param.
apps/landing/hooks/external-google-picker.hooks.ts:72- The debug
console.log/console.warnstatements insendResultToOpenerlogparamsandnonce, which can include sensitive data likeaccessToken/picker selections. Please remove these logs or gate them behind a non-production/debug flag to avoid leaking tokens in browser consoles and log collection tooling.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
apps/jetstream-canvas/src/controllers/sf-bulk-api.canvas.controller.ts
Outdated
Show resolved
Hide resolved
21ade01 to
663d9d4
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 128 out of 141 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
apps/landing/hooks/external-google-picker.hooks.ts:61
isTrustedOrigin()currently treats anyhttps://origin as trusted, butopenerOriginis sourced directly from query params. This effectively allows any third-party website to use this page as an OAuth+Google Picker relay using Jetstream’s Google client configuration (quota/abuse risk) and receive results viapostMessage. Recommend restrictingopenerOriginto an explicit allow-list (Jetstream web origins + extension origins), and/or deriving the allowed target origin from a server-issued/signed nonce instead of trusting a URL param.
apps/landing/hooks/external-google-picker.hooks.ts:98- There are multiple unconditional
console.log/console.warnstatements insendResultToOpener. These will ship to production and may leak implementation details into user consoles; they also add noise when this page is used frequently. Consider removing them or gating behind a debug flag /NODE_ENV !== 'production', and prefer the app logger if you need telemetry.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add API and core application logic for a new distribution method for canvas apps
chore: move canvas types to shared lib
…vas and jetstream-web-extension update JSON response handling in route utilities to use nullish coalescing.
…fetchFn error handling
…m and jetstream-desktop-client
…n parameter comment
eb36650 to
31fe073
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 131 out of 144 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
apps/landing/hooks/external-google-picker.hooks.ts:61
isTrustedOrigincurrently treats anyhttps://origin as trusted. Because this page can return Google OAuth results/tokens towindow.openervia postMessage, allowing arbitrary HTTPS origins enables token exfiltration if this page is opened by an attacker-controlled site. Restrict the allowed origins to a small allow-list (e.g., Jetstream-owned domains and extension schemes), or validateopenerOriginagainst a server-signed value rather than accepting it from query params.
apps/landing/hooks/external-google-picker.hooks.ts:72sendResultToOpenerlogsparams(and related context) to the console. In this flowparamscan include sensitive values such asgoogleAccessToken/ expiry and file identifiers. Please remove these logs or ensure they are behind a non-production debug flag with explicit redaction of tokens/PII.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function escapeJsonForScript(json: string): string { | ||
| return json.replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/\//g, '\\u002f').replace(/'/g, '\\u0027'); | ||
| } |
There was a problem hiding this comment.
escapeJsonForScript escapes <, >, /, and ', but does not escape Unicode line/paragraph separators (U+2028/U+2029). Those characters can terminate a JavaScript string literal when embedding JSON inside <script> (even when wrapped in quotes), causing script parse errors and potentially enabling injection in edge cases. Consider escaping \u2028 and \u2029 (and optionally \u0000.. control chars) before embedding.
| // The fullscreen VF page passes { isFullScreen: true } via the apex:canvasApp parameters attribute | ||
| const isFullscreen = z.coerce.boolean().default(true).parse(sr.context?.environment?.parameters?.isFullScreen); | ||
|
|
There was a problem hiding this comment.
z.coerce.boolean().default(true) will coerce undefined to false, so the .default(true) will never apply when isFullScreen is missing. This makes isFullscreen default to false unexpectedly and hides the fullscreen-specific behavior. Prefer parsing with an explicit optional default before coercion (e.g., treat undefined as true), or use a preprocess that preserves undefined so the default can apply.
| let parsedBody: unknown = undefined; | ||
|
|
||
| if (req.request.method !== 'GET' && !skipBodyParsing) { | ||
| const contentType = req.request.headers.get('content-type') ?? ''; | ||
| if (contentType.startsWith('application/json')) { | ||
| try { | ||
| parsedBody = await req.request.json(); | ||
| } catch { | ||
| // headers may not have been correct, just ignore and continue | ||
| } | ||
| } else if (contentType.startsWith('application/zip')) { | ||
| parsedBody = await req.request.arrayBuffer(); | ||
| } else { | ||
| parsedBody = await req.request.text(); | ||
| } | ||
| } | ||
|
|
||
| try { | ||
| const data = { | ||
| params: params ? params.parse(req.params) : undefined, | ||
| body: body && parsedBody !== undefined ? body.parse(parsedBody) : undefined, | ||
| query: query ? query.parse(queryParams) : undefined, |
There was a problem hiding this comment.
createRoute only parses/validates the request body when parsedBody !== undefined. If a route declares a body schema but the request has no body (or JSON parsing fails), data.body becomes undefined instead of triggering schema validation, which can lead to downstream runtime errors and inconsistent 400 handling. Consider always running body.parse(parsedBody) when a body schema is provided (even if parsedBody is undefined), and/or throw a clear error when body parsing fails for application/json requests.
Introduce a managed package for Jetstream deployed as a Managed Package using a Canvas App.