@n8n/workflow-sdk 0.11.2 → 0.12.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.
Files changed (40) hide show
  1. package/dist/ast-interpreter/validators.js +1 -0
  2. package/dist/ast-interpreter/validators.js.map +1 -1
  3. package/dist/build.tsbuildinfo +1 -1
  4. package/dist/generate-types/generate-types.d.ts +8 -0
  5. package/dist/generate-types/generate-types.js +121 -27
  6. package/dist/generate-types/generate-types.js.map +1 -1
  7. package/dist/generate-types/generate-zod-schemas.d.ts +1 -0
  8. package/dist/generate-types/generate-zod-schemas.js +81 -18
  9. package/dist/generate-types/generate-zod-schemas.js.map +1 -1
  10. package/dist/prompts/best-practices/guides/web-app.d.ts +7 -0
  11. package/dist/prompts/best-practices/guides/web-app.js +206 -0
  12. package/dist/prompts/best-practices/guides/web-app.js.map +1 -0
  13. package/dist/prompts/best-practices/index.d.ts +1 -0
  14. package/dist/prompts/best-practices/index.js +5 -1
  15. package/dist/prompts/best-practices/index.js.map +1 -1
  16. package/dist/prompts/best-practices/types.d.ts +1 -0
  17. package/dist/prompts/best-practices/types.js +2 -0
  18. package/dist/prompts/best-practices/types.js.map +1 -1
  19. package/dist/types/base.d.ts +8 -0
  20. package/dist/types/base.js +43 -0
  21. package/dist/types/base.js.map +1 -1
  22. package/dist/validation/index.d.ts +1 -1
  23. package/dist/validation/index.js +40 -0
  24. package/dist/validation/index.js.map +1 -1
  25. package/dist/workflow-builder/connection-utils.js +1 -1
  26. package/dist/workflow-builder/connection-utils.js.map +1 -1
  27. package/dist/workflow-builder/control-flow-builders/split-in-batches.js +2 -0
  28. package/dist/workflow-builder/control-flow-builders/split-in-batches.js.map +1 -1
  29. package/dist/workflow-builder/node-builders/node-builder.js +7 -1
  30. package/dist/workflow-builder/node-builders/node-builder.js.map +1 -1
  31. package/dist/workflow-builder/plugins/serializers/json-serializer.js +2 -0
  32. package/dist/workflow-builder/plugins/serializers/json-serializer.js.map +1 -1
  33. package/dist/workflow-builder/validation-helpers.d.ts +1 -0
  34. package/dist/workflow-builder/validation-helpers.js +7 -0
  35. package/dist/workflow-builder/validation-helpers.js.map +1 -1
  36. package/dist/workflow-builder/workflow-import.js +1 -0
  37. package/dist/workflow-builder/workflow-import.js.map +1 -1
  38. package/dist/workflow-builder.js +8 -2
  39. package/dist/workflow-builder.js.map +1 -1
  40. package/package.json +2 -2
@@ -23,6 +23,10 @@ export interface NodeProperty {
23
23
  show?: Record<string, unknown[]>;
24
24
  hide?: Record<string, unknown[]>;
25
25
  };
26
+ disabledOptions?: {
27
+ show?: Record<string, unknown[]>;
28
+ hide?: Record<string, unknown[]>;
29
+ };
26
30
  typeOptions?: Record<string, unknown>;
27
31
  noDataExpression?: boolean;
28
32
  modes?: Array<{
@@ -102,6 +106,10 @@ export interface DiscriminatedUnionResult {
102
106
  code: string;
103
107
  configTypes: ConfigTypeInfo[];
104
108
  }
109
+ export declare function narrowDisplayOptionsByDisabled(prop: NodeProperty): {
110
+ displayOptions: NodeProperty['displayOptions'];
111
+ fullyDisabled: boolean;
112
+ };
105
113
  export declare function mapPropertyType(prop: NodeProperty, discriminatorContext?: DiscriminatorCombination): string;
106
114
  export declare function extractDiscriminatorCombinations(node: NodeTypeDescription): DiscriminatorCombination[];
107
115
  export declare function getPropertiesForCombination(node: NodeTypeDescription, combination: DiscriminatorCombination): NodeProperty[];
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.discoverSchemasForNode = discoverSchemasForNode;
37
37
  exports.jsonSchemaToTypeScript = jsonSchemaToTypeScript;
38
38
  exports.findSchemaForOperation = findSchemaForOperation;
39
+ exports.narrowDisplayOptionsByDisabled = narrowDisplayOptionsByDisabled;
39
40
  exports.mapPropertyType = mapPropertyType;
40
41
  exports.extractDiscriminatorCombinations = extractDiscriminatorCombinations;
41
42
  exports.getPropertiesForCombination = getPropertiesForCombination;
@@ -87,6 +88,9 @@ const DEV_OUTPUT_PATH = path.resolve(__dirname, '../../dist/node-definitions');
87
88
  const NODES_BASE_DIST = path.resolve(__dirname, '../../../../nodes-base/dist/nodes');
88
89
  const DISCRIMINATOR_FIELDS = ['resource', 'operation', 'mode'];
89
90
  const CUSTOM_API_CALL_KEY = '__CUSTOM_API_CALL__';
91
+ const DISPLAY_ONLY_PROPERTY_TYPES = new Set(['notice', 'curlImport', 'credentials', 'callout']);
92
+ const ICON_TS_TYPE = "{ type: 'icon' | 'emoji'; value: string }";
93
+ const WORKFLOW_SELECTOR_TS_TYPE = "{ __rl: true; mode: 'list' | 'id'; value: string | number; cachedResultName?: string; cachedResultUrl?: string } | Expression<string>";
90
94
  const ASSIGNMENT_TYPE_JSDOC = `/**
91
95
  * Assignment type determines how the value is interpreted.
92
96
  * - string: Direct string value or expression evaluating to string
@@ -533,7 +537,14 @@ function mapNestedPropertyTypeInner(prop, discriminatorContext) {
533
537
  case 'notice':
534
538
  case 'curlImport':
535
539
  case 'credentials':
540
+ case 'callout':
536
541
  return '';
542
+ case 'button':
543
+ return 'string | Expression<string>';
544
+ case 'icon':
545
+ return ICON_TS_TYPE;
546
+ case 'workflowSelector':
547
+ return WORKFLOW_SELECTOR_TS_TYPE;
537
548
  case 'credentialsSelect':
538
549
  return 'string | Expression<string>';
539
550
  default:
@@ -549,10 +560,6 @@ function quotePropertyName(name) {
549
560
  }
550
561
  return name;
551
562
  }
552
- function isPropertyOptional(prop) {
553
- const hasDefault = 'default' in prop && prop.default !== undefined;
554
- return !prop.required || hasDefault;
555
- }
556
563
  function generateNestedPropertyJSDoc(prop, indent, discriminatorContext) {
557
564
  const lines = [];
558
565
  const description = prop.description ?? prop.displayName;
@@ -656,7 +663,7 @@ function generateFixedCollectionType(prop, discriminatorContext) {
656
663
  const groupName = quotePropertyName(group.name);
657
664
  const nestedProps = [];
658
665
  for (const nestedProp of group.values) {
659
- if (['notice', 'curlImport', 'credentials'].includes(nestedProp.type)) {
666
+ if (DISPLAY_ONLY_PROPERTY_TYPES.has(nestedProp.type)) {
660
667
  continue;
661
668
  }
662
669
  const nestedType = mapNestedPropertyType(nestedProp, discriminatorContext);
@@ -668,7 +675,23 @@ function generateFixedCollectionType(prop, discriminatorContext) {
668
675
  }
669
676
  if (nestedProps.length > 0) {
670
677
  const innerType = `{\n${nestedProps.join(';\n')};\n${INDENT.repeat(2)}}`;
671
- const groupType = isMultipleValues ? `Array<${innerType}>` : innerType;
678
+ const minRequired = prop.typeOptions?.minRequiredFields;
679
+ const maxAllowed = prop.typeOptions?.maxAllowedFields;
680
+ const hasMinRequired = typeof minRequired === 'number' && minRequired > 0;
681
+ let groupType;
682
+ if (isMultipleValues) {
683
+ if (hasMinRequired) {
684
+ const requiredHead = Array(minRequired).fill(innerType).join(', ');
685
+ groupType = `[${requiredHead}, ...Array<${innerType}>]`;
686
+ }
687
+ else {
688
+ groupType = `Array<${innerType}>`;
689
+ }
690
+ }
691
+ else {
692
+ groupType = innerType;
693
+ }
694
+ const groupOptional = hasMinRequired ? '' : '?';
672
695
  const groupJsDocLines = [];
673
696
  if (group.displayName || group.description) {
674
697
  const desc = (group.description ?? group.displayName ?? '')
@@ -687,12 +710,24 @@ function generateFixedCollectionType(prop, discriminatorContext) {
687
710
  }
688
711
  groupJsDocLines.push(`${INDENT.repeat(2)} * @builderHint ${safeBuilderHint}`);
689
712
  }
713
+ if (isMultipleValues && hasMinRequired) {
714
+ if (groupJsDocLines.length === 0) {
715
+ groupJsDocLines.push(`${INDENT.repeat(2)}/**`);
716
+ }
717
+ groupJsDocLines.push(`${INDENT.repeat(2)} * @minItems ${minRequired}`);
718
+ }
719
+ if (isMultipleValues && typeof maxAllowed === 'number' && maxAllowed > 0) {
720
+ if (groupJsDocLines.length === 0) {
721
+ groupJsDocLines.push(`${INDENT.repeat(2)}/**`);
722
+ }
723
+ groupJsDocLines.push(`${INDENT.repeat(2)} * @maxItems ${maxAllowed}`);
724
+ }
690
725
  if (groupJsDocLines.length > 0) {
691
726
  groupJsDocLines.push(`${INDENT.repeat(2)} */`);
692
- groups.push(`${groupJsDocLines.join('\n')}\n${INDENT.repeat(2)}${groupName}?: ${groupType}`);
727
+ groups.push(`${groupJsDocLines.join('\n')}\n${INDENT.repeat(2)}${groupName}${groupOptional}: ${groupType}`);
693
728
  }
694
729
  else {
695
- groups.push(`${groupName}?: ${groupType}`);
730
+ groups.push(`${groupName}${groupOptional}: ${groupType}`);
696
731
  }
697
732
  }
698
733
  }
@@ -701,19 +736,71 @@ function generateFixedCollectionType(prop, discriminatorContext) {
701
736
  }
702
737
  return `{\n${INDENT.repeat(2)}${groups.join(`;\n${INDENT.repeat(2)}`)};\n${INDENT}}`;
703
738
  }
739
+ function narrowDisplayOptionsByDisabled(prop) {
740
+ const { displayOptions, disabledOptions } = prop;
741
+ if (!disabledOptions?.show) {
742
+ return { displayOptions, fullyDisabled: false };
743
+ }
744
+ const currentShow = displayOptions?.show;
745
+ const narrowedShow = {};
746
+ const mergedHide = {};
747
+ for (const [key, values] of Object.entries(displayOptions?.hide ?? {})) {
748
+ mergedHide[key] = [...values];
749
+ }
750
+ if (currentShow) {
751
+ for (const [key, values] of Object.entries(currentShow)) {
752
+ const disabledValues = disabledOptions.show[key];
753
+ if (!disabledValues) {
754
+ narrowedShow[key] = values;
755
+ continue;
756
+ }
757
+ const remaining = values.filter((v) => !disabledValues.some((d) => JSON.stringify(d) === JSON.stringify(v)));
758
+ if (remaining.length === 0) {
759
+ return { displayOptions: undefined, fullyDisabled: true };
760
+ }
761
+ narrowedShow[key] = remaining;
762
+ }
763
+ }
764
+ for (const [key, values] of Object.entries(disabledOptions.show)) {
765
+ if (currentShow && key in currentShow)
766
+ continue;
767
+ const existing = mergedHide[key] ?? [];
768
+ const seen = new Set(existing.map((v) => JSON.stringify(v)));
769
+ for (const v of values) {
770
+ if (!seen.has(JSON.stringify(v))) {
771
+ existing.push(v);
772
+ }
773
+ }
774
+ mergedHide[key] = existing;
775
+ }
776
+ const result = {};
777
+ if (Object.keys(narrowedShow).length > 0)
778
+ result.show = narrowedShow;
779
+ if (Object.keys(mergedHide).length > 0)
780
+ result.hide = mergedHide;
781
+ return {
782
+ displayOptions: Object.keys(result).length > 0 ? result : undefined,
783
+ fullyDisabled: false,
784
+ };
785
+ }
704
786
  function mergeCollectionProperties(properties) {
705
787
  const seenProps = new Map();
706
788
  for (const prop of properties) {
707
- if (['notice', 'curlImport', 'credentials'].includes(prop.type)) {
789
+ if (DISPLAY_ONLY_PROPERTY_TYPES.has(prop.type)) {
790
+ continue;
791
+ }
792
+ const { displayOptions: narrowedDisplayOptions, fullyDisabled } = narrowDisplayOptionsByDisabled(prop);
793
+ if (fullyDisabled) {
708
794
  continue;
709
795
  }
710
- if (seenProps.has(prop.name)) {
711
- const existingProp = seenProps.get(prop.name);
712
- if ((prop.type === 'collection' || prop.type === 'fixedCollection') &&
713
- prop.options &&
796
+ const normalizedProp = { ...prop, displayOptions: narrowedDisplayOptions };
797
+ if (seenProps.has(normalizedProp.name)) {
798
+ const existingProp = seenProps.get(normalizedProp.name);
799
+ if ((normalizedProp.type === 'collection' || normalizedProp.type === 'fixedCollection') &&
800
+ normalizedProp.options &&
714
801
  existingProp.options) {
715
802
  const existingOptionNames = new Set(existingProp.options.map((o) => o.name));
716
- for (const opt of prop.options) {
803
+ for (const opt of normalizedProp.options) {
717
804
  if (!existingOptionNames.has(opt.name)) {
718
805
  existingProp.options.push(opt);
719
806
  }
@@ -721,9 +808,9 @@ function mergeCollectionProperties(properties) {
721
808
  }
722
809
  continue;
723
810
  }
724
- seenProps.set(prop.name, {
725
- ...prop,
726
- options: prop.options ? [...prop.options] : undefined,
811
+ seenProps.set(normalizedProp.name, {
812
+ ...normalizedProp,
813
+ options: normalizedProp.options ? [...normalizedProp.options] : undefined,
727
814
  });
728
815
  }
729
816
  return Array.from(seenProps.values());
@@ -738,7 +825,7 @@ function generateCollectionType(prop, discriminatorContext) {
738
825
  continue;
739
826
  }
740
827
  const nestedType = nestedProp.type;
741
- if (['notice', 'curlImport', 'credentials'].includes(nestedType)) {
828
+ if (DISPLAY_ONLY_PROPERTY_TYPES.has(nestedType)) {
742
829
  continue;
743
830
  }
744
831
  const propType = mapNestedPropertyType(nestedProp, discriminatorContext);
@@ -852,7 +939,14 @@ function mapPropertyTypeInner(prop, discriminatorContext) {
852
939
  case 'notice':
853
940
  case 'curlImport':
854
941
  case 'credentials':
942
+ case 'callout':
855
943
  return '';
944
+ case 'button':
945
+ return 'string | Expression<string>';
946
+ case 'icon':
947
+ return ICON_TS_TYPE;
948
+ case 'workflowSelector':
949
+ return WORKFLOW_SELECTOR_TS_TYPE;
856
950
  case 'credentialsSelect':
857
951
  return 'string | Expression<string>';
858
952
  default:
@@ -914,7 +1008,7 @@ function getPropertiesForCombination(node, combination) {
914
1008
  if (DISCRIMINATOR_FIELDS.includes(prop.name)) {
915
1009
  continue;
916
1010
  }
917
- if (['notice', 'curlImport', 'credentials'].includes(prop.type)) {
1011
+ if (DISPLAY_ONLY_PROPERTY_TYPES.has(prop.type)) {
918
1012
  continue;
919
1013
  }
920
1014
  if (prop.displayOptions?.show) {
@@ -1004,7 +1098,7 @@ function generateDiscriminatedUnion(node) {
1004
1098
  lines.push(`export interface ${configName} {`);
1005
1099
  const mergedProps = mergeCollectionProperties(node.properties);
1006
1100
  for (const prop of mergedProps) {
1007
- const propLine = generatePropertyLine(prop, isPropertyOptional(prop));
1101
+ const propLine = generatePropertyLine(prop, (0, generate_zod_schemas_1.isPropertyOptional)(prop));
1008
1102
  if (propLine) {
1009
1103
  lines.push(propLine);
1010
1104
  }
@@ -1046,7 +1140,7 @@ function generateDiscriminatedUnion(node) {
1046
1140
  continue;
1047
1141
  }
1048
1142
  seenNames.add(prop.name);
1049
- const propLine = generatePropertyLine(prop, isPropertyOptional(prop), combo);
1143
+ const propLine = generatePropertyLine(prop, (0, generate_zod_schemas_1.isPropertyOptional)(prop), combo);
1050
1144
  if (propLine) {
1051
1145
  lines.push(propLine);
1052
1146
  }
@@ -1317,7 +1411,7 @@ function generateSharedFile(node, version, _importDepth = 5) {
1317
1411
  lines.push(' */');
1318
1412
  lines.push('');
1319
1413
  lines.push('');
1320
- const outputProps = filteredProperties.filter((p) => !['notice', 'curlImport', 'credentials'].includes(p.type));
1414
+ const outputProps = filteredProperties.filter((p) => !DISPLAY_ONLY_PROPERTY_TYPES.has(p.type));
1321
1415
  const needsFilter = outputProps.some((p) => p.type === 'filter');
1322
1416
  const needsAssignment = outputProps.some((p) => p.type === 'assignmentCollection');
1323
1417
  if (needsFilter || needsAssignment) {
@@ -1454,7 +1548,7 @@ function generateDiscriminatorFile(node, version, combo, props, schema, _importD
1454
1548
  if (seenNames.has(prop.name))
1455
1549
  continue;
1456
1550
  seenNames.add(prop.name);
1457
- const propLine = generatePropertyLine(prop, isPropertyOptional(prop), combo);
1551
+ const propLine = generatePropertyLine(prop, (0, generate_zod_schemas_1.isPropertyOptional)(prop), combo);
1458
1552
  if (propLine) {
1459
1553
  lines.push(propLine);
1460
1554
  }
@@ -1665,7 +1759,7 @@ function generateSingleVersionTypeFile(node, specificVersion) {
1665
1759
  lines.push('');
1666
1760
  const aiInputTypes = extractAIInputTypesFromBuilderHint(node);
1667
1761
  const subnodeConfigTypeName = aiInputTypes.length > 0 ? `${nodeName}${versionSuffix}SubnodeConfig` : undefined;
1668
- const outputProps = filteredProperties.filter((p) => !['notice', 'curlImport', 'credentials'].includes(p.type));
1762
+ const outputProps = filteredProperties.filter((p) => !DISPLAY_ONLY_PROPERTY_TYPES.has(p.type));
1669
1763
  const needsFilter = outputProps.some((p) => p.type === 'filter');
1670
1764
  const needsAssignment = outputProps.some((p) => p.type === 'assignmentCollection');
1671
1765
  if (needsFilter || needsAssignment) {
@@ -1836,7 +1930,7 @@ function generateNodeTypeFile(nodes) {
1836
1930
  lines.push(generateNodeJSDoc(node));
1837
1931
  lines.push('');
1838
1932
  lines.push('');
1839
- const outputProps = nodeArray.flatMap((n) => n.properties.filter((p) => !['notice', 'curlImport', 'credentials'].includes(p.type)));
1933
+ const outputProps = nodeArray.flatMap((n) => n.properties.filter((p) => !DISPLAY_ONLY_PROPERTY_TYPES.has(p.type)));
1840
1934
  const needsFilter = outputProps.some((p) => p.type === 'filter');
1841
1935
  const needsAssignment = outputProps.some((p) => p.type === 'assignmentCollection');
1842
1936
  if (needsFilter || needsAssignment) {
@@ -1937,7 +2031,7 @@ function generateDiscriminatedUnionForEntry(node, nodeName, versionSuffix) {
1937
2031
  lines.push(`export interface ${configName} {`);
1938
2032
  const mergedProps = mergeCollectionProperties(node.properties);
1939
2033
  for (const prop of mergedProps) {
1940
- const propLine = generatePropertyLine(prop, isPropertyOptional(prop));
2034
+ const propLine = generatePropertyLine(prop, (0, generate_zod_schemas_1.isPropertyOptional)(prop));
1941
2035
  if (propLine) {
1942
2036
  lines.push(propLine);
1943
2037
  }
@@ -1998,7 +2092,7 @@ function generateDiscriminatedUnionForEntry(node, nodeName, versionSuffix) {
1998
2092
  continue;
1999
2093
  }
2000
2094
  seenNames.add(prop.name);
2001
- const propLine = generatePropertyLine(prop, isPropertyOptional(prop), combo);
2095
+ const propLine = generatePropertyLine(prop, (0, generate_zod_schemas_1.isPropertyOptional)(prop), combo);
2002
2096
  if (propLine) {
2003
2097
  lines.push(propLine);
2004
2098
  }