@prismatic-io/spectral 10.15.0 → 10.16.2

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.
@@ -11,7 +11,10 @@ interface RetryConfig extends Omit<IAxiosRetryConfig, "retryDelay"> {
11
11
  * a retryCondition function to determine when retries should occur.
12
12
  */
13
13
  retryAllErrors?: boolean;
14
- /** When true, double the retry delay after each attempt (e.g. 1000ms, 2000ms, 4000ms, 8000ms, etc.). */
14
+ /**
15
+ * When true, double the retryDelay after each attempt (e.g. 1000ms, 2000ms, 4000ms, 8000ms, etc.).
16
+ * If no retryDelay is specified, defaults to axios-retry's exponentialDelay function.
17
+ */
15
18
  useExponentialBackoff?: boolean;
16
19
  }
17
20
  export interface ClientProps {
@@ -30,6 +33,7 @@ export interface ClientProps {
30
33
  /** Configuration used to determine if and how failed HTTP requests should be retried. */
31
34
  retryConfig?: RetryConfig;
32
35
  }
36
+ export declare const toAxiosRetryConfig: ({ retryDelay, retryAllErrors, retryCondition, useExponentialBackoff, ...rest }: RetryConfig) => IAxiosRetryConfig;
33
37
  /**
34
38
  * Creates a reusable Axios HTTP client. See
35
39
  * https://prismatic.io/docs/custom-connectors/connections/#using-the-built-in-createclient-http-client
@@ -46,7 +46,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
46
46
  return (mod && mod.__esModule) ? mod : { "default": mod };
47
47
  };
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.inputs = exports.buildRawRequestAction = exports.sendRawRequest = exports.handleErrors = exports.createClient = void 0;
49
+ exports.inputs = exports.buildRawRequestAction = exports.sendRawRequest = exports.handleErrors = exports.createClient = exports.toAxiosRetryConfig = void 0;
50
50
  const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
51
51
  const axios_1 = __importDefault(require("axios"));
52
52
  const axios_retry_1 = __importStar(require("axios-retry"));
@@ -84,8 +84,11 @@ const toFormData = (formData, fileData, fileDataFileNames = {}) => {
84
84
  };
85
85
  const computeRetryDelay = (retryDelay, useExponentialBackoff) => {
86
86
  if (useExponentialBackoff) {
87
- return axios_retry_1.exponentialDelay;
87
+ return typeof retryDelay === "number"
88
+ ? (retryCount) => Math.pow(2, (retryCount - 1)) * retryDelay
89
+ : axios_retry_1.exponentialDelay;
88
90
  }
91
+ // retryDelay is either a number or a function
89
92
  return typeof retryDelay === "number" ? () => retryDelay : retryDelay;
90
93
  };
91
94
  const toAxiosRetryConfig = (_a) => {
@@ -96,6 +99,7 @@ const toAxiosRetryConfig = (_a) => {
96
99
  ? retryCondition
97
100
  : axios_retry_1.isNetworkOrIdempotentRequestError }));
98
101
  };
102
+ exports.toAxiosRetryConfig = toAxiosRetryConfig;
99
103
  /**
100
104
  * Creates a reusable Axios HTTP client. See
101
105
  * https://prismatic.io/docs/custom-connectors/connections/#using-the-built-in-createclient-http-client
@@ -141,7 +145,7 @@ const createClient = ({ baseUrl, responseType, headers, timeout, params, debug =
141
145
  }
142
146
  if (retryConfig) {
143
147
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
- (0, axios_retry_1.default)(client, toAxiosRetryConfig(retryConfig));
148
+ (0, axios_retry_1.default)(client, (0, exports.toAxiosRetryConfig)(retryConfig));
145
149
  }
146
150
  return client;
147
151
  };
@@ -81,10 +81,7 @@ function createDebugContext(context) {
81
81
  },
82
82
  memoryUsage: (actionContext, label, showDetail) => {
83
83
  if (globalDebug) {
84
- const usage = showDetail
85
- ? memoryUsageInMB()
86
- : // @ts-expect-error: memoryUsage.rss() is documented but not typed
87
- node_process_1.memoryUsage.rss() / MEMORY_USAGE_CONVERSION;
84
+ const usage = showDetail ? memoryUsageInMB() : node_process_1.memoryUsage.rss() / MEMORY_USAGE_CONVERSION;
88
85
  actionContext.debug.results.memoryUsage.push({
89
86
  mark: label,
90
87
  rss: typeof usage === "number" ? usage : usage.rss,
@@ -1,8 +1,12 @@
1
- import { IntegrationDefinition, ConfigVar, Flow, ConfigPages, ComponentRegistry, TriggerReference, CollectionType, Inputs, TriggerResult as TriggerPerformResult, ConfigVarResultCollection } from "../types";
1
+ import { IntegrationDefinition, ConfigVar, Flow, ConfigPages, ComponentRegistry, TriggerReference, CollectionType, Inputs, TriggerResult as TriggerPerformResult, ConfigVarResultCollection, QueueConfig, StandardQueueConfig } from "../types";
2
2
  import { Component as ServerComponent, ActionContext, TriggerPayload, TriggerResult } from ".";
3
3
  import { RequiredConfigVariable as ServerRequiredConfigVariable, ConfigPage as ServerConfigPage, ComponentReference as ServerComponentReference } from "./integration";
4
+ export declare const CONCURRENCY_LIMIT_MAX = 15;
5
+ export declare const CONCURRENCY_LIMIT_MIN = 2;
4
6
  export declare const convertIntegration: <TInputs extends Inputs, TActionInputs extends Inputs, TPayload extends TriggerPayload = TriggerPayload, TAllowsBranching extends boolean = boolean, TResult extends TriggerPerformResult<TAllowsBranching, TPayload> = TriggerPerformResult<TAllowsBranching, TPayload>>(definition: IntegrationDefinition<TInputs, TActionInputs, TPayload, TAllowsBranching, TResult>) => ServerComponent<TInputs, TActionInputs, ConfigVarResultCollection, TPayload, TAllowsBranching, TResult>;
5
7
  export declare const convertConfigPages: (pages: ConfigPages | undefined, userLevelConfigured: boolean) => ServerConfigPage[];
8
+ /** Converts typed QueueConfig to legacy format with usesFifoQueue and concurrencyLimit. */
9
+ export declare const convertQueueConfig: (queueConfig: QueueConfig) => StandardQueueConfig;
6
10
  /** Converts a Flow into the structure necessary for YAML generation. */
7
11
  export declare const convertFlow: <TInputs extends Inputs, TActionInputs extends Inputs, TPayload extends TriggerPayload = TriggerPayload, TAllowsBranching extends boolean = boolean, TResult extends TriggerPerformResult<TAllowsBranching, TPayload> = TriggerPerformResult<TAllowsBranching, TPayload>>(flow: Flow<TInputs, TActionInputs, TPayload, TAllowsBranching, TResult>, componentRegistry: ComponentRegistry, referenceKey: string) => Record<string, unknown>;
8
12
  /** Converts an input value to the expected server type by its collection type. */
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.invokeTriggerComponentInput = exports.convertConfigVar = exports.convertInputValue = exports.convertFlow = exports.convertConfigPages = exports.convertIntegration = void 0;
15
+ exports.invokeTriggerComponentInput = exports.convertConfigVar = exports.convertInputValue = exports.convertFlow = exports.convertQueueConfig = exports.convertConfigPages = exports.convertIntegration = exports.CONCURRENCY_LIMIT_MIN = exports.CONCURRENCY_LIMIT_MAX = void 0;
16
16
  const yaml_1 = __importDefault(require("yaml"));
17
17
  const uuid_1 = require("uuid");
18
18
  const assign_1 = __importDefault(require("lodash/assign"));
@@ -27,6 +27,8 @@ const context_1 = require("./context");
27
27
  const asyncContext_1 = require("./asyncContext");
28
28
  const path_1 = __importDefault(require("path"));
29
29
  const fs_1 = require("fs");
30
+ exports.CONCURRENCY_LIMIT_MAX = 15;
31
+ exports.CONCURRENCY_LIMIT_MIN = 2;
30
32
  const convertIntegration = (definition) => {
31
33
  var _a, _b, _c;
32
34
  // Generate a unique reference key that will be used to reference the
@@ -279,6 +281,30 @@ const flowUsesWrapperTrigger = (flow) => {
279
281
  flow.onInstanceDeploy ||
280
282
  flow.webhookLifecycleHandlers);
281
283
  };
284
+ /** Converts typed QueueConfig to legacy format with usesFifoQueue and concurrencyLimit. */
285
+ const convertQueueConfig = (queueConfig) => {
286
+ if (!("type" in queueConfig)) {
287
+ return queueConfig;
288
+ }
289
+ switch (queueConfig.type) {
290
+ case "parallel":
291
+ return { usesFifoQueue: false };
292
+ case "throttled":
293
+ return {
294
+ usesFifoQueue: true,
295
+ concurrencyLimit: queueConfig.concurrencyLimit,
296
+ dedupeIdField: queueConfig.dedupeIdField,
297
+ };
298
+ case "sequential":
299
+ return {
300
+ usesFifoQueue: true,
301
+ dedupeIdField: queueConfig.dedupeIdField,
302
+ };
303
+ default:
304
+ return queueConfig;
305
+ }
306
+ };
307
+ exports.convertQueueConfig = convertQueueConfig;
282
308
  const convertFlowSchemas = (flowKey, schemas) => {
283
309
  return Object.entries(schemas).reduce((acc, [key, value]) => {
284
310
  var _a;
@@ -356,7 +382,7 @@ const convertFlow = (flow, componentRegistry, referenceKey) => {
356
382
  throw new Error(`${flow.name} is marked as a polling trigger but has no schedule. Polling triggers require a schedule.`);
357
383
  }
358
384
  if ("queueConfig" in flow && typeof flow.queueConfig === "object") {
359
- const { queueConfig } = flow;
385
+ const queueConfig = (0, exports.convertQueueConfig)(flow.queueConfig);
360
386
  if (hasSchedule && queueConfig.usesFifoQueue) {
361
387
  throw new Error(`${flow.name} has a schedule & usesFifoQueue set to true. FIFO queues cannot be used with scheduled flows.`);
362
388
  }
@@ -367,8 +393,9 @@ const convertFlow = (flow, componentRegistry, referenceKey) => {
367
393
  throw new Error(`${flow.name} is configured for both FIFO queues and singleton executions, but these options are mutually exclusive. Please choose one.`);
368
394
  }
369
395
  if (queueConfig.concurrencyLimit !== undefined &&
370
- (queueConfig.concurrencyLimit < 2 || queueConfig.concurrencyLimit > 10)) {
371
- throw new Error(`${flow.name} has an invalid concurrencyLimit of ${queueConfig.concurrencyLimit}. concurrencyLimit must be between 2 and 10.`);
396
+ (queueConfig.concurrencyLimit < exports.CONCURRENCY_LIMIT_MIN ||
397
+ queueConfig.concurrencyLimit > exports.CONCURRENCY_LIMIT_MAX)) {
398
+ throw new Error(`${flow.name} has an invalid concurrencyLimit of ${queueConfig.concurrencyLimit}. concurrencyLimit must be between ${exports.CONCURRENCY_LIMIT_MIN} and ${exports.CONCURRENCY_LIMIT_MAX}.`);
372
399
  }
373
400
  result.queueConfig = Object.assign(Object.assign({ usesFifoQueue: false }, queueConfig), (queueConfig.dedupeIdField
374
401
  ? {
@@ -198,16 +198,35 @@ export type RetryConfig = {
198
198
  uniqueRequestIdField?: string;
199
199
  };
200
200
  /** Defines attributes of a queue configuration used by a flow of an integration. */
201
- export type QueueConfig = {
201
+ export type StandardQueueConfig = {
202
202
  /** Determines whether the flow should be executed using FIFO ordering. Not valid for synchronous or scheduled flows. */
203
203
  usesFifoQueue?: boolean;
204
204
  /** Reference to the field in the flow's trigger return payload; used to determine whether to queue the execution. */
205
205
  dedupeIdField?: string;
206
206
  /** Determines whether the flow should be setup for singleton executions. Only valid for scheduled/polling trigger-based flows. */
207
207
  singletonExecutions?: boolean;
208
- /** The maximum number of concurrent executions for this flow. Must be between 2 and 10. */
208
+ /** The maximum number of concurrent executions for this flow. Must be between 2 and 15. */
209
209
  concurrencyLimit?: number;
210
210
  };
211
+ export type ParallelQueueConfig = {
212
+ /** No limits. All requests processed simultaneously. */
213
+ type: "parallel";
214
+ };
215
+ export type ThrottledQueueConfig = {
216
+ /** Set the max concurrent executions per instance. */
217
+ type: "throttled";
218
+ /** The maximum number of concurrent executions for this flow. Must be between 2 and 15. */
219
+ concurrencyLimit?: number;
220
+ /** Reference to the field in the flow's trigger return payload; used to determine whether to queue the execution. */
221
+ dedupeIdField?: string;
222
+ };
223
+ export type SequentialQueueConfig = {
224
+ /** Processed one at a time, in order received. */
225
+ type: "sequential";
226
+ /** Reference to the field in the flow's trigger return payload; used to determine whether to queue the execution. */
227
+ dedupeIdField?: string;
228
+ };
229
+ export type QueueConfig = ParallelQueueConfig | ThrottledQueueConfig | SequentialQueueConfig | StandardQueueConfig;
211
230
  /** Defines attributes of a step error configuration used to determine how to handle errors during flow step execution. */
212
231
  export type StepErrorConfig = {
213
232
  /** Defines the type of error handler. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismatic-io/spectral",
3
- "version": "10.15.0",
3
+ "version": "10.16.2",
4
4
  "description": "Utility library for building Prismatic connectors and code-native integrations",
5
5
  "keywords": ["prismatic"],
6
6
  "main": "dist/index.js",
@@ -34,18 +34,20 @@
34
34
  "format": "yarn run lint-fix && biome format --write .",
35
35
  "check-format": "biome format .",
36
36
  "check": "yarn run check-format && yarn run lint",
37
- "test": "jest"
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "test:ui": "vitest --ui"
38
40
  },
39
41
  "files": ["dist/"],
40
42
  "dependencies": {
41
- "axios": "1.12.2",
43
+ "axios": "1.13.5",
42
44
  "axios-retry": "4.5.0",
43
45
  "date-fns": "2.30.0",
44
46
  "ejs": "^3.1.10",
45
47
  "form-data": "4.0.4",
46
48
  "fs-extra": "^11.2.0",
47
49
  "jest-mock": "29.7.0",
48
- "lodash": "4.17.21",
50
+ "lodash": "4.17.23",
49
51
  "object-sizeof": "^2.6.4",
50
52
  "prettier": "2.6.2",
51
53
  "safe-stable-stringify": "2.3.1",
@@ -57,20 +59,20 @@
57
59
  },
58
60
  "devDependencies": {
59
61
  "@biomejs/biome": "1.6.3",
62
+ "@fast-check/vitest": "^0.2.4",
60
63
  "@types/ejs": "3.1.5",
61
64
  "@types/fs-extra": "11.0.4",
62
- "@types/jest": "29.5.12",
63
- "@types/lodash": "4.17.0",
64
- "@types/node": "14.14.35",
65
+ "@types/lodash": "4.17.23",
66
+ "@types/node": "^22.19.7",
65
67
  "@types/prettier": "2.6.2",
66
68
  "@types/sax": "1.2.4",
67
69
  "@types/url-join": "4.0.1",
68
70
  "@types/uuid": "8.3.4",
69
71
  "@types/valid-url": "1.0.3",
72
+ "@vitest/ui": "^4.0.18",
70
73
  "copyfiles": "2.4.1",
71
- "fast-check": "2.16.0",
72
- "jest": "29.7.0",
73
- "ts-jest": "29.1.2",
74
- "typescript": "5.5.3"
74
+ "fast-check": "^4.5.3",
75
+ "typescript": "5.5.3",
76
+ "vitest": "^4.0.18"
75
77
  }
76
78
  }