@prismatic-io/spectral 4.0.6 → 4.1.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/README.md CHANGED
@@ -14,22 +14,23 @@ Please see our [documentation](https://prismatic.io/docs/custom-components/writi
14
14
 
15
15
  ## What is Prismatic?
16
16
 
17
- Prismatic is the embedded integration platform for B2B software companies. It's the easiest way to build integrations and provide a first-class integration experience to your customers.
17
+ Prismatic is the integration platform for B2B software companies. It's the quickest way to build integrations to the other apps your customers use and to add a native integration marketplace to your product.
18
18
 
19
- Prismatic reduces integration effort and empowers every role with exactly what they need, so you can spend less time on integrations and more time on core product innovation.
19
+ Prismatic significantly reduces overall integration effort and enables non-dev teams to take on more of the integration workload, so that you can deliver integrations faster and spend more time on core product innovation.
20
20
 
21
21
  With Prismatic, you can:
22
22
 
23
- - Build reusable [integrations](https://prismatic.io/docs/integrations) in an intuitive low-code integration designer
23
+ - Build reusable [integrations](https://prismatic.io/docs/integrations) in a low-code integration designer that's tailored for your product
24
+ - Use [pre-built components](https://prismatic.io/docs/components/component-catalog) to handle most of your integrations' functionality, and write [custom components](https://prismatic.io/docs/custom-components/writing-custom-components) when needed
25
+ - Quickly add an [integration marketplace](https://prismatic.io/docs/integration-marketplace) to your product so customers can explore, activate, and monitor integrations
24
26
  - Easily deploy customer-specific integration [instances](https://prismatic.io/docs/instances) with unique configurations and credentials
25
- - Run your integrations in a purpose-built environment
26
- - Provide better support with built-in [logging](https://prismatic.io/docs/logging) and [alerting](https://prismatic.io/docs/monitoring-and-alerting)
27
- - Embed a white-labeled customer integration portal with an [integration marketplace](https://prismatic.io/docs/integration-marketplace/) and customer self-service tools
28
- - Mold the platform to your product, industry, and the way you build software
27
+ - Provide better support with tools like [logging](https://prismatic.io/docs/logging) and [alerting](https://prismatic.io/docs/monitoring-and-alerting)
28
+ - Run your integrations in a purpose-built environment designed for security and scalability
29
+ - Use powerful dev tools to mold the platform to your product, industry, and the way you build software
29
30
 
30
31
  ## Who uses Prismatic?
31
32
 
32
- Prismatic is for B2B (business-to-business) software companies, meaning software companies that provide applications used by businesses. It's a good fit for products/teams at any stage, including early stage SaaS, established SaaS, and legacy or on-prem systems.
33
+ Prismatic is for B2B (business-to-business) software companies, meaning software companies that provide applications used by businesses. It's a good fit for products/teams ranging from early-stage and growing SaaS startups to large, established software companies looking to improve the way they do integrations.
33
34
 
34
35
  Many B2B software teams serve customers in niche vertical markets, and we designed Prismatic with that in mind. We provide powerful and flexible tools so you can build exactly the integrations your customers need, no matter who your customers are, no matter what systems you need to connect to, no matter how "non-standard" your integration scenario.
35
36
 
package/dist/testing.js CHANGED
@@ -99,6 +99,8 @@ exports.credentials = {
99
99
  * See https://prismatic.io/docs/custom-components/writing-custom-components/#verifying-correct-logging-in-action-tests for information on testing correct logging behavior in your custom component.
100
100
  */
101
101
  const loggerMock = () => ({
102
+ metric: console.log,
103
+ trace: jest_mock_1.spyOn(console, "trace"),
102
104
  debug: jest_mock_1.spyOn(console, "debug"),
103
105
  info: jest_mock_1.spyOn(console, "info"),
104
106
  log: jest_mock_1.spyOn(console, "log"),
@@ -114,7 +116,7 @@ exports.loggerMock = loggerMock;
114
116
  */
115
117
  const invoke = (actionBase, params, context) => __awaiter(void 0, void 0, void 0, function* () {
116
118
  const action = (actionBase.perform ? actionBase : Object.values(actionBase)[0]);
117
- const realizedContext = Object.assign({ credential: undefined, logger: exports.loggerMock(), instanceState: {}, stepId: "mockStepId", executionId: "mockExecutionId" }, context);
119
+ const realizedContext = Object.assign({ credential: undefined, logger: exports.loggerMock(), instanceState: {}, executionState: {}, stepId: "mockStepId", executionId: "mockExecutionId" }, context);
118
120
  const result = yield action.perform(realizedContext, params);
119
121
  return {
120
122
  result,
@@ -141,6 +143,9 @@ const defaultTriggerPayload = () => {
141
143
  webhookUrls: {
142
144
  "Flow 1": "https://example.com",
143
145
  },
146
+ webhookApiKeys: {
147
+ "Flow 1": ["example-123", "example-456"],
148
+ },
144
149
  customer: {
145
150
  name: "Customer 1",
146
151
  externalId: "1234",
@@ -156,7 +161,7 @@ exports.defaultTriggerPayload = defaultTriggerPayload;
156
161
  */
157
162
  const invokeTrigger = (triggerBase, context, payload, params) => __awaiter(void 0, void 0, void 0, function* () {
158
163
  const trigger = (triggerBase.perform ? triggerBase : Object.values(triggerBase)[0]);
159
- const realizedContext = Object.assign({ credential: undefined, logger: exports.loggerMock(), instanceState: {}, stepId: "mockStepId", executionId: "mockExecutionId" }, context);
164
+ const realizedContext = Object.assign({ credential: undefined, logger: exports.loggerMock(), instanceState: {}, executionState: {}, stepId: "mockStepId", executionId: "mockExecutionId" }, context);
160
165
  const realizedPayload = Object.assign(Object.assign({}, exports.defaultTriggerPayload()), payload);
161
166
  const realizedParams = params || {};
162
167
  const result = yield trigger.perform(realizedContext, realizedPayload, realizedParams);
@@ -14,6 +14,8 @@ export interface ActionDefinition<T extends Inputs, AllowsBranching extends bool
14
14
  authorization?: AuthorizationDefinition;
15
15
  /** Optional attribute that specifies whether an Action will terminate execution.*/
16
16
  terminateExecution?: boolean;
17
+ /** Specifies whether an Action will break out of a loop. */
18
+ breakLoop?: boolean;
17
19
  /** Determines whether an Action will allow Conditional Branching.*/
18
20
  allowsBranching?: AllowsBranching;
19
21
  /** Static Branch names associated with an Action. */
@@ -12,6 +12,8 @@ export declare type ActionLoggerFunction = (...args: unknown[]) => void;
12
12
  * An object containing logger functions.
13
13
  */
14
14
  export interface ActionLogger {
15
+ metric: ActionLoggerFunction;
16
+ trace: ActionLoggerFunction;
15
17
  debug: ActionLoggerFunction;
16
18
  info: ActionLoggerFunction;
17
19
  log: ActionLoggerFunction;
@@ -9,6 +9,8 @@ export interface ActionContext {
9
9
  logger: ActionLogger;
10
10
  /** A key/value store that may be used to store small amounts of data that is persisted between Instance executions */
11
11
  instanceState: Record<string, unknown>;
12
+ /** A key/value store that may be used to store small amounts of data for use later during the execution */
13
+ executionState: Record<string, unknown>;
12
14
  /** A unique id that corresponds to the step on the Integration */
13
15
  stepId: string;
14
16
  /** A unique id that corresponds to the specific execution of the Integration */
@@ -7,7 +7,9 @@ export interface ActionPerformDataReturn<ReturnData> {
7
7
  /** The HTTP Status code that will be used if this terminates a synchronous invocation */
8
8
  statusCode?: number;
9
9
  /** An optional object, the keys and values of which will be persisted in the instanceState and available for subsequent actions and executions */
10
- state?: Record<string, unknown>;
10
+ instanceState?: Record<string, unknown>;
11
+ /** An optional object, the keys and values of which will be persisted in the executionState and available for the duration of the execution */
12
+ executionState?: Record<string, unknown>;
11
13
  }
12
14
  /** Used to represent a branching return of conventional data and does not require content type to be specified */
13
15
  /** Used to represent a binary or serialized data branching return as content type must be specified */
@@ -21,6 +21,8 @@ export interface TriggerDefinition<T extends Inputs, AllowsBranching extends boo
21
21
  authorization?: AuthorizationDefinition;
22
22
  /** Optional attribute that specifies whether this Trigger will terminate execution. */
23
23
  terminateExecution?: boolean;
24
+ /** Specifies whether an Action will break out of a loop. */
25
+ breakLoop?: boolean;
24
26
  /** Determines whether this Trigger allows Conditional Branching. */
25
27
  allowsBranching?: AllowsBranching;
26
28
  /** Static Branch names associated with this Trigger. */
@@ -14,9 +14,14 @@ export interface TriggerPayload {
14
14
  data: unknown;
15
15
  contentType?: string;
16
16
  };
17
+ /** The webhook URLs assigned to this integration's flows upon instance deploy */
17
18
  webhookUrls: {
18
19
  [key: string]: string;
19
20
  };
21
+ /** The optional API keys assigned to the flows of this integration. These may be unique per integration instance and per flow. */
22
+ webhookApiKeys: {
23
+ [key: string]: string[];
24
+ };
20
25
  customer: {
21
26
  externalId: string | null;
22
27
  name: string | null;
@@ -7,7 +7,9 @@ export interface TriggerBaseResult {
7
7
  /** Optional HTTP response to the request that invoked the integration. */
8
8
  response?: HttpResponse;
9
9
  /** An optional object, the keys and values of which will be persisted in the instanceState and available for subsequent actions and executions */
10
- state?: Record<string, unknown>;
10
+ instanceState?: Record<string, unknown>;
11
+ /** An optional object, the keys and values of which will be persisted in the executionState and available for the duration of the execution */
12
+ executionState?: Record<string, unknown>;
11
13
  }
12
14
  /** Represents the result of a Trigger action that uses branching. */
13
15
  export interface TriggerBranchingResult extends TriggerBaseResult {
@@ -47,6 +47,8 @@ interface BaseAction {
47
47
  authorization?: AuthorizationDefinition;
48
48
  /** Optional attribute that specifies whether an Action will terminate execution. */
49
49
  terminateExecution?: boolean;
50
+ /** Specifies whether an Action will break out of a loop. */
51
+ breakLoop?: boolean;
50
52
  /** Determines whether an Action will allow Conditional Branching. */
51
53
  allowsBranching?: boolean;
52
54
  /** Static Branch names associated with an Action. */
@@ -87,7 +89,9 @@ export interface ServerPerformDataStructureReturn {
87
89
  /** The HTTP Status code that will be used if this terminates a synchronous invocation */
88
90
  statusCode?: number;
89
91
  /** An optional object, the keys and values of which will be persisted in the instanceState and available for subsequent actions and executions */
90
- state?: Record<string, unknown>;
92
+ instanceState?: Record<string, unknown>;
93
+ /** An optional object, the keys and values of which will be persisted in the executionState and available for the duration of the execution */
94
+ executionState?: Record<string, unknown>;
91
95
  }
92
96
  /** Used to represent a binary or serialized data return as content type must be specified */
93
97
  interface ServerPerformDataReturn {
@@ -98,7 +102,9 @@ interface ServerPerformDataReturn {
98
102
  /** The HTTP Status code that will be used if this terminates a synchronous invocation */
99
103
  statusCode?: number;
100
104
  /** An optional object, the keys and values of which will be persisted in the instanceState and available for subsequent actions and executions */
101
- state?: Record<string, unknown>;
105
+ instanceState?: Record<string, unknown>;
106
+ /** An optional object, the keys and values of which will be persisted in the executionState and available for the duration of the execution */
107
+ executionState?: Record<string, unknown>;
102
108
  }
103
109
  /** Used to represent a branching return of conventional data and does not require content type to be specified */
104
110
  export interface ServerPerformBranchingDataStructureReturn extends ServerPerformDataStructureReturn {
package/dist/util.d.ts CHANGED
@@ -5,6 +5,16 @@
5
5
  */
6
6
  import { DataPayload } from "./types/server-types";
7
7
  import { KeyValuePair } from "./types";
8
+ /**
9
+ * This function returns a lower cased version of the headers passed to it.
10
+ *
11
+ * - `lowerCaseHeaders({"Content-Type": "Application/JSON"}) will return {"content-type": "Application/JSON"}`
12
+ * - `lowerCaseHeaders({"Cache-Control": "max-age=604800"}) will return {"cache-control": "max-age=604800"}`
13
+ * - `lowerCaseHeaders({"Accept-Language": "en-us"}) will return {"accept-language": "en-us"}`
14
+ * @param headers The headers to convert to lower case
15
+ * @returns This function returns a header object
16
+ * */
17
+ export declare const lowerCaseHeaders: (headers: Record<string, string>) => Record<string, string>;
8
18
  declare const _default: {
9
19
  types: {
10
20
  isBool: (value: unknown) => value is boolean;
@@ -25,6 +35,7 @@ declare const _default: {
25
35
  toString: (value: unknown, defaultValue?: string) => string;
26
36
  keyValPairListToObject: (kvpList?: KeyValuePair<unknown>[]) => Record<string, unknown>;
27
37
  isJSON: (value: string) => boolean;
38
+ lowerCaseHeaders: (headers: Record<string, string>) => Record<string, string>;
28
39
  };
29
40
  docs: {
30
41
  formatJsonExample: (input: unknown) => string;
package/dist/util.js CHANGED
@@ -8,6 +8,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
8
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
9
9
  };
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.lowerCaseHeaders = void 0;
11
12
  /** */
12
13
  const parseISO_1 = __importDefault(require("date-fns/parseISO"));
13
14
  const isValid_1 = __importDefault(require("date-fns/isValid"));
@@ -97,7 +98,7 @@ const toInt = (value, defaultValue) => {
97
98
  * - `util.types.isBool("5.5")` will return `true`, since the string `"5.5"` can easily be coerced into a number.
98
99
  * - `util.types.isBool("Hello")` will return `false`, since `"Hello"` is not a number.
99
100
  *
100
- * @param value The varible to test.
101
+ * @param value The variable to test.
101
102
  * @returns This function returns true if `value` can easily be coerced into a number, and false otherwise.
102
103
  */
103
104
  const isNumber = (value) => !Number.isNaN(Number(value));
@@ -310,6 +311,19 @@ const isJSON = (value) => {
310
311
  return false;
311
312
  }
312
313
  };
314
+ /**
315
+ * This function returns a lower cased version of the headers passed to it.
316
+ *
317
+ * - `lowerCaseHeaders({"Content-Type": "Application/JSON"}) will return {"content-type": "Application/JSON"}`
318
+ * - `lowerCaseHeaders({"Cache-Control": "max-age=604800"}) will return {"cache-control": "max-age=604800"}`
319
+ * - `lowerCaseHeaders({"Accept-Language": "en-us"}) will return {"accept-language": "en-us"}`
320
+ * @param headers The headers to convert to lower case
321
+ * @returns This function returns a header object
322
+ * */
323
+ const lowerCaseHeaders = (headers) => Object.entries(headers).reduce((result, [key, val]) => {
324
+ return Object.assign(Object.assign({}, result), { [key.toLowerCase()]: val });
325
+ }, {});
326
+ exports.lowerCaseHeaders = lowerCaseHeaders;
313
327
  exports.default = {
314
328
  types: {
315
329
  isBool,
@@ -330,6 +344,7 @@ exports.default = {
330
344
  toString,
331
345
  keyValPairListToObject,
332
346
  isJSON,
347
+ lowerCaseHeaders: exports.lowerCaseHeaders,
333
348
  },
334
349
  docs: {
335
350
  formatJsonExample,
package/dist/util.test.js CHANGED
@@ -283,4 +283,23 @@ describe("util", () => {
283
283
  }));
284
284
  });
285
285
  });
286
+ const validJSON = fast_check_1.default.jsonObject().map((x) => JSON.stringify(x));
287
+ const invalidJSON = fast_check_1.default.constantFrom("", "['']", "someString", null, undefined);
288
+ describe("JSON", () => {
289
+ it("returns true in the case of actual JSON", () => {
290
+ fast_check_1.default.assert(fast_check_1.default.property(validJSON, (v) => {
291
+ expect(util_1.default.types.isJSON(v)).toStrictEqual(true);
292
+ }));
293
+ });
294
+ it("returns false in the case of invalid JSON", () => {
295
+ fast_check_1.default.assert(fast_check_1.default.property(invalidJSON, (v) => {
296
+ expect(util_1.default.types.isJSON(util_1.default.types.toString(v))).toStrictEqual(false);
297
+ }));
298
+ });
299
+ describe("JSON", () => {
300
+ it("returns true in the case of actual JSON", () => {
301
+ expect(util_1.default.types.lowerCaseHeaders({ "Content-Type": "Application/Json" })).toStrictEqual({ "content-type": "Application/Json" });
302
+ });
303
+ });
304
+ });
286
305
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismatic-io/spectral",
3
- "version": "4.0.6",
3
+ "version": "4.1.0",
4
4
  "description": "Utility library for building Prismatic components",
5
5
  "keywords": [
6
6
  "prismatic"