@hubspot/ui-extensions-dev-server 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/DevModeParentInterface.js +5 -6
- package/dist/lib/DevModeUnifiedInterface.js +2 -2
- package/dist/lib/DevServerState.d.ts +14 -4
- package/dist/lib/DevServerState.js +34 -1
- package/dist/lib/__tests__/DevModeParentInterface.spec.js +42 -1
- package/dist/lib/__tests__/DevModeUnifiedInterface.spec.js +34 -0
- package/dist/lib/__tests__/DevServerState.spec.js +180 -0
- package/dist/lib/__tests__/{app-functions/errorReporter.spec.js → errorReporter.spec.js} +5 -5
- package/dist/lib/__tests__/extensionsService.spec.js +57 -9
- package/dist/lib/__tests__/factories.d.ts +1 -1
- package/dist/lib/__tests__/factories.js +1 -1
- package/dist/lib/__tests__/fixtures/extensionConfig.js +3 -0
- package/dist/lib/__tests__/plugins/devBuildPlugin.spec.js +1 -1
- package/dist/lib/__tests__/{app-functions/services → proxy}/AppProxyService.spec.js +73 -3
- package/dist/lib/__tests__/{app-functions → proxy}/signing.spec.js +1 -1
- package/dist/lib/__tests__/server.spec.js +14 -11
- package/dist/lib/__tests__/serverless/config.spec.js +61 -0
- package/dist/lib/__tests__/{app-functions → serverless}/context.spec.js +2 -2
- package/dist/lib/__tests__/serverless/executor_unsupported.spec.js +37 -0
- package/dist/lib/__tests__/{app-functions/executor_v20232.spec.js → serverless/executor_v20251.spec.js} +6 -13
- package/dist/lib/__tests__/{app-functions/executor_v20231.spec.js → serverless/executor_v202603.spec.js} +26 -11
- package/dist/lib/__tests__/{app-functions → serverless}/fixtures/constants.d.ts +4 -3
- package/dist/lib/__tests__/{app-functions → serverless}/fixtures/constants.js +9 -3
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-async-fails.cjs +5 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-async-fails.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-async-succeeds.cjs +5 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-async-succeeds.d.cts +3 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-does-not-export-main.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-does-not-export-main.d.cts +1 -0
- package/dist/lib/__tests__/{app-functions/fixtures/v2023.1/app.functions → serverless/fixtures/v2026.03/functions}/func-echos-input.cjs +3 -3
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-echos-input.d.cts +5 -0
- package/dist/lib/__tests__/{app-functions/fixtures/v2023.1/app.functions → serverless/fixtures/v2026.03/functions}/func-logs.cjs +2 -2
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-logs.d.cts +3 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-function.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-function.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-implicitly.cjs +7 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-implicitly.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-promise-rejected.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-promise-rejected.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-promise-resolved.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-promise-resolved.d.cts +3 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-text.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-text.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-undefined.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-undefined.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-times-out.cjs +12 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-times-out.d.cts +1 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-undeclared.cjs +4 -0
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-undeclared.d.cts +1 -0
- package/dist/lib/__tests__/{app-functions/fixtures/v2023.1/app.functions → serverless/fixtures/v2026.03/functions}/func-uses-secret.cjs +3 -3
- package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-uses-secret.d.cts +4 -0
- package/dist/lib/__tests__/{app-functions → serverless}/secrets.spec.js +4 -4
- package/dist/lib/__tests__/{app-functions → serverless}/services/PrivateAppUserTokenManager.spec.js +4 -4
- package/dist/lib/__tests__/serverless/services/services_v20251.spec.d.ts +1 -0
- package/dist/lib/__tests__/{app-functions/services/services_v20232.spec.js → serverless/services/services_v20251.spec.js} +9 -63
- package/dist/lib/__tests__/serverless/services/services_v202603.spec.d.ts +1 -0
- package/dist/lib/__tests__/{app-functions/services/services_v20231.spec.js → serverless/services/services_v202603.spec.js} +18 -91
- package/dist/lib/__tests__/serverless/setup.d.ts +1 -0
- package/dist/lib/__tests__/utils.spec.js +26 -1
- package/dist/lib/constants.d.ts +2 -2
- package/dist/lib/constants.js +2 -2
- package/dist/lib/{app-functions/errorReporter.js → errorReporter.js} +2 -2
- package/dist/lib/extensionsService.js +6 -0
- package/dist/lib/{app-functions/services → proxy}/AppProxyService.d.ts +1 -1
- package/dist/lib/{app-functions/services → proxy}/AppProxyService.js +15 -4
- package/dist/lib/proxy/constants.d.ts +13 -0
- package/dist/lib/{app-functions → proxy}/constants.js +0 -18
- package/dist/lib/proxy/types.d.ts +44 -0
- package/dist/lib/proxy/types.js +1 -0
- package/dist/lib/server.js +2 -1
- package/dist/lib/serverless/config.js +100 -0
- package/dist/lib/serverless/constants.d.ts +7 -0
- package/dist/lib/serverless/constants.js +12 -0
- package/dist/lib/{app-functions → serverless}/errors.d.ts +1 -0
- package/dist/lib/{app-functions → serverless}/errors.js +6 -0
- package/dist/lib/{app-functions → serverless}/executor.js +19 -13
- package/dist/lib/serverless/secrets.d.ts +5 -0
- package/dist/lib/{app-functions → serverless}/services/AppFunctionExecutionService.js +1 -1
- package/dist/lib/{app-functions → serverless}/services/PrivateAppUserTokenManager.js +1 -1
- package/dist/lib/{app-functions → serverless}/types.d.ts +1 -44
- package/dist/lib/types.d.ts +12 -3
- package/dist/lib/types.js +7 -2
- package/dist/lib/utils.d.ts +2 -1
- package/dist/lib/utils.js +3 -0
- package/package.json +1 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-async-fails.cjs +0 -8
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-async-fails.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-async-succeeds.cjs +0 -8
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-async-succeeds.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-callback-on-promise-rejected.cjs +0 -8
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-callback-on-promise-resolved.cjs +0 -8
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-callback-on-promise-resolved.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-does-not-export-main.cjs +0 -4
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-does-not-export-main.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-echos-input.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-logs.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-function.cjs +0 -4
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-function.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-promise-rejected.cjs +0 -7
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-promise-rejected.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-promise-resolved.cjs +0 -7
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-promise-resolved.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-text.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-undefined.cjs +0 -4
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-returns-undefined.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-times-out.cjs +0 -10
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-times-out.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-undeclared.cjs +0 -4
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-undeclared.d.cts +0 -1
- package/dist/lib/__tests__/app-functions/fixtures/v2023.1/app.functions/func-uses-secret.d.cts +0 -1
- package/dist/lib/app-functions/config.js +0 -48
- package/dist/lib/app-functions/constants.d.ts +0 -26
- package/dist/lib/app-functions/index.d.ts +0 -4
- package/dist/lib/app-functions/index.js +0 -4
- package/dist/lib/app-functions/secrets.d.ts +0 -5
- package/dist/lib/app-functions/services/index.d.ts +0 -3
- package/dist/lib/app-functions/services/index.js +0 -3
- /package/dist/lib/__tests__/{app-functions/context.spec.d.ts → DevServerState.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/errorReporter.spec.d.ts → errorReporter.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/services → proxy}/AppProxyService.spec.d.ts +0 -0
- /package/dist/lib/__tests__/{app-functions → proxy}/signing.spec.d.ts +0 -0
- /package/dist/lib/__tests__/{app-functions/executor_v20231.spec.d.ts → serverless/config.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/executor_v20232.spec.d.ts → serverless/context.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/secrets.spec.d.ts → serverless/executor_unsupported.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/services/PrivateAppUserTokenManager.spec.d.ts → serverless/executor_v20251.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/services/services_v20231.spec.d.ts → serverless/executor_v202603.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-async-fails.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-async-fails.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-async-succeeds.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-async-succeeds.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-calls-callback.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-calls-callback.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-does-not-export-main.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-does-not-export-main.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-echos-input.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-echos-input.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-logs.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-logs.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-function.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-function.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-implicitly.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-implicitly.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-promise-rejected.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-promise-rejected.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-promise-resolved.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-promise-resolved.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-text.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-text.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-undefined.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-returns-undefined.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.1 → serverless/fixtures/v2025.1}/app.functions/func-throws-error.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.1 → serverless/fixtures/v2025.1}/app.functions/func-throws-error.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-times-out.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-times-out.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-undeclared.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-undeclared.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-uses-secret.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2 → serverless/fixtures/v2025.1}/app.functions/func-uses-secret.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.1/app.functions/func-returns-text.cjs → serverless/fixtures/v2026.03/functions/func-calls-callback.cjs} +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.1/app.functions/func-callback-on-promise-rejected.d.cts → serverless/fixtures/v2026.03/functions/func-calls-callback.d.cts} +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2/app.functions → serverless/fixtures/v2026.03/functions}/func-throws-error.cjs +0 -0
- /package/dist/lib/__tests__/{app-functions/fixtures/v2023.2/app.functions → serverless/fixtures/v2026.03/functions}/func-throws-error.d.cts +0 -0
- /package/dist/lib/__tests__/{app-functions/services/services_v20232.spec.d.ts → serverless/secrets.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions/setup.d.ts → serverless/services/PrivateAppUserTokenManager.spec.d.ts} +0 -0
- /package/dist/lib/__tests__/{app-functions → serverless}/setup.js +0 -0
- /package/dist/lib/{app-functions/errorReporter.d.ts → errorReporter.d.ts} +0 -0
- /package/dist/lib/{app-functions → proxy}/signing.d.ts +0 -0
- /package/dist/lib/{app-functions → proxy}/signing.js +0 -0
- /package/dist/lib/{app-functions → serverless}/api/privateAppUserToken.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/api/privateAppUserToken.js +0 -0
- /package/dist/lib/{app-functions → serverless}/config.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/context.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/context.js +0 -0
- /package/dist/lib/{app-functions → serverless}/executor.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/secrets.js +0 -0
- /package/dist/lib/{app-functions → serverless}/services/AppFunctionExecutionService.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/services/PrivateAppUserTokenManager.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/services/constants.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/services/constants.js +0 -0
- /package/dist/lib/{app-functions → serverless}/services/messages.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/services/messages.js +0 -0
- /package/dist/lib/{app-functions → serverless}/types.js +0 -0
- /package/dist/lib/{app-functions → serverless}/utils.d.ts +0 -0
- /package/dist/lib/{app-functions → serverless}/utils.js +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
vi.mock('../../errorReporter.ts', () => ({
|
|
3
|
+
reportError: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
import { extractErrorData, mapToLocalUrl, AppProxyService, } from "../../proxy/AppProxyService.js";
|
|
6
|
+
import { axiosErrorMappings, defaultServerError, validationError, } from "../../proxy/constants.js";
|
|
4
7
|
import axios, { AxiosError, HttpStatusCode } from 'axios';
|
|
5
8
|
import httpMocks from 'node-mocks-http';
|
|
6
9
|
import { EventEmitter } from 'node:events';
|
|
7
|
-
import * as signing from "
|
|
10
|
+
import * as signing from "../../proxy/signing.js";
|
|
8
11
|
const callAppProxy = async ({ requestUri, method, requestTimeoutMillis, requestBody, requestHeaders, accountId, localDevUrlMapping = {}, logger, }) => {
|
|
9
12
|
const request = httpMocks.createRequest({
|
|
10
13
|
method: 'POST',
|
|
@@ -79,6 +82,20 @@ describe('AppProxyService', () => {
|
|
|
79
82
|
[validUrl]: newValidUrl,
|
|
80
83
|
}, validUrlWithBasePath, [], logger)).toBe(`${newValidUrl}${basePath}`);
|
|
81
84
|
});
|
|
85
|
+
it('should preserve the local mapping sub-path when merging URLs', () => {
|
|
86
|
+
const newValidUrl = 'https://localhost:3000/api/v1';
|
|
87
|
+
const requestPath = '/some/endpoint';
|
|
88
|
+
expect(mapToLocalUrl({
|
|
89
|
+
[validUrl]: newValidUrl,
|
|
90
|
+
}, `${validUrl}${requestPath}`, [], logger)).toBe(`${newValidUrl}${requestPath}`);
|
|
91
|
+
});
|
|
92
|
+
it('should preserve the local mapping sub-path with trailing slash when merging URLs', () => {
|
|
93
|
+
const newValidUrl = 'https://localhost:3000/api/v1/';
|
|
94
|
+
const requestPath = '/some/endpoint';
|
|
95
|
+
expect(mapToLocalUrl({
|
|
96
|
+
[validUrl]: newValidUrl,
|
|
97
|
+
}, `${validUrl}${requestPath}`, [], logger)).toBe(`https://localhost:3000/api/v1${requestPath}`);
|
|
98
|
+
});
|
|
82
99
|
it('should honor urls with ports', () => {
|
|
83
100
|
const newValidUrl = 'https://localhost:5173';
|
|
84
101
|
expect(mapToLocalUrl({
|
|
@@ -343,6 +360,8 @@ describe('AppProxyService', () => {
|
|
|
343
360
|
requestUri: [requestUri],
|
|
344
361
|
}),
|
|
345
362
|
}));
|
|
363
|
+
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining(`returned HTTP ${statusCode}`));
|
|
364
|
+
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Request failed'));
|
|
346
365
|
});
|
|
347
366
|
it('returns success responses with error info in the body if the proxy returns 4xx, mimicking the backend proxy behavior', async () => {
|
|
348
367
|
const responseBody = { message: 'this is 404z' };
|
|
@@ -380,6 +399,7 @@ describe('AppProxyService', () => {
|
|
|
380
399
|
requestUri: [requestUri],
|
|
381
400
|
}),
|
|
382
401
|
}));
|
|
402
|
+
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining(`returned HTTP ${statusCode}`));
|
|
383
403
|
});
|
|
384
404
|
it('returns success responses with error info in the body if the proxy returns 5xx, mimicking the backend proxy behavior', async () => {
|
|
385
405
|
const responseBody = { message: 'there is 500' };
|
|
@@ -417,6 +437,56 @@ describe('AppProxyService', () => {
|
|
|
417
437
|
requestUri: [requestUri],
|
|
418
438
|
}),
|
|
419
439
|
}));
|
|
440
|
+
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining(`returned HTTP ${statusCode}`));
|
|
441
|
+
});
|
|
442
|
+
it('should log an error when the proxy cannot reach the backend (e.g. ECONNREFUSED)', async () => {
|
|
443
|
+
const method = 'GET';
|
|
444
|
+
const requestUri = 'http://localhost:9999';
|
|
445
|
+
const accountId = 123456;
|
|
446
|
+
const requestTimeoutMillis = 1000;
|
|
447
|
+
// @ts-expect-error Typescript doesn't know this is a spy
|
|
448
|
+
axios.request.mockImplementationOnce(() => Promise.reject(new AxiosError('connect ECONNREFUSED 127.0.0.1:9999', AxiosError.ERR_NETWORK)));
|
|
449
|
+
await callAppProxy({
|
|
450
|
+
requestUri,
|
|
451
|
+
method,
|
|
452
|
+
requestTimeoutMillis,
|
|
453
|
+
accountId,
|
|
454
|
+
logger,
|
|
455
|
+
});
|
|
456
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('connect ECONNREFUSED'));
|
|
457
|
+
expect(logger.info).toHaveBeenCalledWith(expect.stringContaining('Request failed'));
|
|
458
|
+
});
|
|
459
|
+
it('should log an error when TLS verification fails', async () => {
|
|
460
|
+
const method = 'GET';
|
|
461
|
+
const requestUri = 'https://localhost:1235';
|
|
462
|
+
const accountId = 123456;
|
|
463
|
+
const requestTimeoutMillis = 1000;
|
|
464
|
+
// @ts-expect-error Typescript doesn't know this is a spy
|
|
465
|
+
axios.request.mockImplementationOnce(() => Promise.reject(new AxiosError('unable to verify the first certificate', AxiosError.ERR_NETWORK)));
|
|
466
|
+
await callAppProxy({
|
|
467
|
+
requestUri,
|
|
468
|
+
method,
|
|
469
|
+
requestTimeoutMillis,
|
|
470
|
+
accountId,
|
|
471
|
+
logger,
|
|
472
|
+
});
|
|
473
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('unable to verify the first certificate'));
|
|
474
|
+
});
|
|
475
|
+
it('should log an error for non-Axios errors', async () => {
|
|
476
|
+
const method = 'GET';
|
|
477
|
+
const requestUri = 'http://localhost:1234';
|
|
478
|
+
const accountId = 123456;
|
|
479
|
+
const requestTimeoutMillis = 1000;
|
|
480
|
+
// @ts-expect-error Typescript doesn't know this is a spy
|
|
481
|
+
axios.request.mockImplementationOnce(() => Promise.reject(new TypeError('Cannot read properties of undefined')));
|
|
482
|
+
await callAppProxy({
|
|
483
|
+
requestUri,
|
|
484
|
+
method,
|
|
485
|
+
requestTimeoutMillis,
|
|
486
|
+
accountId,
|
|
487
|
+
logger,
|
|
488
|
+
});
|
|
489
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('Cannot read properties of undefined'));
|
|
420
490
|
});
|
|
421
491
|
describe('with local.json mapping', () => {
|
|
422
492
|
const mappedUrl = 'http://localhost:1234';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
2
|
import { Signature } from '@hubspot/api-client';
|
|
3
|
-
import { getSignatureHeaders, sign, formatForSigning, } from "../../
|
|
3
|
+
import { getSignatureHeaders, sign, formatForSigning, } from "../../proxy/signing.js";
|
|
4
4
|
/**
|
|
5
5
|
* Validate signing of requests for headers
|
|
6
6
|
*/
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { afterEach, describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import * as
|
|
2
|
+
import * as serverlessServices from "../serverless/services/AppFunctionExecutionService.js";
|
|
3
|
+
import * as proxyService from "../proxy/AppProxyService.js";
|
|
3
4
|
import startDevServer from "../server.js";
|
|
4
5
|
import { DevServerState } from "../DevServerState.js";
|
|
5
6
|
import { createMockLogger, createDevServerConfig, createMockViteDevServer, } from "./factories.js";
|
|
6
7
|
const useMock = vi.fn();
|
|
7
|
-
vi.mock('../
|
|
8
|
-
AppProxyService: vi.fn(() => vi.fn((req, res, next) => next())),
|
|
8
|
+
vi.mock('../serverless/services/AppFunctionExecutionService.ts', () => ({
|
|
9
9
|
AppFunctionExecutionService: vi.fn(() => vi.fn((req, res, next) => next())),
|
|
10
10
|
}));
|
|
11
|
+
vi.mock('../proxy/AppProxyService.ts', () => ({
|
|
12
|
+
AppProxyService: vi.fn(() => vi.fn((req, res, next) => next())),
|
|
13
|
+
}));
|
|
11
14
|
vi.mock('express', () => {
|
|
12
15
|
const expressMock = () => ({
|
|
13
16
|
use: useMock,
|
|
@@ -43,8 +46,8 @@ describe('server', () => {
|
|
|
43
46
|
describe('startDevServer', () => {
|
|
44
47
|
beforeEach(() => {
|
|
45
48
|
useMock.mockClear();
|
|
46
|
-
vi.mocked(
|
|
47
|
-
vi.mocked(
|
|
49
|
+
vi.mocked(serverlessServices.AppFunctionExecutionService).mockReturnValue(vi.fn());
|
|
50
|
+
vi.mocked(proxyService.AppProxyService).mockReturnValue(vi.fn());
|
|
48
51
|
vi.clearAllMocks();
|
|
49
52
|
});
|
|
50
53
|
it('should add the AppProxyService middleware when localDevUrlMapping is provided', async () => {
|
|
@@ -61,8 +64,8 @@ describe('server', () => {
|
|
|
61
64
|
expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function),
|
|
62
65
|
// This is the AppProxyService middleware
|
|
63
66
|
expect.any(Function));
|
|
64
|
-
expect(
|
|
65
|
-
expect(
|
|
67
|
+
expect(proxyService.AppProxyService).toHaveBeenCalledTimes(1);
|
|
68
|
+
expect(proxyService.AppProxyService).toHaveBeenCalledWith({
|
|
66
69
|
accountId: devServerConfig.accountId,
|
|
67
70
|
allowedUrls: [],
|
|
68
71
|
localDevUrlMapping: devServerState.localDevUrlMapping,
|
|
@@ -79,7 +82,7 @@ describe('server', () => {
|
|
|
79
82
|
viteDevServer: createMockViteDevServer(),
|
|
80
83
|
});
|
|
81
84
|
expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function));
|
|
82
|
-
expect(
|
|
85
|
+
expect(proxyService.AppProxyService).toHaveBeenCalledTimes(0);
|
|
83
86
|
});
|
|
84
87
|
it('should not add the AppProxyService middleware when localDevUrlMapping is not provided', async () => {
|
|
85
88
|
const devServerState = new DevServerState({
|
|
@@ -91,7 +94,7 @@ describe('server', () => {
|
|
|
91
94
|
viteDevServer: createMockViteDevServer(),
|
|
92
95
|
});
|
|
93
96
|
expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function));
|
|
94
|
-
expect(
|
|
97
|
+
expect(proxyService.AppProxyService).toHaveBeenCalledTimes(0);
|
|
95
98
|
});
|
|
96
99
|
it('should add the AppFunctionExecutionService middleware if is a private app', async () => {
|
|
97
100
|
const devServerState = new DevServerState({
|
|
@@ -104,7 +107,7 @@ describe('server', () => {
|
|
|
104
107
|
devServerState,
|
|
105
108
|
viteDevServer: createMockViteDevServer(),
|
|
106
109
|
});
|
|
107
|
-
expect(
|
|
110
|
+
expect(serverlessServices.AppFunctionExecutionService).toHaveBeenCalledTimes(1);
|
|
108
111
|
});
|
|
109
112
|
it('should not add the AppFunctionExecutionService middleware if is a public app', async () => {
|
|
110
113
|
const devServerState = new DevServerState({
|
|
@@ -118,7 +121,7 @@ describe('server', () => {
|
|
|
118
121
|
devServerState,
|
|
119
122
|
viteDevServer: createMockViteDevServer(),
|
|
120
123
|
});
|
|
121
|
-
expect(
|
|
124
|
+
expect(serverlessServices.AppFunctionExecutionService).not.toHaveBeenCalled();
|
|
122
125
|
});
|
|
123
126
|
it('should return httpServer and shutdown function', async () => {
|
|
124
127
|
const devServerState = new DevServerState(devServerConfig);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { loadMultiFunctionInfo } from "../../serverless/config.js";
|
|
4
|
+
import { TEST_CONFIG_V202603 as TEST_CONFIG } from "./fixtures/constants.js";
|
|
5
|
+
describe('loadMultiFunctionInfo (v2026.03)', () => {
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
vi.restoreAllMocks();
|
|
8
|
+
});
|
|
9
|
+
it('loads app functions from hsmeta files', () => {
|
|
10
|
+
const result = loadMultiFunctionInfo(TEST_CONFIG);
|
|
11
|
+
expect(result.appFunctions).toHaveProperty('returns-text');
|
|
12
|
+
expect(result.appFunctions['returns-text']).toEqual({
|
|
13
|
+
file: 'func-returns-text.cjs',
|
|
14
|
+
secrets: [],
|
|
15
|
+
});
|
|
16
|
+
expect(Object.keys(result.appFunctions).length).toBeGreaterThan(0);
|
|
17
|
+
});
|
|
18
|
+
it('skips hsmeta files that cannot be read', () => {
|
|
19
|
+
const originalReadFileSync = fs.readFileSync;
|
|
20
|
+
vi.spyOn(fs, 'readFileSync').mockImplementation((...args) => {
|
|
21
|
+
const filePath = args[0];
|
|
22
|
+
if (typeof filePath === 'string' &&
|
|
23
|
+
filePath.endsWith('returns-text-hsmeta.json')) {
|
|
24
|
+
throw new Error('ENOENT: no such file or directory');
|
|
25
|
+
}
|
|
26
|
+
return originalReadFileSync.apply(fs, args);
|
|
27
|
+
});
|
|
28
|
+
const result = loadMultiFunctionInfo(TEST_CONFIG);
|
|
29
|
+
expect(result.appFunctions).not.toHaveProperty('returns-text');
|
|
30
|
+
expect(TEST_CONFIG.logger.warn).toHaveBeenCalledWith(expect.stringContaining('Failed to read or parse'));
|
|
31
|
+
expect(TEST_CONFIG.logger.warn).toHaveBeenCalledWith(expect.stringContaining('returns-text-hsmeta.json'));
|
|
32
|
+
});
|
|
33
|
+
it('skips hsmeta files with invalid JSON', () => {
|
|
34
|
+
const originalReadFileSync = fs.readFileSync;
|
|
35
|
+
vi.spyOn(fs, 'readFileSync').mockImplementation((...args) => {
|
|
36
|
+
const filePath = args[0];
|
|
37
|
+
if (typeof filePath === 'string' &&
|
|
38
|
+
filePath.endsWith('returns-text-hsmeta.json')) {
|
|
39
|
+
return 'not-valid-json';
|
|
40
|
+
}
|
|
41
|
+
return originalReadFileSync.apply(fs, args);
|
|
42
|
+
});
|
|
43
|
+
const result = loadMultiFunctionInfo(TEST_CONFIG);
|
|
44
|
+
expect(result.appFunctions).not.toHaveProperty('returns-text');
|
|
45
|
+
expect(TEST_CONFIG.logger.warn).toHaveBeenCalledWith(expect.stringContaining('Failed to read or parse'));
|
|
46
|
+
});
|
|
47
|
+
it('still loads other functions when one hsmeta file fails', () => {
|
|
48
|
+
const originalReadFileSync = fs.readFileSync;
|
|
49
|
+
vi.spyOn(fs, 'readFileSync').mockImplementation((...args) => {
|
|
50
|
+
const filePath = args[0];
|
|
51
|
+
if (typeof filePath === 'string' &&
|
|
52
|
+
filePath.endsWith('returns-text-hsmeta.json')) {
|
|
53
|
+
throw new Error('ENOENT: no such file or directory');
|
|
54
|
+
}
|
|
55
|
+
return originalReadFileSync.apply(fs, args);
|
|
56
|
+
});
|
|
57
|
+
const result = loadMultiFunctionInfo(TEST_CONFIG);
|
|
58
|
+
expect(result.appFunctions).not.toHaveProperty('returns-text');
|
|
59
|
+
expect(Object.keys(result.appFunctions).length).toBeGreaterThan(0);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
2
2
|
import { Client } from '@hubspot/api-client';
|
|
3
|
-
import { fetchObjectContext } from "../../
|
|
4
|
-
import { SAMPLE_BAD_REQUEST_API_ERROR, SAMPLE_NOT_FOUND_API_ERROR, SAMPLE_UNAUTHORIZED_API_ERROR,
|
|
3
|
+
import { fetchObjectContext } from "../../serverless/context.js";
|
|
4
|
+
import { SAMPLE_BAD_REQUEST_API_ERROR, SAMPLE_NOT_FOUND_API_ERROR, SAMPLE_UNAUTHORIZED_API_ERROR, TEST_CONFIG_V20251 as TEST_CONFIG, } from "./fixtures/constants.js";
|
|
5
5
|
/**
|
|
6
6
|
* Validate construction of the context (first argument in an app function)
|
|
7
7
|
*/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
|
+
import { Client } from '@hubspot/api-client';
|
|
3
|
+
import { executeFunction } from "../../serverless/executor.js";
|
|
4
|
+
import { Reason, ExecutionError } from "../../serverless/errors.js";
|
|
5
|
+
import { PLATFORM_VERSION } from "../../constants.js";
|
|
6
|
+
import { buildUnsupportedVersionConfig } from "./fixtures/constants.js";
|
|
7
|
+
describe('app function executor - unsupported platform versions', () => {
|
|
8
|
+
const initialEnvJson = JSON.stringify(process.env);
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
vi.spyOn(Client.prototype, 'crm', 'get').mockReturnValue({
|
|
11
|
+
objects: {
|
|
12
|
+
basicApi: {
|
|
13
|
+
getById: () =>
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
Promise.resolve({
|
|
16
|
+
properties: { firstname: 'First', lastname: 'Last' },
|
|
17
|
+
}),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
vi.resetAllMocks();
|
|
24
|
+
process.env = JSON.parse(initialEnvJson);
|
|
25
|
+
});
|
|
26
|
+
it.each([['V20252', PLATFORM_VERSION.V20252]])('should reject with UnsupportedVersion for %s', async (_label, platformVersion) => {
|
|
27
|
+
const config = buildUnsupportedVersionConfig(platformVersion);
|
|
28
|
+
try {
|
|
29
|
+
await executeFunction(config, 'returns-text', {}, () => { });
|
|
30
|
+
expect.unreachable('should have thrown');
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
expect(err).toBeInstanceOf(ExecutionError);
|
|
34
|
+
expect(err.reason).toBe(Reason.UnsupportedVersion);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
2
|
import { Client } from '@hubspot/api-client';
|
|
3
|
-
import { Reason, ExecutionError } from "../../
|
|
4
|
-
import { executeFunction } from "../../
|
|
5
|
-
import * as SecretsModule from "../../
|
|
6
|
-
import { NOOP_CALLBACK,
|
|
7
|
-
|
|
8
|
-
* Validate function execution using sample functions defined in
|
|
9
|
-
* the app path of TEST_CONFIG, which is fixtures/app.functions/
|
|
10
|
-
*/
|
|
11
|
-
describe(`app function executor`, () => {
|
|
3
|
+
import { Reason, ExecutionError } from "../../serverless/errors.js";
|
|
4
|
+
import { executeFunction } from "../../serverless/executor.js";
|
|
5
|
+
import * as SecretsModule from "../../serverless/secrets.js";
|
|
6
|
+
import { NOOP_CALLBACK, TEST_CONFIG_V20251 as TEST_CONFIG, } from "./fixtures/constants.js";
|
|
7
|
+
describe(`app function executor (v2025.1)`, () => {
|
|
12
8
|
let actual;
|
|
13
9
|
const initialEnvJson = JSON.stringify(process.env);
|
|
14
10
|
const setActual = (value) => {
|
|
@@ -16,12 +12,10 @@ describe(`app function executor`, () => {
|
|
|
16
12
|
};
|
|
17
13
|
beforeEach(() => {
|
|
18
14
|
setActual(undefined);
|
|
19
|
-
// mock `apiClient.crm.objects.basicApi.getById` to return propertiesToSend for the CRM object
|
|
20
15
|
vi.spyOn(Client.prototype, 'crm', 'get').mockReturnValue({
|
|
21
16
|
objects: {
|
|
22
17
|
basicApi: {
|
|
23
18
|
getById: () =>
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
25
19
|
// @ts-ignore
|
|
26
20
|
Promise.resolve({
|
|
27
21
|
properties: { firstname: 'First', lastname: 'Last' },
|
|
@@ -32,7 +26,6 @@ describe(`app function executor`, () => {
|
|
|
32
26
|
});
|
|
33
27
|
afterEach(() => {
|
|
34
28
|
vi.resetAllMocks();
|
|
35
|
-
// restore process.env
|
|
36
29
|
process.env = JSON.parse(initialEnvJson);
|
|
37
30
|
});
|
|
38
31
|
it('executes a function', async () => {
|
|
@@ -176,7 +169,7 @@ describe(`app function executor`, () => {
|
|
|
176
169
|
expect(err.cause).toHaveProperty('message', 'Oops');
|
|
177
170
|
}
|
|
178
171
|
});
|
|
179
|
-
it('throws an error if the function calls callback
|
|
172
|
+
it('throws an error if the function calls callback', async () => {
|
|
180
173
|
try {
|
|
181
174
|
await executeFunction(TEST_CONFIG, 'calls-callback', {}, NOOP_CALLBACK);
|
|
182
175
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
|
|
2
2
|
import { Client } from '@hubspot/api-client';
|
|
3
|
-
import { Reason, ExecutionError } from "../../
|
|
4
|
-
import { executeFunction } from "../../
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* the app path of TEST_CONFIG, which is fixtures/app.functions/
|
|
9
|
-
*/
|
|
10
|
-
describe('app function executor', () => {
|
|
3
|
+
import { Reason, ExecutionError } from "../../serverless/errors.js";
|
|
4
|
+
import { executeFunction } from "../../serverless/executor.js";
|
|
5
|
+
import * as SecretsModule from "../../serverless/secrets.js";
|
|
6
|
+
import { NOOP_CALLBACK, TEST_CONFIG_V202603 as TEST_CONFIG, } from "./fixtures/constants.js";
|
|
7
|
+
describe(`app function executor (v2026.03)`, () => {
|
|
11
8
|
let actual;
|
|
12
9
|
const initialEnvJson = JSON.stringify(process.env);
|
|
13
10
|
const setActual = (value) => {
|
|
@@ -15,12 +12,10 @@ describe('app function executor', () => {
|
|
|
15
12
|
};
|
|
16
13
|
beforeEach(() => {
|
|
17
14
|
setActual(undefined);
|
|
18
|
-
// mock `apiClient.crm.objects.basicApi.getById` to return propertiesToSend for the CRM object
|
|
19
15
|
vi.spyOn(Client.prototype, 'crm', 'get').mockReturnValue({
|
|
20
16
|
objects: {
|
|
21
17
|
basicApi: {
|
|
22
18
|
getById: () =>
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
24
19
|
// @ts-ignore
|
|
25
20
|
Promise.resolve({
|
|
26
21
|
properties: { firstname: 'First', lastname: 'Last' },
|
|
@@ -31,7 +26,6 @@ describe('app function executor', () => {
|
|
|
31
26
|
});
|
|
32
27
|
afterEach(() => {
|
|
33
28
|
vi.resetAllMocks();
|
|
34
|
-
// restore process.env
|
|
35
29
|
process.env = JSON.parse(initialEnvJson);
|
|
36
30
|
});
|
|
37
31
|
it('executes a function', async () => {
|
|
@@ -90,19 +84,29 @@ describe('app function executor', () => {
|
|
|
90
84
|
});
|
|
91
85
|
describe('handles secrets', () => {
|
|
92
86
|
it('supplies secrets including the private app access token', async () => {
|
|
87
|
+
const setProperTokenInSecretsSpy = vi.spyOn(SecretsModule, 'setProperTokenInSecrets');
|
|
88
|
+
const loadSecretsSpy = vi.spyOn(SecretsModule, 'loadSecrets');
|
|
93
89
|
await executeFunction(TEST_CONFIG, 'uses-secret', {}, setActual);
|
|
94
90
|
expect(actual).toEqual({
|
|
95
91
|
contextSecrets: 'Listen up: ',
|
|
96
92
|
processEnvs: 'Listen up: Good dog!',
|
|
97
93
|
});
|
|
94
|
+
expect(setProperTokenInSecretsSpy).toHaveBeenCalledTimes(1);
|
|
95
|
+
expect(loadSecretsSpy).toHaveBeenCalledTimes(1);
|
|
96
|
+
setProperTokenInSecretsSpy.mockRestore();
|
|
97
|
+
loadSecretsSpy.mockRestore();
|
|
98
98
|
});
|
|
99
99
|
it('works with other inputs', async () => {
|
|
100
|
+
const setProperTokenInSecretsSpy = vi.spyOn(SecretsModule, 'setProperTokenInSecrets');
|
|
101
|
+
const loadSecretsSpy = vi.spyOn(SecretsModule, 'loadSecrets');
|
|
100
102
|
const inputs = { parameters: { PHRASE: 'Bella, ' } };
|
|
101
103
|
await executeFunction(TEST_CONFIG, 'uses-secret', inputs, setActual);
|
|
102
104
|
expect(actual).toEqual({
|
|
103
105
|
contextSecrets: 'Listen up: Bella, ',
|
|
104
106
|
processEnvs: 'Listen up: Bella, Good dog!',
|
|
105
107
|
});
|
|
108
|
+
setProperTokenInSecretsSpy.mockRestore();
|
|
109
|
+
loadSecretsSpy.mockRestore();
|
|
106
110
|
});
|
|
107
111
|
});
|
|
108
112
|
it('throws an error if the function is not declared', async () => {
|
|
@@ -165,4 +169,15 @@ describe('app function executor', () => {
|
|
|
165
169
|
expect(err.cause).toHaveProperty('message', 'Oops');
|
|
166
170
|
}
|
|
167
171
|
});
|
|
172
|
+
it('throws an error if the function calls callback', async () => {
|
|
173
|
+
try {
|
|
174
|
+
await executeFunction(TEST_CONFIG, 'calls-callback', {}, NOOP_CALLBACK);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
expect(err).toBeInstanceOf(ExecutionError);
|
|
178
|
+
expect(err.reason).toBe(Reason.UncaughtError);
|
|
179
|
+
expect(err.cause).toBeInstanceOf(Error);
|
|
180
|
+
expect(err.cause).toHaveProperty('message', 'callback is not a function');
|
|
181
|
+
}
|
|
182
|
+
});
|
|
168
183
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ApiException, ServiceConfiguration } from '../../../
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
1
|
+
import { ApiException, PlatformVersion, ServiceConfiguration } from '../../../serverless/types.ts';
|
|
2
|
+
export declare const TEST_CONFIG_V20251: ServiceConfiguration;
|
|
3
|
+
export declare const TEST_CONFIG_V202603: ServiceConfiguration;
|
|
4
|
+
export declare function buildUnsupportedVersionConfig(platformVersion: PlatformVersion): ServiceConfiguration;
|
|
4
5
|
export declare const NOOP_CALLBACK: () => void;
|
|
5
6
|
export declare const SAMPLE_FUNCTION_JS = "exports.main = (context = {}, sendResponse) => {\n sendResponse({\n propertiesToSend: context.propertiesToSend,\n parameters: context.parameters,\n payload: context.event && context.event.payload,\n secrets: context.secrets,\n });\n};\n";
|
|
6
7
|
export declare const SAMPLE_SERVERLESS_JSON: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
|
-
import { PLATFORM_VERSION } from "../../../
|
|
2
|
+
import { PLATFORM_VERSION } from "../../../constants.js";
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
function buildTestConfig(platformVersion) {
|
|
5
5
|
return {
|
|
@@ -17,8 +17,14 @@ function buildTestConfig(platformVersion) {
|
|
|
17
17
|
platformVersion,
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
export const
|
|
21
|
-
export const
|
|
20
|
+
export const TEST_CONFIG_V20251 = buildTestConfig(PLATFORM_VERSION.V20251);
|
|
21
|
+
export const TEST_CONFIG_V202603 = buildTestConfig(PLATFORM_VERSION.V202603);
|
|
22
|
+
export function buildUnsupportedVersionConfig(platformVersion) {
|
|
23
|
+
return {
|
|
24
|
+
...buildTestConfig(PLATFORM_VERSION.V20251),
|
|
25
|
+
platformVersion,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
22
28
|
export const NOOP_CALLBACK = () => { };
|
|
23
29
|
export const SAMPLE_FUNCTION_JS = `exports.main = (context = {}, sendResponse) => {
|
|
24
30
|
sendResponse({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): Promise<never>;
|
package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-does-not-export-main.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function notMain(__context?: {}): string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.main = (context = {}
|
|
3
|
-
|
|
2
|
+
exports.main = (context = {}) => {
|
|
3
|
+
return {
|
|
4
4
|
propertiesToSend: context.propertiesToSend,
|
|
5
5
|
parameters: context.parameters,
|
|
6
6
|
payload: context.event && context.event.payload,
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
8
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.main = (__context = {}
|
|
2
|
+
exports.main = (__context = {}) => {
|
|
3
3
|
console.log('log line');
|
|
4
4
|
console.debug('debug line');
|
|
5
5
|
console.info('info line');
|
|
6
6
|
console.warn('warn line');
|
|
7
7
|
console.error('error line');
|
|
8
8
|
console.info('print data:', [1, 2]);
|
|
9
|
-
|
|
9
|
+
return { status: 'success' };
|
|
10
10
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): () => void;
|
package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-implicitly.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): Promise<any>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): string;
|
package/dist/lib/__tests__/serverless/fixtures/v2026.03/functions/func-returns-undefined.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(__context?: {}): undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.main = (context = {}) => {
|
|
3
|
+
const parameters = context.parameters || {};
|
|
4
|
+
const delayMs = parameters.delayMs || 60_000;
|
|
5
|
+
const startedAt = Date.now();
|
|
6
|
+
return new Promise((resolve, __reject) => {
|
|
7
|
+
setTimeout(() => resolve({
|
|
8
|
+
status: 'success',
|
|
9
|
+
elapsedMs: Date.now() - startedAt,
|
|
10
|
+
}), delayMs);
|
|
11
|
+
});
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function main(context?: {}): Promise<any>;
|