@prismatic-io/spectral 10.13.0 → 10.15.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.
@@ -9,7 +9,7 @@ export declare const convertFlow: <TInputs extends Inputs, TActionInputs extends
9
9
  export declare const convertInputValue: (value: unknown, collectionType: CollectionType | undefined) => unknown;
10
10
  /** Converts a Config Var into the structure necessary for YAML generation. */
11
11
  export declare const convertConfigVar: (key: string, configVar: ConfigVar, referenceKey: string, componentRegistry: ComponentRegistry) => ServerRequiredConfigVariable;
12
- export declare const invokeTriggerComponentInput: (componentRef: ServerComponentReference, onTrigger: TriggerReference | undefined, eventName: "perform" | "onInstanceDeploy" | "onInstanceDelete") => {
12
+ export declare const invokeTriggerComponentInput: (componentRef: ServerComponentReference, onTrigger: TriggerReference | undefined, eventName: "perform" | "onInstanceDeploy" | "onInstanceDelete" | "webhookCreate" | "webhookDelete") => {
13
13
  component: {
14
14
  key: string;
15
15
  version: number | "LATEST";
@@ -20,10 +20,10 @@ export declare const invokeTriggerComponentInput: (componentRef: ServerComponent
20
20
  isPublic: boolean;
21
21
  };
22
22
  key: string;
23
- triggerEventFunctionName: "perform" | "onInstanceDeploy" | "onInstanceDelete";
23
+ triggerEventFunctionName: "perform" | "onInstanceDeploy" | "onInstanceDelete" | "webhookCreate" | "webhookDelete";
24
24
  };
25
25
  export type TriggerActionInvokeFunction = (ref: {
26
26
  component: ServerComponentReference["component"];
27
27
  key: string;
28
- triggerEventFunctionName: "perform" | "onInstanceDeploy" | "onInstanceDelete";
28
+ triggerEventFunctionName: "perform" | "onInstanceDeploy" | "onInstanceDelete" | "webhookCreate" | "webhookDelete";
29
29
  }, context: ActionContext, payload: TriggerPayload | null, params: Record<string, unknown>) => Promise<TriggerResult>;
@@ -92,7 +92,7 @@ const convertConfigPages = (pages, userLevelConfigured) => {
92
92
  }) })));
93
93
  };
94
94
  exports.convertConfigPages = convertConfigPages;
95
- const codeNativeIntegrationYaml = ({ name, description, category, documentation, version, labels, endpointType, triggerPreprocessFlowConfig, flows, configPages, userLevelConfigPages, scopedConfigVars, instanceProfile = "Default Instance Profile", componentRegistry = {}, }, referenceKey, configVars, metadata) => {
95
+ const codeNativeIntegrationYaml = ({ name, description, category, documentation, version, labels, endpointType, triggerPreprocessFlowConfig, flows, configPages, userLevelConfigPages, scopedConfigVars, instanceProfile, componentRegistry = {}, }, referenceKey, configVars, metadata) => {
96
96
  // Find the preprocess flow config on the flow, if one exists.
97
97
  const preprocessFlows = flows.filter((flow) => flow.preprocessFlowConfig);
98
98
  // Do some validation of preprocess flow configs.
@@ -125,29 +125,17 @@ const codeNativeIntegrationYaml = ({ name, description, category, documentation,
125
125
  // Transform the IntegrationDefinition into the structure that is appropriate
126
126
  // for generating YAML, which will then be used by the Prismatic API to import
127
127
  // the integration as a Code Native Integration.
128
- const result = {
129
- definitionVersion: integration_1.DefinitionVersion,
130
- isCodeNative: true,
131
- name,
128
+ const result = Object.assign(Object.assign({ definitionVersion: integration_1.DefinitionVersion, isCodeNative: true, name,
132
129
  description,
133
130
  category,
134
131
  documentation,
135
132
  version,
136
133
  labels,
137
134
  requiredConfigVars,
138
- endpointType,
139
- preprocessFlowName: hasPreprocessFlow ? preprocessFlows[0].name : undefined,
140
- externalCustomerIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerIdField),
141
- externalCustomerUserIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerUserIdField),
142
- flowNameField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.flowNameField),
143
- flows: flows.map((flow) => (0, exports.convertFlow)(flow, componentRegistry, referenceKey)),
144
- defaultInstanceProfile: instanceProfile,
145
- configPages: [
135
+ endpointType, preprocessFlowName: hasPreprocessFlow ? preprocessFlows[0].name : undefined, externalCustomerIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerIdField), externalCustomerUserIdField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.externalCustomerUserIdField), flowNameField: fieldNameToReferenceInput(hasPreprocessFlow ? "onExecution" : "payload", preprocessFlowConfig === null || preprocessFlowConfig === void 0 ? void 0 : preprocessFlowConfig.flowNameField), flows: flows.map((flow) => (0, exports.convertFlow)(flow, componentRegistry, referenceKey)) }, (instanceProfile && { defaultInstanceProfile: instanceProfile })), { configPages: [
146
136
  ...(0, exports.convertConfigPages)(configPages, false),
147
137
  ...(0, exports.convertConfigPages)(userLevelConfigPages, true),
148
- ],
149
- importMetadata: metadata,
150
- };
138
+ ], importMetadata: metadata });
151
139
  return yaml_1.default.stringify(result);
152
140
  };
153
141
  const permissionAndVisibilityTypeValueMap = {
@@ -283,10 +271,13 @@ const codeNativeIntegrationComponentReference = (referenceKey) => ({
283
271
  isPublic: false,
284
272
  });
285
273
  /* A flow's trigger gets wrapped in a custom component if there's a defined
286
- * onTrigger function, or if any custom onInstance behavior is defined.
274
+ * onTrigger function, or if any custom onInstance or webhook lifecycle behavior is defined.
287
275
  * */
288
276
  const flowUsesWrapperTrigger = (flow) => {
289
- return typeof flow.onTrigger === "function" || flow.onInstanceDelete || flow.onInstanceDeploy;
277
+ return (typeof flow.onTrigger === "function" ||
278
+ flow.onInstanceDelete ||
279
+ flow.onInstanceDeploy ||
280
+ flow.webhookLifecycleHandlers);
290
281
  };
291
282
  const convertFlowSchemas = (flowKey, schemas) => {
292
283
  return Object.entries(schemas).reduce((acc, [key, value]) => {
@@ -303,6 +294,7 @@ const convertFlow = (flow, componentRegistry, referenceKey) => {
303
294
  result.trigger = undefined;
304
295
  result.onInstanceDeploy = undefined;
305
296
  result.onInstanceDelete = undefined;
297
+ result.webhookLifecycleHandlers = undefined;
306
298
  result.onExecution = undefined;
307
299
  result.preprocessFlowConfig = undefined;
308
300
  result.errorConfig = undefined;
@@ -417,6 +409,22 @@ const convertInputValue = (value, collectionType) => {
417
409
  }));
418
410
  };
419
411
  exports.convertInputValue = convertInputValue;
412
+ const validateOnPremConnectionConfig = (connection) => {
413
+ if ((0, types_1.isConnectionDefinitionConfigVar)(connection)) {
414
+ const hasOnPremControlledInputs = Object.values(connection.inputs).some((value) => {
415
+ return "onPremControlled" in value && value.onPremControlled;
416
+ });
417
+ const { onPremConnectionConfig: config } = connection;
418
+ if (hasOnPremControlledInputs && !config) {
419
+ throw new Error(`Connection ${connection.stableKey} has onPremControlled inputs but no onPremConnectionConfig value set. Please set an onPremConnectionConfig value for the connection.`);
420
+ }
421
+ if (!hasOnPremControlledInputs && config && config !== "disallowed") {
422
+ throw new Error(`Connection ${connection.stableKey} has onPremConnectionConfig set but no onPremControlled inputs. The connection will not be valid without onPremControlled inputs (host, port).`);
423
+ }
424
+ return hasOnPremControlledInputs && config ? config : "disallowed";
425
+ }
426
+ return "disallowed";
427
+ };
420
428
  /** Converts a Config Var into the structure necessary for YAML generation. */
421
429
  const convertConfigVar = (key, configVar, referenceKey, componentRegistry) => {
422
430
  var _a, _b, _c;
@@ -437,6 +445,7 @@ const convertConfigVar = (key, configVar, referenceKey, componentRegistry) => {
437
445
  description,
438
446
  key,
439
447
  dataType: "connection",
448
+ onPremiseConnectionConfig: validateOnPremConnectionConfig(configVar),
440
449
  connection: {
441
450
  key: (0, camelCase_1.default)(key),
442
451
  component: codeNativeIntegrationComponentReference(referenceKey),
@@ -630,11 +639,12 @@ function generateTriggerPerformFn(params) {
630
639
  throw new Error(`Invalid trigger configuration detected: ${JSON.stringify(params, null, 2)}`);
631
640
  }
632
641
  }
633
- /** Generates a wrapper function that calls an existing component's onInstanceDeploy
634
- * or onInstanceDelete, then calls the flow-defined version if it exists.
642
+ /** Generates a wrapper function that calls an existing component's trigger event function
643
+ * (onInstanceDeploy, onInstanceDelete, webhookCreate, or webhookDelete), then calls
644
+ * the flow-defined version if it exists.
635
645
  * Returns the deep-merged results of the two, prioritizing the custom response
636
646
  * if there's a conflict. */
637
- const generateOnInstanceWrapperFn = (componentRef, onTrigger, eventName, componentRegistry, customFn) => {
647
+ const generateTriggerEventWrapperFn = (componentRef, onTrigger, eventName, componentRegistry, customFn) => {
638
648
  const usesComponentRef = componentRef && typeof onTrigger !== "function";
639
649
  if (usesComponentRef) {
640
650
  return (context, params) => __awaiter(void 0, void 0, void 0, function* () {
@@ -693,11 +703,12 @@ const codeNativeIntegrationComponent = ({ name, iconPath, description, flows = [
693
703
  inputs: [],
694
704
  } });
695
705
  }, {});
696
- const convertedTriggers = flows.reduce((result, { name, onTrigger, onInstanceDeploy, onInstanceDelete, schedule, triggerType }) => {
706
+ const convertedTriggers = flows.reduce((result, { name, onTrigger, onInstanceDeploy, onInstanceDelete, webhookLifecycleHandlers, schedule, triggerType, }) => {
697
707
  if (!flowUsesWrapperTrigger({
698
708
  onTrigger,
699
709
  onInstanceDelete,
700
710
  onInstanceDeploy,
711
+ webhookLifecycleHandlers,
701
712
  })) {
702
713
  // In this scenario, the user has defined an existing component trigger
703
714
  // without any custom behavior, so we don't need to wrap anything.
@@ -723,8 +734,10 @@ const codeNativeIntegrationComponent = ({ name, iconPath, description, flows = [
723
734
  componentRegistry,
724
735
  triggerType,
725
736
  });
726
- const deleteFn = generateOnInstanceWrapperFn(ref, onTrigger, "onInstanceDelete", componentRegistry, onInstanceDelete);
727
- const deployFn = generateOnInstanceWrapperFn(ref, onTrigger, "onInstanceDeploy", componentRegistry, onInstanceDeploy);
737
+ const deleteFn = generateTriggerEventWrapperFn(ref, onTrigger, "onInstanceDelete", componentRegistry, onInstanceDelete);
738
+ const deployFn = generateTriggerEventWrapperFn(ref, onTrigger, "onInstanceDeploy", componentRegistry, onInstanceDeploy);
739
+ const webhookCreateFn = generateTriggerEventWrapperFn(ref, onTrigger, "webhookCreate", componentRegistry, webhookLifecycleHandlers === null || webhookLifecycleHandlers === void 0 ? void 0 : webhookLifecycleHandlers.create);
740
+ const webhookDeleteFn = generateTriggerEventWrapperFn(ref, onTrigger, "webhookDelete", componentRegistry, webhookLifecycleHandlers === null || webhookLifecycleHandlers === void 0 ? void 0 : webhookLifecycleHandlers.delete);
728
741
  return Object.assign(Object.assign({}, result), { [key]: {
729
742
  key,
730
743
  display: {
@@ -736,6 +749,10 @@ const codeNativeIntegrationComponent = ({ name, iconPath, description, flows = [
736
749
  hasOnInstanceDeploy: !!deployFn,
737
750
  onInstanceDelete: deleteFn,
738
751
  hasOnInstanceDelete: !!deleteFn,
752
+ webhookCreate: webhookCreateFn,
753
+ hasWebhookCreateFunction: !!webhookCreateFn,
754
+ webhookDelete: webhookDeleteFn,
755
+ hasWebhookDeleteFunction: !!webhookDeleteFn,
739
756
  inputs: [],
740
757
  scheduleSupport: triggerType === "polling" ? "required" : "valid",
741
758
  synchronousResponseSupport: "valid",
@@ -169,13 +169,14 @@ export type DataSourceConfigVar = DataSourceDefinitionConfigVar | DataSourceRefe
169
169
  type BaseConnectionConfigVar = BaseConfigVar & {
170
170
  dataType: "connection";
171
171
  };
172
+ export type OnPremiseConnectionConfigTypeEnum = "allowed" | "disallowed" | "required";
172
173
  type ConnectionDefinitionConfigVar = ConnectionDefinition extends infer TConnectionDefinitionType extends ConnectionDefinition ? TConnectionDefinitionType extends infer TConnectionDefinition extends ConnectionDefinition ? BaseConnectionConfigVar & Omit<TConnectionDefinition, "inputs" | "display" | "key"> & {
173
174
  icons?: TConnectionDefinition["display"]["icons"];
175
+ onPremConnectionConfig?: OnPremiseConnectionConfigTypeEnum;
174
176
  inputs: {
175
177
  [Key in keyof TConnectionDefinition["inputs"]]: TConnectionDefinition["inputs"][Key] & ConfigVarInputVisibility;
176
178
  };
177
179
  } : never : never;
178
- type OnPremiseConnectionConfigTypeEnum = "allowed" | "disallowed" | "required";
179
180
  type ConnectionReferenceConfigVar = ComponentRegistryConnection extends infer TConnectionReference ? TConnectionReference extends ComponentRegistryConnection ? BaseConnectionConfigVar & {
180
181
  connection: TConnectionReference["reference"] & ("onPremAvailable" extends keyof TConnectionReference ? TConnectionReference["onPremAvailable"] extends true ? {
181
182
  template?: string;
@@ -61,7 +61,7 @@ export type IntegrationDefinition<TInputs extends Inputs = Inputs, TActionInputs
61
61
  /** Scoped ConfigVars for this integration. */
62
62
  scopedConfigVars?: ScopedConfigVarMap;
63
63
  /** Instance Profile used for this integration.
64
- * @default "Default Instance Profile"
64
+ * If not specified, the tenant's default Instance Profile will be used.
65
65
  */
66
66
  instanceProfile?: string;
67
67
  /**
@@ -133,6 +133,16 @@ interface FlowBase<TTriggerPayload extends TriggerPayload = TriggerPayload> {
133
133
  * https://prismatic.io/docs/custom-connectors/triggers/#instance-deploy-and-delete-events-for-triggers
134
134
  */
135
135
  onInstanceDelete?: TriggerEventFunction<Inputs, ConfigVars>;
136
+ /**
137
+ * Optional webhook lifecycle handlers for create and delete operations. See
138
+ * https://prismatic.io/docs/custom-connectors/triggers/#webhook-lifecycle-events
139
+ */
140
+ webhookLifecycleHandlers?: {
141
+ /** Function to execute to configure a webhook. */
142
+ create: TriggerEventFunction<Inputs, ConfigVars>;
143
+ /** Function to execute for webhook teardown. */
144
+ delete: TriggerEventFunction<Inputs, ConfigVars>;
145
+ };
136
146
  /** Specifies the main function for this flow which is run when this flow is invoked. */
137
147
  onExecution: FlowOnExecution<TTriggerPayload>;
138
148
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismatic-io/spectral",
3
- "version": "10.13.0",
3
+ "version": "10.15.0",
4
4
  "description": "Utility library for building Prismatic connectors and code-native integrations",
5
5
  "keywords": ["prismatic"],
6
6
  "main": "dist/index.js",