Skip to content

Conversation

@tokio-on-jupiter
Copy link
Contributor

Summary

Replace @lifeomic/alpha with @jupiterone/platform-sdk-fetch canary release (6.0.3-canary-487-1.0).

Changes

File Changes
packages/integration-sdk-runtime/package.json Updated dependency
packages/integration-sdk-runtime/src/api/index.ts Replaced Alpha with RequestClient
packages/integration-sdk-runtime/src/synchronization/*.ts Removed axios types
packages/cli/src/import/importAssetsFromCsv.ts Updated type import
tsconfig.dist.json Added skipLibCheck for external type issues
Tests Updated mocks for RequestClient

Breaking Changes

  • ApiClient type is now RequestClient instead of Alpha
  • Deprecated options: alphaOptions and proxyUrl (not supported by RequestClient)

Test Plan

Related

@tokio-on-jupiter tokio-on-jupiter requested a review from a team as a code owner January 23, 2026 19:19
Copilot AI review requested due to automatic review settings January 23, 2026 19:19
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

This PR replaces the deprecated @lifeomic/alpha HTTP client with @jupiterone/platform-sdk-fetch canary release to modernize the API client implementation.

Changes:

  • Updated dependency from @lifeomic/alpha to @jupiterone/platform-sdk-fetch
  • Replaced Alpha type with RequestClient throughout the codebase
  • Removed proxy configuration support and deprecated alphaOptions/proxyUrl parameters

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/integration-sdk-runtime/package.json Updated dependency to platform-sdk-fetch canary
packages/integration-sdk-runtime/src/api/index.ts Replaced Alpha with RequestClient, removed proxy support
packages/integration-sdk-runtime/src/synchronization/index.ts Updated type imports and error handling
packages/integration-sdk-runtime/src/synchronization/events.ts Updated config type imports
packages/integration-sdk-runtime/src/synchronization/error.ts Replaced AxiosError with custom RequestClientError interface
packages/integration-sdk-runtime/tsconfig.dist.json Added skipLibCheck to handle external type issues
packages/cli/src/import/importAssetsFromCsv.ts Updated type imports
packages/integration-sdk-runtime/src/api/tests/index.test.ts Updated mocks for RequestClient
packages/cli/src/tests/cli-import.test.ts Updated test mocks

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

Comment on lines 118 to 120
export const compressRequest: RequestInterceptor = function (config) {
if (
config.method === 'post' &&
config.method === 'POST' &&
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The compressRequest interceptor now only sets the 'Content-Encoding' header but does not actually compress the data. The comment on lines 126-128 notes this issue but doesn't implement actual compression. This means data won't be compressed despite the header claiming it is, which could cause server-side decompression failures.

Copilot uses AI. Check for mistakes.
@@ -23,7 +35,7 @@ export function synchronizationApiError(
return new IntegrationError({
code: 'UNEXPECTED_SYNCRONIZATION_ERROR',
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

Corrected spelling of 'SYNCRONIZATION' to 'SYNCHRONIZATION'.

Suggested change
code: 'UNEXPECTED_SYNCRONIZATION_ERROR',
code: 'UNEXPECTED_SYNCHRONIZATION_ERROR',

Copilot uses AI. Check for mistakes.
'Content-Encoding': 'gzip',
};
}
config.data = await gzipData(config.data);

Choose a reason for hiding this comment

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

Does config.data need to be compressed here?

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

export const getAccountFromEnvironment = () =>
getFromEnv('JUPITERONE_ACCOUNT', IntegrationAccountRequiredError);

function parseProxyUrl(proxyUrl: string) {

Choose a reason for hiding this comment

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

Does the proxy support need to be maintained?

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

Copilot AI review requested due to automatic review settings January 23, 2026 19:40
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 10 out of 11 changed files in this pull request and generated 3 comments.


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

Comment on lines 118 to 137
export const compressRequest: RequestInterceptor = function (config) {
if (
config.method === 'post' &&
config.method === 'POST' &&
config.url &&
/\/persister\/synchronization\/jobs\/[0-9a-fA-F-]+\/(entities|relationships)/.test(
config.url,
)
) {
if (config.headers) {
config.headers['Content-Encoding'] = 'gzip';
} else {
config.headers = {
// Note: Compression is handled differently in RequestClient
// The data compression would need to be applied at the request level
// For now, we mark the headers - actual compression may need additional handling
return {
...config,
headers: {
...config.headers,
'Content-Encoding': 'gzip',
};
}
config.data = await gzipData(config.data);
},
};
}
return config;
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The compressRequest interceptor sets the 'Content-Encoding: gzip' header but does not actually compress the data. The previous implementation called gzipData(config.data) but this logic has been removed. This will cause the server to expect compressed data but receive uncompressed data, resulting in decompression failures. Either implement the actual data compression using gzipData or remove this interceptor entirely if compression is handled elsewhere.

Copilot uses AI. Check for mistakes.
code: 'UNEXPECTED_SYNCRONIZATION_ERROR',
message: errorMessage,
cause: err,
cause: err instanceof Error ? err : undefined,
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

Setting cause to undefined when the error is not an instance of Error loses error information. The original implementation passed err directly to preserve all error details. Consider using cause: err as Error or structuring the error differently to retain the original error object for debugging purposes.

Suggested change
cause: err instanceof Error ? err : undefined,
cause: err as Error,

Copilot uses AI. Check for mistakes.
});

describe('getApiKeyFromEnvironment', () => {
describe('getAccountFromEnvironment', () => {
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The describe block name 'getAccountFromEnvironment' is a duplicate of line 55's describe block name which should be 'getApiKeyFromEnvironment'. This appears to be a copy-paste error from the original code that should be corrected for clarity.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 23, 2026 19:50
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 10 out of 11 changed files in this pull request and generated 3 comments.


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

Comment on lines 115 to 138
/**
* Request interceptor that compresses upload data for synchronization endpoints
*/
export const compressRequest: RequestInterceptor = function (config) {
if (
config.method === 'post' &&
config.method === 'POST' &&
config.url &&
/\/persister\/synchronization\/jobs\/[0-9a-fA-F-]+\/(entities|relationships)/.test(
config.url,
)
) {
if (config.headers) {
config.headers['Content-Encoding'] = 'gzip';
} else {
config.headers = {
// Note: Compression is handled differently in RequestClient
// The data compression would need to be applied at the request level
// For now, we mark the headers - actual compression may need additional handling
return {
...config,
headers: {
...config.headers,
'Content-Encoding': 'gzip',
};
}
config.data = await gzipData(config.data);
},
};
}
return config;
};
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The compressRequest interceptor sets the 'Content-Encoding: gzip' header but doesn't actually compress the data. The original implementation called gzipData(config.data) to compress the request body. Without actual compression, servers expecting gzipped data will fail to process the request.

Copilot uses AI. Check for mistakes.
Comment on lines 54 to 65
accessToken,
retryOptions,
compressUploads,
alphaOptions,
proxyUrl,
}: CreateApiClientInput): ApiClient {
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The deprecated parameters alphaOptions and proxyUrl are destructured but never used in the function body. Either remove them from the destructuring or explicitly acknowledge their deprecation with a warning log.

Copilot uses AI. Check for mistakes.
code: 'UNEXPECTED_SYNCRONIZATION_ERROR',
message: errorMessage,
cause: err,
cause: err instanceof Error ? err : undefined,
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

When err is not an Error instance, setting cause to undefined loses error context. Consider converting unknown errors to Error instances or using the original value to preserve debugging information.

Suggested change
cause: err instanceof Error ? err : undefined,
cause: err,

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings January 23, 2026 20:56
@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

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 9 out of 10 changed files in this pull request and generated 1 comment.


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

},
);
rawBody: compressedData,
} as any);
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

Using as any type assertion bypasses type safety. Consider defining a proper type for the options parameter that includes the rawBody property, or add a TODO comment explaining this is temporary until the upstream types are updated.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress here.

@github-actions
Copy link

Canary release failed.

Check the workflow run for details.

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress here.

@github-actions
Copy link

Canary release failed.

Check the workflow run for details.

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress 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 9 out of 10 changed files in this pull request and generated 2 comments.


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

client.interceptors.response.use(
(response) => response,
(error: any) => {
async (error: any) => {
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The error parameter is typed as any, which reduces type safety. Consider defining a proper error type that captures the expected error structure from RequestClient.

Copilot uses AI. Check for mistakes.

export function synchronizationApiError(
err: AxiosError<SynchronizationApiErrorResponse>,
err: RequestClientError | Error | unknown,
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

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

The parameter accepts unknown in addition to specific error types, but then performs type assertions without proper type guards. Consider adding a type guard function to safely narrow the type before accessing properties.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

Canary release failed.

Check the workflow run for details.

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

- Fix headers/config types in createMockResponse helper
- Fix managedQuestionFileValidator tests to use proper response format
Copilot AI review requested due to automatic review settings January 27, 2026 21:15
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 23 out of 24 changed files in this pull request and generated no new comments.


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

…ault

- Add npm overrides to pin @sinclair/[email protected] to match main branch
  lockfile versions and avoid type incompatibilities
- Add dotenv and dotenv-expand dependencies to integration-sdk-cli package
  to ensure correct v5 API is used (root node_modules has v10 for nx)
- Update test expectations for compression default change (now enabled by default)
- Disable compression in batching/upload tests to maintain test behavior
Copilot AI review requested due to automatic review settings January 27, 2026 23:41
@tokio-on-jupiter tokio-on-jupiter force-pushed the feat/PLATENG-800-replace-lifeomic-alpha branch from a484569 to 642fe86 Compare January 27, 2026 23:41
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 26 out of 27 changed files in this pull request and generated no new comments.


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

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress here.

@github-actions
Copy link

Canary release published successfully!

Published packages:

Install with:

npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]

…ublish

- Change preid counter from github.run_attempt to github.run_id to ensure
  unique versions across different workflow runs
- Add git commit step before lerna publish from-package to ensure lerna
  detects the version changes as publishable
@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress here.

@github-actions
Copy link

Canary release published successfully!

Published packages:

Install with:

npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]

@tokio-on-jupiter
Copy link
Contributor Author

/canary-release

@github-actions
Copy link

🚀 Canary release workflow has been triggered.

You can follow the progress here.

@github-actions
Copy link

Canary release published successfully!

Published packages:

Install with:

npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/integration-sdk-entity-validator@17.2.2-canary-1188-21458536266.0
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]
npm install @jupiterone/[email protected]

const mockedGlobby = jest.mocked(globby);

// Mock RequestClient
const mockPost = jest.fn();

Choose a reason for hiding this comment

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

Would recommend moving these to integration-sdk-testing since they're used and redeclared across multiple test files

const mockedAxios = jest.mocked<AxiosInstance>(axios);
const mockedFileSystem = jest.mocked(fileSystem);

const mockGet = jest.fn();

Choose a reason for hiding this comment

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

Would recommend moving these mocks to integration-sdk-testing since they're used and redeclared across multiple test files

beforeEach(() => {
mockedRuntime.createApiClient.mockReturnValue(axios);
mockGet.mockReset();
mockedRuntime.createApiClient.mockReturnValue(mockApiClient as any);

Choose a reason for hiding this comment

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

This is a violation of our no any policy - I would refactor this to support using a strongly typed interface. I would recommend using the node-typescript quality plugin moving forward that will continually enforce and handle auto fixing issues like this (immediately after code generation) in the future: https://github.com/JupiterOne/claude-toolbox/pull/39

response: { use: jest.fn(), eject: jest.fn() },
};

jest.mock('@jupiterone/platform-sdk-fetch', () => ({

Choose a reason for hiding this comment

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

Let's also move this to integration-sdk-testing

"compilerOptions": {
"sourceMap": true
"sourceMap": true,
"skipLibCheck": true

Choose a reason for hiding this comment

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

Revert

level: 'trace',
type: 'raw',
stream: ringbuffer,
stream: ringbuffer as any,

Choose a reason for hiding this comment

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

as any violation - revert/fix

"strictFunctionTypes": true,
"allowJs": false
"allowJs": false,
"skipLibCheck": true

Choose a reason for hiding this comment

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

Suggested change
"skipLibCheck": true
"skipLibCheck": false

[type]: batch,
},
{
const url = `/persister/synchronization/jobs/${jobId}/${type as string}`;

Choose a reason for hiding this comment

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

All of this should be a handled internal implementation detail of platform-sdk-fetch requestClient. For any consumer service today that uses: @lifeomic/alpha, we want to ensure that they get a drop in compatible replacement. If this code is required in the consuming service additional work needs to be done in platform-sdk-fetch to ensure we can minimize required code changes across all affected services so we can quickly migrate off @lifeomic/alpha by utilizing a deterministic codemod/code transform.

}

function cleanAxiosError(err: AxiosError) {
function cleanRequestError(err: any) {

Choose a reason for hiding this comment

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

This should likely be replaced with a similar signature such as:

err: HttpRequestError that would be exported by platform-sdk-fetch as a type.

The type could have the same properties, etc. as AxiosError for drop in consumer compatibility.

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