@trayio/cdk-cli 5.13.0-unstable → 5.14.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 +1 -1
- package/dist/commands/connector/add-dynamic-output-schema.d.ts +5 -0
- package/dist/commands/connector/add-dynamic-output-schema.d.ts.map +1 -1
- package/dist/commands/connector/add-dynamic-output-schema.js +77 -157
- package/dist/commands/connector/add-dynamic-output-schema.unit.test.d.ts +2 -0
- package/dist/commands/connector/add-dynamic-output-schema.unit.test.d.ts.map +1 -0
- package/dist/commands/connector/add-dynamic-output-schema.unit.test.js +335 -0
- package/dist/lib/dynamic-output/auth-detector.d.ts +21 -0
- package/dist/lib/dynamic-output/auth-detector.d.ts.map +1 -0
- package/dist/lib/dynamic-output/auth-detector.js +85 -0
- package/dist/lib/dynamic-output/index.d.ts +2 -0
- package/dist/lib/dynamic-output/index.d.ts.map +1 -0
- package/dist/lib/dynamic-output/index.js +5 -0
- package/dist/templates/dynamic-output-schema-template.zip +0 -0
- package/oclif.manifest.json +1 -1
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ $ npm install -g @trayio/cdk-cli
|
|
|
19
19
|
$ tray-cdk COMMAND
|
|
20
20
|
running command...
|
|
21
21
|
$ tray-cdk (--version|-v)
|
|
22
|
-
@trayio/cdk-cli/5.
|
|
22
|
+
@trayio/cdk-cli/5.14.0 linux-x64 node-v18.20.8
|
|
23
23
|
$ tray-cdk --help [COMMAND]
|
|
24
24
|
USAGE
|
|
25
25
|
$ tray-cdk COMMAND
|
|
@@ -5,7 +5,12 @@ export default class AddDynamicOutputSchema extends Command {
|
|
|
5
5
|
static args: {
|
|
6
6
|
operationName: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
|
+
private generator;
|
|
8
9
|
run(): Promise<void>;
|
|
10
|
+
private validateParentOperation;
|
|
11
|
+
private detectAuthConfig;
|
|
12
|
+
private copyInputFromParent;
|
|
13
|
+
private updateParentOperationJson;
|
|
9
14
|
private findSrcDirectory;
|
|
10
15
|
}
|
|
11
16
|
//# sourceMappingURL=add-dynamic-output-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-dynamic-output-schema.d.ts","sourceRoot":"","sources":["../../../src/commands/connector/add-dynamic-output-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"add-dynamic-output-schema.d.ts","sourceRoot":"","sources":["../../../src/commands/connector/add-dynamic-output-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,aAAa,CAAC;AAW5C,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,OAAO;IAC1D,MAAM,CAAC,WAAW,SACiD;IAEnE,MAAM,CAAC,QAAQ,WAGb;IAEF,MAAM,CAAC,IAAI;;MAOT;IAEF,OAAO,CAAC,SAAS,CAAyB;IAEpC,GAAG;IAsGT,OAAO,CAAC,uBAAuB;YAuBjB,gBAAgB;YAehB,mBAAmB;YA8BnB,yBAAyB;IAcvC,OAAO,CAAC,gBAAgB;CAOxB"}
|
|
@@ -28,6 +28,8 @@ const fse = __importStar(require("fs-extra"));
|
|
|
28
28
|
const path = __importStar(require("path"));
|
|
29
29
|
const StringExtensions_1 = require("@trayio/commons/string/StringExtensions");
|
|
30
30
|
const colorizeString_1 = require("@trayio/cdk-cli-commons/utils/colorizeString");
|
|
31
|
+
const NodeFsGenerator_1 = require("@trayio/generator/generator/NodeFsGenerator");
|
|
32
|
+
const auth_detector_1 = require("../../lib/dynamic-output/auth-detector");
|
|
31
33
|
class AddDynamicOutputSchema extends core_1.Command {
|
|
32
34
|
static description = 'Add a dynamic output schema operation for an existing operation';
|
|
33
35
|
static examples = [
|
|
@@ -41,20 +43,16 @@ class AddDynamicOutputSchema extends core_1.Command {
|
|
|
41
43
|
description: 'Name of the parent operation to add dynamic output schema for',
|
|
42
44
|
}),
|
|
43
45
|
};
|
|
46
|
+
generator = new NodeFsGenerator_1.NodeFsGenerator();
|
|
44
47
|
async run() {
|
|
45
48
|
const { args } = await this.parse(AddDynamicOutputSchema);
|
|
46
49
|
const { operationName } = args;
|
|
47
50
|
const currentDirectory = process.cwd();
|
|
48
51
|
const srcDir = this.findSrcDirectory(currentDirectory);
|
|
49
52
|
// Validate parent operation exists
|
|
53
|
+
this.validateParentOperation(srcDir, operationName);
|
|
50
54
|
const parentOperationPath = path.join(srcDir, operationName);
|
|
51
|
-
if (!fse.existsSync(parentOperationPath)) {
|
|
52
|
-
this.error((0, colorizeString_1.error)(`Operation '${operationName}' not found in src/ directory.\nMake sure you're in the connector root or src/ directory.`));
|
|
53
|
-
}
|
|
54
55
|
const parentOperationJsonPath = path.join(parentOperationPath, 'operation.json');
|
|
55
|
-
if (!fse.existsSync(parentOperationJsonPath)) {
|
|
56
|
-
this.error((0, colorizeString_1.error)(`Operation '${operationName}' exists but missing operation.json file.`));
|
|
57
|
-
}
|
|
58
56
|
this.log(`Checking for operation '${operationName}'... ✓`);
|
|
59
57
|
// Check if dynamic output schema operation already exists
|
|
60
58
|
const outputSchemaOpName = `${operationName}_output_schema`;
|
|
@@ -64,173 +62,95 @@ class AddDynamicOutputSchema extends core_1.Command {
|
|
|
64
62
|
}
|
|
65
63
|
// Read parent operation.json
|
|
66
64
|
const parentOperationJson = await fse.readJson(parentOperationJsonPath);
|
|
67
|
-
//
|
|
65
|
+
// Detect auth configuration
|
|
66
|
+
const authInfo = await this.detectAuthConfig(srcDir);
|
|
67
|
+
this.log(`Creating dynamic output schema operation '${outputSchemaOpName}'...`);
|
|
68
|
+
// Build template values for generator
|
|
69
|
+
const templateValues = {
|
|
70
|
+
operationNameSnakeCase: operationName,
|
|
71
|
+
operationNameTitleCase: StringExtensions_1.StringExtensions.titleCase(operationName),
|
|
72
|
+
operationNamePascalCase: StringExtensions_1.StringExtensions.pascalCase(operationName),
|
|
73
|
+
operationNameCamelCase: StringExtensions_1.StringExtensions.camelCase(operationName),
|
|
74
|
+
outputSchemaOpNameSnakeCase: outputSchemaOpName,
|
|
75
|
+
outputSchemaOpNamePascalCase: StringExtensions_1.StringExtensions.pascalCase(outputSchemaOpName),
|
|
76
|
+
outputSchemaOpNameCamelCase: StringExtensions_1.StringExtensions.camelCase(outputSchemaOpName),
|
|
77
|
+
parentOpNameSnakeCase: operationName,
|
|
78
|
+
parentOpNamePascalCase: StringExtensions_1.StringExtensions.pascalCase(operationName),
|
|
79
|
+
parentOpNameCamelCase: StringExtensions_1.StringExtensions.camelCase(operationName),
|
|
80
|
+
authType: authInfo.authType,
|
|
81
|
+
authFileName: authInfo.authFileName,
|
|
82
|
+
};
|
|
83
|
+
// Generate files from template
|
|
84
|
+
const rootDir = __dirname;
|
|
85
|
+
const templateDir = path.join(rootDir, '..', '..', 'templates');
|
|
86
|
+
const templatePath = path.join(templateDir, 'dynamic-output-schema-template.zip');
|
|
87
|
+
await this.generator.generate(templatePath, srcDir, templateValues)();
|
|
88
|
+
this.log(' ✓ Generated operation files from template');
|
|
89
|
+
// Ensure the output schema operation directory exists
|
|
90
|
+
await fse.ensureDir(outputSchemaOpPath);
|
|
91
|
+
// Manually copy input.ts from parent operation (can't be templated)
|
|
92
|
+
await this.copyInputFromParent(parentOperationPath, outputSchemaOpPath, StringExtensions_1.StringExtensions.pascalCase(operationName), StringExtensions_1.StringExtensions.pascalCase(outputSchemaOpName));
|
|
93
|
+
// Update parent operation.json with dynamic_output: true
|
|
94
|
+
await this.updateParentOperationJson(parentOperationJsonPath, parentOperationJson);
|
|
95
|
+
// Success message with next steps
|
|
96
|
+
this.log('');
|
|
97
|
+
this.log((0, colorizeString_1.success)(`Success! Created dynamic output schema operation: ${outputSchemaOpName}`));
|
|
98
|
+
this.log('');
|
|
99
|
+
this.log('Next steps:');
|
|
100
|
+
this.log(` 1. Edit src/${outputSchemaOpName}/handler.ts`);
|
|
101
|
+
this.log(' 2. Customize the data fetching logic for your use case');
|
|
102
|
+
this.log(' 3. Run "tray-cdk connector build" to build the connector');
|
|
103
|
+
this.log('');
|
|
104
|
+
this.log('Note: Dynamic output is only safe for read-only GET operations!');
|
|
105
|
+
}
|
|
106
|
+
validateParentOperation(srcDir, operationName) {
|
|
107
|
+
const parentOperationPath = path.join(srcDir, operationName);
|
|
108
|
+
if (!fse.existsSync(parentOperationPath)) {
|
|
109
|
+
this.error((0, colorizeString_1.error)(`Operation '${operationName}' not found in src/ directory.\nMake sure you're in the connector root or src/ directory.`));
|
|
110
|
+
}
|
|
111
|
+
const parentOperationJsonPath = path.join(parentOperationPath, 'operation.json');
|
|
112
|
+
if (!fse.existsSync(parentOperationJsonPath)) {
|
|
113
|
+
this.error((0, colorizeString_1.error)(`Operation '${operationName}' exists but missing operation.json file.`));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async detectAuthConfig(srcDir) {
|
|
68
117
|
const connectorJsonPath = path.join(path.dirname(srcDir), 'connector.json');
|
|
69
|
-
let connectorNamePascalCase = 'MyConnector';
|
|
70
|
-
let authFileName = 'Authentication';
|
|
71
|
-
let authType = 'NoAuth';
|
|
72
118
|
try {
|
|
73
119
|
const connectorJson = await fse.readJson(connectorJsonPath);
|
|
74
|
-
|
|
75
|
-
// Check for {ConnectorName}Auth.ts pattern (standard pattern)
|
|
76
|
-
const standardAuthFile = `${connectorNamePascalCase}Auth.ts`;
|
|
77
|
-
const standardAuthPath = path.join(srcDir, standardAuthFile);
|
|
78
|
-
if (fse.existsSync(standardAuthPath)) {
|
|
79
|
-
authFileName = standardAuthFile.replace('.ts', '');
|
|
80
|
-
authType = `${connectorNamePascalCase}Auth`;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
// Fall back to other common patterns
|
|
84
|
-
const authFiles = ['Authentication.ts', 'Auth.ts'];
|
|
85
|
-
const foundAuthFile = authFiles.find((file) => {
|
|
86
|
-
const authPath = path.join(srcDir, file);
|
|
87
|
-
return fse.existsSync(authPath);
|
|
88
|
-
});
|
|
89
|
-
if (foundAuthFile) {
|
|
90
|
-
authFileName = foundAuthFile.replace('.ts', '');
|
|
91
|
-
// Try to read and extract auth type name
|
|
92
|
-
const authContent = await fse.readFile(path.join(srcDir, foundAuthFile), 'utf-8');
|
|
93
|
-
const typeMatch = authContent.match(/export\s+type\s+(\w+)/);
|
|
94
|
-
if (typeMatch) {
|
|
95
|
-
[, authType] = typeMatch;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
120
|
+
return await auth_detector_1.AuthDetector.detectAuthInfo(srcDir, connectorJson.name);
|
|
99
121
|
}
|
|
100
122
|
catch (e) {
|
|
101
123
|
// If we can't read connector.json, use defaults
|
|
102
124
|
this.warn('Could not read connector.json, using default auth type. Auth import may need manual adjustment.');
|
|
125
|
+
return await auth_detector_1.AuthDetector.detectAuthInfo(srcDir);
|
|
103
126
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
.map((word, i) => i === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1))
|
|
118
|
-
.join('');
|
|
119
|
-
// 1. Generate operation.json
|
|
120
|
-
const operationJson = {
|
|
121
|
-
name: outputSchemaOpName,
|
|
122
|
-
title: `${StringExtensions_1.StringExtensions.titleCase(operationName)} Output Schema`,
|
|
123
|
-
description: `Dynamic output schema generator for ${operationName} (private operation)`,
|
|
124
|
-
isPrivate: true,
|
|
125
|
-
};
|
|
126
|
-
await fse.writeJson(path.join(outputSchemaOpPath, 'operation.json'), operationJson, { spaces: 2 });
|
|
127
|
-
this.log(' ✓ Generated operation.json');
|
|
128
|
-
// 2. Generate input.ts (re-export from parent)
|
|
129
|
-
const inputTsContent = `export type { ${parentOpNamePascalCase}Input as ${outputSchemaOpNamePascalCase}Input } from '../${operationName}/input';
|
|
127
|
+
}
|
|
128
|
+
async copyInputFromParent(parentOperationPath, outputSchemaOpPath, parentOpNamePascalCase, outputSchemaOpNamePascalCase) {
|
|
129
|
+
const parentInputPath = path.join(parentOperationPath, 'input.ts');
|
|
130
|
+
let inputTsContent;
|
|
131
|
+
if (fse.existsSync(parentInputPath)) {
|
|
132
|
+
// Read parent input.ts and copy it with renamed types
|
|
133
|
+
const parentInputContent = await fse.readFile(parentInputPath, 'utf-8');
|
|
134
|
+
// Replace the parent type name with the new type name
|
|
135
|
+
inputTsContent = parentInputContent.replace(new RegExp(`\\b${parentOpNamePascalCase}Input\\b`, 'g'), `${outputSchemaOpNamePascalCase}Input`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Fallback: create a simple input type
|
|
139
|
+
inputTsContent = `export type ${outputSchemaOpNamePascalCase}Input = Record<string, any>;
|
|
130
140
|
`;
|
|
141
|
+
}
|
|
131
142
|
await fse.writeFile(path.join(outputSchemaOpPath, 'input.ts'), inputTsContent);
|
|
132
|
-
this.log(' ✓ Generated input.ts');
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
export type ${outputSchemaOpNamePascalCase}Output = DynamicOutput;
|
|
137
|
-
`;
|
|
138
|
-
await fse.writeFile(path.join(outputSchemaOpPath, 'output.ts'), outputTsContent);
|
|
139
|
-
this.log(' ✓ Generated output.ts');
|
|
140
|
-
// 4. Generate handler.ts from template
|
|
141
|
-
const handlerTsContent = `import { OperationHandlerSetup } from '@trayio/cdk-dsl/connector/operation/OperationHandlerSetup';
|
|
142
|
-
import {
|
|
143
|
-
OperationHandlerResult,
|
|
144
|
-
DynamicOutput,
|
|
145
|
-
} from '@trayio/cdk-dsl/connector/operation/OperationHandler';
|
|
146
|
-
import { JsonSchemaIntrospector } from '@trayio/commons/schema/JsonSchemaIntrospector';
|
|
147
|
-
import { ${parentOpNamePascalCase}Input } from '../${operationName}/input';
|
|
148
|
-
import { ${authType} } from '../${authFileName}';
|
|
149
|
-
import { ${parentOpNameCamelCase}Handler } from '../${operationName}/handler';
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Dynamic output schema handler for ${operationName}
|
|
153
|
-
*
|
|
154
|
-
* This handler generates a JSON Schema by introspecting actual API responses.
|
|
155
|
-
* Customize the data-fetching logic below for your specific use case.
|
|
156
|
-
*/
|
|
157
|
-
export const ${outputSchemaOpNameCamelCase}Handler =
|
|
158
|
-
OperationHandlerSetup.configureDynamicOutputHandler<
|
|
159
|
-
${authType},
|
|
160
|
-
${parentOpNamePascalCase}Input
|
|
161
|
-
>((handler) =>
|
|
162
|
-
handler.usingComposite(async (ctx, input, invoke) => {
|
|
163
|
-
try {
|
|
164
|
-
// TODO: Customize this logic for your use case
|
|
165
|
-
|
|
166
|
-
// Option 1: Invoke the main operation (ONLY for read-only GET operations!)
|
|
167
|
-
const result = await invoke(${parentOpNameCamelCase}Handler)(input);
|
|
168
|
-
|
|
169
|
-
// Option 2: Call a metadata/schema endpoint instead
|
|
170
|
-
// const result = await invoke(getSchemaMetadataHandler)(input);
|
|
171
|
-
|
|
172
|
-
// Option 3: Compute schema without API calls
|
|
173
|
-
// const schema = computeSchemaBasedOnInput(input);
|
|
174
|
-
// return OperationHandlerResult.success<DynamicOutput>({ output_schema: schema });
|
|
175
|
-
|
|
176
|
-
if (result.isFailure) {
|
|
177
|
-
// Return generic fallback schema on error
|
|
178
|
-
return OperationHandlerResult.success<DynamicOutput>({
|
|
179
|
-
output_schema: {
|
|
180
|
-
type: 'object',
|
|
181
|
-
additionalProperties: true,
|
|
182
|
-
description: 'Generic schema - operation failed',
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Use the standard JsonSchemaIntrospector utility to convert response to JSON Schema
|
|
188
|
-
const schema = JsonSchemaIntrospector.introspectToJsonSchema(
|
|
189
|
-
result.value,
|
|
190
|
-
{
|
|
191
|
-
maxDepth: 10,
|
|
192
|
-
includeExamples: false,
|
|
193
|
-
strictRequired: true,
|
|
194
|
-
}
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
return OperationHandlerResult.success<DynamicOutput>({
|
|
198
|
-
output_schema: schema,
|
|
199
|
-
});
|
|
200
|
-
} catch (error) {
|
|
201
|
-
// Fallback on any error
|
|
202
|
-
return OperationHandlerResult.success<DynamicOutput>({
|
|
203
|
-
output_schema: {
|
|
204
|
-
type: 'object',
|
|
205
|
-
additionalProperties: true,
|
|
206
|
-
description: 'Fallback schema due to error',
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
);
|
|
212
|
-
`;
|
|
213
|
-
await fse.writeFile(path.join(outputSchemaOpPath, 'handler.ts'), handlerTsContent);
|
|
214
|
-
this.log(' ✓ Generated handler.ts (with JsonSchemaIntrospector template)');
|
|
215
|
-
// 5. Update parent operation.json with isDynamicOutput: true
|
|
143
|
+
this.log(' ✓ Generated input.ts from parent operation');
|
|
144
|
+
}
|
|
145
|
+
async updateParentOperationJson(parentOperationJsonPath, parentOperationJson) {
|
|
216
146
|
const updatedParentJson = {
|
|
217
147
|
...parentOperationJson,
|
|
218
|
-
|
|
148
|
+
dynamic_output: true,
|
|
219
149
|
};
|
|
220
150
|
await fse.writeJson(parentOperationJsonPath, updatedParentJson, {
|
|
221
151
|
spaces: 2,
|
|
222
152
|
});
|
|
223
|
-
this.log(
|
|
224
|
-
// Success message with next steps
|
|
225
|
-
this.log('');
|
|
226
|
-
this.log((0, colorizeString_1.success)(`Success! Created dynamic output schema operation: ${outputSchemaOpName}`));
|
|
227
|
-
this.log('');
|
|
228
|
-
this.log('Next steps:');
|
|
229
|
-
this.log(` 1. Edit src/${outputSchemaOpName}/handler.ts`);
|
|
230
|
-
this.log(' 2. Customize the data fetching logic for your use case');
|
|
231
|
-
this.log(' 3. Run "tray-cdk connector build" to build the connector');
|
|
232
|
-
this.log('');
|
|
233
|
-
this.log('Note: Dynamic output is only safe for read-only GET operations!');
|
|
153
|
+
this.log(' ✓ Updated parent operation.json with dynamic_output: true');
|
|
234
154
|
}
|
|
235
155
|
findSrcDirectory(currentDirectory) {
|
|
236
156
|
const { base } = path.parse(currentDirectory);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-dynamic-output-schema.unit.test.d.ts","sourceRoot":"","sources":["../../../src/commands/connector/add-dynamic-output-schema.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const stdout_stderr_1 = require("stdout-stderr");
|
|
30
|
+
const fse = __importStar(require("fs-extra"));
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const add_dynamic_output_schema_1 = __importDefault(require("./add-dynamic-output-schema"));
|
|
33
|
+
jest.mock('fs-extra');
|
|
34
|
+
describe('AddDynamicOutputSchema', () => {
|
|
35
|
+
const mockFse = fse;
|
|
36
|
+
const operationName = 'get_posts';
|
|
37
|
+
const outputSchemaOpName = 'get_posts_output_schema';
|
|
38
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
39
|
+
const parentOperationPath = path.join(srcDir, operationName);
|
|
40
|
+
const outputSchemaOpPath = path.join(srcDir, outputSchemaOpName);
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
// Default mocks for successful case
|
|
44
|
+
mockFse.existsSync.mockImplementation((filePath) => {
|
|
45
|
+
const pathStr = filePath.toString();
|
|
46
|
+
if (pathStr.includes(operationName) &&
|
|
47
|
+
pathStr.includes('operation.json')) {
|
|
48
|
+
return true; // Parent operation.json exists
|
|
49
|
+
}
|
|
50
|
+
if (pathStr.includes(operationName) &&
|
|
51
|
+
!pathStr.includes('output_schema')) {
|
|
52
|
+
return true; // Parent operation exists
|
|
53
|
+
}
|
|
54
|
+
if (pathStr.includes('output_schema')) {
|
|
55
|
+
return false; // Output schema operation doesn't exist yet
|
|
56
|
+
}
|
|
57
|
+
if (pathStr.includes('connector.json')) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (pathStr.includes('MyConnectorAuth.ts')) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
});
|
|
65
|
+
mockFse.readJson.mockImplementation(async (filePath) => {
|
|
66
|
+
const pathStr = filePath.toString();
|
|
67
|
+
if (pathStr.includes('connector.json')) {
|
|
68
|
+
return { name: 'my_connector' };
|
|
69
|
+
}
|
|
70
|
+
if (pathStr.includes('operation.json')) {
|
|
71
|
+
return {
|
|
72
|
+
name: operationName,
|
|
73
|
+
title: 'Get Posts',
|
|
74
|
+
description: 'Get all posts',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {};
|
|
78
|
+
});
|
|
79
|
+
mockFse.readFile.mockImplementation(async (filePath) => {
|
|
80
|
+
const pathStr = filePath.toString();
|
|
81
|
+
if (pathStr.includes('input.ts')) {
|
|
82
|
+
return `export type GetPostsInput = {
|
|
83
|
+
limit?: number;
|
|
84
|
+
offset?: number;
|
|
85
|
+
};
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
if (pathStr.includes('Auth.ts')) {
|
|
89
|
+
return 'export type MyConnectorAuth = { apiKey: string };';
|
|
90
|
+
}
|
|
91
|
+
return '';
|
|
92
|
+
});
|
|
93
|
+
mockFse.readdir.mockImplementation(async (dirPath) => {
|
|
94
|
+
const pathStr = dirPath.toString();
|
|
95
|
+
if (pathStr.includes('src')) {
|
|
96
|
+
// Mock src directory contents with auth file
|
|
97
|
+
return [
|
|
98
|
+
operationName,
|
|
99
|
+
'MyConnectorAuth.ts',
|
|
100
|
+
'connector.ts',
|
|
101
|
+
'index.ts',
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
return [];
|
|
105
|
+
});
|
|
106
|
+
mockFse.ensureDir.mockResolvedValue(undefined);
|
|
107
|
+
mockFse.writeJson.mockResolvedValue(undefined);
|
|
108
|
+
mockFse.writeFile.mockResolvedValue(undefined);
|
|
109
|
+
});
|
|
110
|
+
afterAll(() => {
|
|
111
|
+
jest.restoreAllMocks();
|
|
112
|
+
});
|
|
113
|
+
describe('successful operation creation', () => {
|
|
114
|
+
it('should create dynamic output schema operation for existing operation', async () => {
|
|
115
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
116
|
+
const mockGenerate = jest
|
|
117
|
+
.fn()
|
|
118
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
119
|
+
command['generator'] = {
|
|
120
|
+
generate: mockGenerate,
|
|
121
|
+
};
|
|
122
|
+
stdout_stderr_1.stdout.start();
|
|
123
|
+
await command.run();
|
|
124
|
+
stdout_stderr_1.stdout.stop();
|
|
125
|
+
// Verify success message
|
|
126
|
+
expect(stdout_stderr_1.stdout.output).toContain(`Success! Created dynamic output schema operation: ${outputSchemaOpName}`);
|
|
127
|
+
// Verify generator was called with correct template and values
|
|
128
|
+
expect(mockGenerate).toHaveBeenCalledWith(expect.stringContaining('dynamic-output-schema-template.zip'), expect.stringContaining('/src'), expect.objectContaining({
|
|
129
|
+
operationNameSnakeCase: operationName,
|
|
130
|
+
outputSchemaOpNameSnakeCase: outputSchemaOpName,
|
|
131
|
+
parentOpNameSnakeCase: operationName,
|
|
132
|
+
authType: 'MyConnectorAuth',
|
|
133
|
+
authFileName: 'MyConnectorAuth',
|
|
134
|
+
}));
|
|
135
|
+
// Verify parent operation.json was updated with dynamic_output: true
|
|
136
|
+
expect(mockFse.writeJson).toHaveBeenCalledWith(path.join(parentOperationPath, 'operation.json'), expect.objectContaining({
|
|
137
|
+
dynamic_output: true,
|
|
138
|
+
}), { spaces: 2 });
|
|
139
|
+
});
|
|
140
|
+
it('should generate correct input.ts by copying and renaming from parent', async () => {
|
|
141
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
142
|
+
const mockGenerate = jest
|
|
143
|
+
.fn()
|
|
144
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
145
|
+
command['generator'] = {
|
|
146
|
+
generate: mockGenerate,
|
|
147
|
+
};
|
|
148
|
+
stdout_stderr_1.stdout.start();
|
|
149
|
+
await command.run();
|
|
150
|
+
stdout_stderr_1.stdout.stop();
|
|
151
|
+
// Verify input.ts was written with renamed types
|
|
152
|
+
expect(mockFse.writeFile).toHaveBeenCalledWith(path.join(outputSchemaOpPath, 'input.ts'), expect.stringContaining('GetPostsOutputSchemaInput'));
|
|
153
|
+
// Verify it doesn't import from parent operation
|
|
154
|
+
const inputCall = mockFse.writeFile.mock.calls.find((call) => call[0].toString().includes('input.ts'));
|
|
155
|
+
expect(inputCall?.[1]).not.toContain(`from '../${operationName}/input'`);
|
|
156
|
+
expect(inputCall?.[1]).toContain('GetPostsOutputSchemaInput');
|
|
157
|
+
});
|
|
158
|
+
it('should handle input.ts fallback when parent input.ts does not exist', async () => {
|
|
159
|
+
mockFse.existsSync.mockImplementation((filePath) => {
|
|
160
|
+
const pathStr = filePath.toString();
|
|
161
|
+
if (pathStr.includes('input.ts')) {
|
|
162
|
+
return false; // Parent input.ts doesn't exist
|
|
163
|
+
}
|
|
164
|
+
if (pathStr.includes(operationName) &&
|
|
165
|
+
pathStr.includes('operation.json')) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
if (pathStr.includes(operationName) &&
|
|
169
|
+
!pathStr.includes('output_schema')) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
if (pathStr.includes('connector.json')) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
});
|
|
177
|
+
mockFse.readdir.mockResolvedValue([
|
|
178
|
+
operationName,
|
|
179
|
+
'MyConnectorAuth.ts',
|
|
180
|
+
'connector.ts',
|
|
181
|
+
]);
|
|
182
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
183
|
+
const mockGenerate = jest
|
|
184
|
+
.fn()
|
|
185
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
186
|
+
command['generator'] = {
|
|
187
|
+
generate: mockGenerate,
|
|
188
|
+
};
|
|
189
|
+
stdout_stderr_1.stdout.start();
|
|
190
|
+
await command.run();
|
|
191
|
+
stdout_stderr_1.stdout.stop();
|
|
192
|
+
// Verify fallback input.ts was created
|
|
193
|
+
const inputCall = mockFse.writeFile.mock.calls.find((call) => call[0].toString().includes('input.ts'));
|
|
194
|
+
expect(inputCall?.[1]).toContain('Record<string, any>');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
describe('error handling', () => {
|
|
198
|
+
it('should error when parent operation does not exist', async () => {
|
|
199
|
+
mockFse.existsSync.mockReturnValue(false);
|
|
200
|
+
mockFse.readdir.mockResolvedValue([]);
|
|
201
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
202
|
+
let errorThrown = false;
|
|
203
|
+
try {
|
|
204
|
+
await command.run();
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
errorThrown = true;
|
|
208
|
+
expect(error.message).toContain(`Operation '${operationName}' not found`);
|
|
209
|
+
}
|
|
210
|
+
expect(errorThrown).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
it('should error when parent operation.json is missing', async () => {
|
|
213
|
+
mockFse.existsSync.mockImplementation((filePath) => {
|
|
214
|
+
const pathStr = filePath.toString();
|
|
215
|
+
if (pathStr.includes('operation.json')) {
|
|
216
|
+
return false; // operation.json doesn't exist
|
|
217
|
+
}
|
|
218
|
+
if (pathStr.includes(operationName)) {
|
|
219
|
+
return true; // but operation folder exists
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
});
|
|
223
|
+
mockFse.readdir.mockResolvedValue([]);
|
|
224
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
225
|
+
let errorThrown = false;
|
|
226
|
+
try {
|
|
227
|
+
await command.run();
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
errorThrown = true;
|
|
231
|
+
expect(error.message).toContain('missing operation.json');
|
|
232
|
+
}
|
|
233
|
+
expect(errorThrown).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
it('should error when dynamic output schema operation already exists', async () => {
|
|
236
|
+
mockFse.existsSync.mockImplementation((filePath) =>
|
|
237
|
+
// Everything exists including the output schema operation
|
|
238
|
+
true);
|
|
239
|
+
mockFse.readdir.mockResolvedValue([]);
|
|
240
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
241
|
+
let errorThrown = false;
|
|
242
|
+
try {
|
|
243
|
+
await command.run();
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
errorThrown = true;
|
|
247
|
+
expect(error.message).toContain('already exists');
|
|
248
|
+
}
|
|
249
|
+
expect(errorThrown).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
it('should warn when connector.json cannot be read', async () => {
|
|
252
|
+
mockFse.readJson.mockImplementation(async (filePath) => {
|
|
253
|
+
const pathStr = filePath.toString();
|
|
254
|
+
if (pathStr.includes('connector.json')) {
|
|
255
|
+
throw new Error('Cannot read connector.json');
|
|
256
|
+
}
|
|
257
|
+
if (pathStr.includes('operation.json')) {
|
|
258
|
+
return {
|
|
259
|
+
name: operationName,
|
|
260
|
+
title: 'Get Posts',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return {};
|
|
264
|
+
});
|
|
265
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
266
|
+
stdout_stderr_1.stdout.start();
|
|
267
|
+
stdout_stderr_1.stderr.start();
|
|
268
|
+
await command.run();
|
|
269
|
+
stdout_stderr_1.stderr.stop();
|
|
270
|
+
stdout_stderr_1.stdout.stop();
|
|
271
|
+
// Should warn but still succeed
|
|
272
|
+
expect(stdout_stderr_1.stderr.output).toContain('Could not read connector.json');
|
|
273
|
+
expect(stdout_stderr_1.stdout.output).toContain('Success!');
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
describe('file detection', () => {
|
|
277
|
+
it('should detect standard {ConnectorName}Auth.ts pattern', async () => {
|
|
278
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
279
|
+
const mockGenerate = jest
|
|
280
|
+
.fn()
|
|
281
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
282
|
+
command['generator'] = {
|
|
283
|
+
generate: mockGenerate,
|
|
284
|
+
};
|
|
285
|
+
stdout_stderr_1.stdout.start();
|
|
286
|
+
await command.run();
|
|
287
|
+
stdout_stderr_1.stdout.stop();
|
|
288
|
+
// Verify auth type was detected and passed to generator
|
|
289
|
+
expect(mockGenerate).toHaveBeenCalledWith(expect.anything(), expect.anything(), expect.objectContaining({
|
|
290
|
+
authType: 'MyConnectorAuth',
|
|
291
|
+
authFileName: 'MyConnectorAuth',
|
|
292
|
+
}));
|
|
293
|
+
});
|
|
294
|
+
it('should handle when in src/ directory', async () => {
|
|
295
|
+
// Mock process.cwd to return src directory
|
|
296
|
+
const originalCwd = process.cwd;
|
|
297
|
+
process.cwd = jest.fn().mockReturnValue(srcDir);
|
|
298
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
299
|
+
const mockGenerate = jest
|
|
300
|
+
.fn()
|
|
301
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
302
|
+
command['generator'] = {
|
|
303
|
+
generate: mockGenerate,
|
|
304
|
+
};
|
|
305
|
+
stdout_stderr_1.stdout.start();
|
|
306
|
+
await command.run();
|
|
307
|
+
stdout_stderr_1.stdout.stop();
|
|
308
|
+
// Verify generator was called with src directory
|
|
309
|
+
expect(mockGenerate).toHaveBeenCalledWith(expect.anything(), srcDir, expect.anything());
|
|
310
|
+
// Restore
|
|
311
|
+
process.cwd = originalCwd;
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
describe('output messages', () => {
|
|
315
|
+
it('should display correct success message and next steps', async () => {
|
|
316
|
+
const command = new add_dynamic_output_schema_1.default([operationName], {});
|
|
317
|
+
const mockGenerate = jest
|
|
318
|
+
.fn()
|
|
319
|
+
.mockImplementation(() => jest.fn().mockResolvedValue(true));
|
|
320
|
+
command['generator'] = {
|
|
321
|
+
generate: mockGenerate,
|
|
322
|
+
};
|
|
323
|
+
stdout_stderr_1.stdout.start();
|
|
324
|
+
await command.run();
|
|
325
|
+
stdout_stderr_1.stdout.stop();
|
|
326
|
+
expect(stdout_stderr_1.stdout.output).toContain('Checking for operation');
|
|
327
|
+
expect(stdout_stderr_1.stdout.output).toContain('Creating dynamic output schema operation');
|
|
328
|
+
expect(stdout_stderr_1.stdout.output).toContain('✓ Generated operation files from template');
|
|
329
|
+
expect(stdout_stderr_1.stdout.output).toContain('✓ Generated input.ts from parent operation');
|
|
330
|
+
expect(stdout_stderr_1.stdout.output).toContain('✓ Updated parent operation.json');
|
|
331
|
+
expect(stdout_stderr_1.stdout.output).toContain('Next steps:');
|
|
332
|
+
expect(stdout_stderr_1.stdout.output).toContain(`Edit src/${outputSchemaOpName}/handler.ts`);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface AuthInfo {
|
|
2
|
+
authFileName: string;
|
|
3
|
+
authType: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Detects the authentication file and type for a connector
|
|
7
|
+
*/
|
|
8
|
+
export declare class AuthDetector {
|
|
9
|
+
/**
|
|
10
|
+
* Detects the auth file and extracts the auth type name
|
|
11
|
+
* @param srcDir - Path to the connector's src directory
|
|
12
|
+
* @param connectorName - Name of the connector from connector.json
|
|
13
|
+
* @returns AuthInfo with file name and type name
|
|
14
|
+
*/
|
|
15
|
+
static detectAuthInfo(srcDir: string, connectorName?: string): Promise<AuthInfo>;
|
|
16
|
+
/**
|
|
17
|
+
* Find a file in a list using case-insensitive matching
|
|
18
|
+
*/
|
|
19
|
+
private static findFileCaseInsensitive;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=auth-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-detector.d.ts","sourceRoot":"","sources":["../../../src/lib/dynamic-output/auth-detector.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,YAAY;IACxB;;;;;OAKG;WACU,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,QAAQ,CAAC;IAkDpB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,uBAAuB;CAQtC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.AuthDetector = void 0;
|
|
27
|
+
const fse = __importStar(require("fs-extra"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const StringExtensions_1 = require("@trayio/commons/string/StringExtensions");
|
|
30
|
+
/**
|
|
31
|
+
* Detects the authentication file and type for a connector
|
|
32
|
+
*/
|
|
33
|
+
class AuthDetector {
|
|
34
|
+
/**
|
|
35
|
+
* Detects the auth file and extracts the auth type name
|
|
36
|
+
* @param srcDir - Path to the connector's src directory
|
|
37
|
+
* @param connectorName - Name of the connector from connector.json
|
|
38
|
+
* @returns AuthInfo with file name and type name
|
|
39
|
+
*/
|
|
40
|
+
static async detectAuthInfo(srcDir, connectorName) {
|
|
41
|
+
let authFileName = 'Authentication';
|
|
42
|
+
let authType = 'NoAuth';
|
|
43
|
+
// Get all files in src directory for case-insensitive matching
|
|
44
|
+
const srcFiles = await fse.readdir(srcDir);
|
|
45
|
+
if (connectorName) {
|
|
46
|
+
const connectorNamePascalCase = StringExtensions_1.StringExtensions.pascalCase(connectorName);
|
|
47
|
+
// Check for {ConnectorName}Auth.ts pattern (standard pattern)
|
|
48
|
+
const standardAuthFile = `${connectorNamePascalCase}Auth.ts`;
|
|
49
|
+
const foundFile = this.findFileCaseInsensitive(srcFiles, standardAuthFile);
|
|
50
|
+
if (foundFile) {
|
|
51
|
+
authFileName = foundFile.replace('.ts', '');
|
|
52
|
+
authType = `${connectorNamePascalCase}Auth`;
|
|
53
|
+
return { authFileName, authType };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Fall back to other common patterns
|
|
57
|
+
const authFiles = ['Authentication.ts', 'Auth.ts'];
|
|
58
|
+
const foundFile = authFiles
|
|
59
|
+
.map((pattern) => this.findFileCaseInsensitive(srcFiles, pattern))
|
|
60
|
+
.find((file) => file !== undefined);
|
|
61
|
+
if (foundFile) {
|
|
62
|
+
authFileName = foundFile.replace('.ts', '');
|
|
63
|
+
const authPath = path.join(srcDir, foundFile);
|
|
64
|
+
// Try to read and extract auth type name
|
|
65
|
+
try {
|
|
66
|
+
const authContent = await fse.readFile(authPath, 'utf-8');
|
|
67
|
+
const typeMatch = authContent.match(/export\s+type\s+(\w+)/);
|
|
68
|
+
if (typeMatch) {
|
|
69
|
+
[, authType] = typeMatch;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
// If we can't read the file, use the default
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { authFileName, authType };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Find a file in a list using case-insensitive matching
|
|
80
|
+
*/
|
|
81
|
+
static findFileCaseInsensitive(files, targetFile) {
|
|
82
|
+
return files.find((file) => file.toLowerCase() === targetFile.toLowerCase());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.AuthDetector = AuthDetector;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/dynamic-output/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthDetector = void 0;
|
|
4
|
+
var auth_detector_1 = require("./auth-detector");
|
|
5
|
+
Object.defineProperty(exports, "AuthDetector", { enumerable: true, get: function () { return auth_detector_1.AuthDetector; } });
|
|
Binary file
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/cdk-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.14.0",
|
|
4
4
|
"description": "A CLI for connector development",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./*": "./dist/*.js"
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"@oclif/plugin-version": "2.0.11",
|
|
23
23
|
"@oclif/plugin-warn-if-update-available": "^3.1.4",
|
|
24
24
|
"@oclif/test": "3.1.12",
|
|
25
|
-
"@trayio/axios": "5.
|
|
26
|
-
"@trayio/cdk-build": "5.
|
|
27
|
-
"@trayio/cdk-cli-commons": "5.
|
|
28
|
-
"@trayio/commons": "5.
|
|
29
|
-
"@trayio/generator": "5.
|
|
30
|
-
"@trayio/tray-client": "5.
|
|
31
|
-
"@trayio/tray-openapi": "5.
|
|
25
|
+
"@trayio/axios": "5.14.0",
|
|
26
|
+
"@trayio/cdk-build": "5.14.0",
|
|
27
|
+
"@trayio/cdk-cli-commons": "5.14.0",
|
|
28
|
+
"@trayio/commons": "5.14.0",
|
|
29
|
+
"@trayio/generator": "5.14.0",
|
|
30
|
+
"@trayio/tray-client": "5.14.0",
|
|
31
|
+
"@trayio/tray-openapi": "5.14.0",
|
|
32
32
|
"chalk": "4.1.2",
|
|
33
33
|
"dotenv": "^16.0.0",
|
|
34
34
|
"inquirer": "8.2.6"
|
|
@@ -92,6 +92,5 @@
|
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@types/inquirer": "8.2.6",
|
|
94
94
|
"oclif": "*"
|
|
95
|
-
}
|
|
96
|
-
"stableVersion": "0.0.0"
|
|
95
|
+
}
|
|
97
96
|
}
|