-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerateOpenApiProperties.cts
More file actions
129 lines (123 loc) · 3.8 KB
/
Copy pathgenerateOpenApiProperties.cts
File metadata and controls
129 lines (123 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import {
N8NPropertiesBuilder,
N8NPropertiesBuilderConfig,
OperationContext,
OperationsCollector,
} from '@devlikeapro/n8n-openapi-node';
import { OpenAPIV3 } from 'openapi-types';
import * as doc from './lucca-api@2024-11-01.json';
import { INodeProperties } from 'n8n-workflow';
import * as fs from 'node:fs';
import * as path from 'node:path';
const luccaNodeDir = path.join(__dirname, '..', '..', 'nodes', 'Lucca');
const excludedRefParameters = [
'#/components/parameters/if-none-match',
'#/components/parameters/if-match',
'#/components/parameters/accept-encoding',
];
class CustomOperationCollector extends OperationsCollector {
public override parseFields(
operation: OpenAPIV3.OperationObject,
context: OperationContext,
): INodeProperties[] {
// don't really know why, but path headers and in:path parameters are not merged in the operation object we do it here
operation.parameters = [
...(operation.parameters ?? []),
...(context.path.parameters?.filter((param) => {
return !('$ref' in param && excludedRefParameters.includes(param.$ref));
}) ?? []),
];
let fields = super.parseFields(operation, context);
fields = fields.map((field) => {
if (field.type === 'json') {
field.type = 'string';
}
if (!field.required) {
field.default = null;
if (field.routing?.send && field.routing.send.type === 'query') {
// Empty values for query/path/header parameters should not be sent
field.routing.send.value = '={{ $value ?? undefined }}';
}
}
if (field.name === 'include') {
field.default = 'totalCount,links';
field.required = true;
}
return field;
});
if (['POST', 'PUT', 'PATCH'].includes(context.method)) {
fields = fields.filter((field) => field.routing?.send?.type !== 'body');
fields.push({
displayName: `Body`,
type: 'json',
name: 'body',
default: '',
description: 'JSON object containing the request body',
routing: {
send: {
type: 'body',
value: '={{$value}}',
},
},
});
}
return fields;
}
}
const config: N8NPropertiesBuilderConfig = {
OperationsCollector: CustomOperationCollector,
};
const parser = new N8NPropertiesBuilder(doc, config);
const additionalPropertiesByResourceAndOperation: Record<string, INodeProperties[]> = {};
const openApiProperties = parser
.build()
.map((operation) => {
const resourceName = (operation.displayOptions?.show?.resource ?? [null])[0] as string | null;
const operationName = (operation.displayOptions?.show?.operation ?? [null])[0] as string | null;
if (
operation.routing?.send?.type === 'query' &&
!operation.required &&
resourceName &&
operationName
) {
const key = `${resourceName}:${operationName}`;
if (!additionalPropertiesByResourceAndOperation[key]) {
additionalPropertiesByResourceAndOperation[key] = [];
}
additionalPropertiesByResourceAndOperation[key].push({
...operation,
displayOptions: undefined,
});
return null;
}
return operation;
})
.filter((operation): operation is INodeProperties => operation !== null);
// not needed parameter are moved in it own select, as it reduce visual polution.
const parametersOptions: INodeProperties[] = Object.entries(
additionalPropertiesByResourceAndOperation,
).map(([key, value]) => {
const [resource, operation] = key.split(':');
return {
displayName: 'Additional query Parameters',
name: 'parameters',
type: 'collection',
placeholder: 'Add query parameter',
options: value,
displayOptions: {
show: {
resource: [resource],
operation: [operation],
},
},
default: {},
} as INodeProperties;
});
fs.writeFileSync(
path.join(luccaNodeDir, 'parametersOptions.json'),
JSON.stringify(parametersOptions, null, 2),
);
fs.writeFileSync(
path.join(luccaNodeDir, 'openApiProperties.json'),
JSON.stringify(openApiProperties, null, 2),
);