@trayio/cdk-cli 5.13.0 → 5.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.
- package/README.md +46 -19
- package/dist/commands/connector/add-dynamic-output-schema.d.ts +16 -0
- package/dist/commands/connector/add-dynamic-output-schema.d.ts.map +1 -0
- package/dist/commands/connector/add-dynamic-output-schema.js +163 -0
- 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/commands/deployment/create.d.ts +1 -0
- package/dist/commands/deployment/create.d.ts.map +1 -1
- package/dist/commands/deployment/get.d.ts +1 -0
- package/dist/commands/deployment/get.d.ts.map +1 -1
- package/dist/commands/namespace/create.d.ts +1 -0
- package/dist/commands/namespace/create.d.ts.map +1 -1
- package/dist/commands/namespace/get.d.ts +1 -0
- package/dist/commands/namespace/get.d.ts.map +1 -1
- package/dist/commands/permissions/add.d.ts +1 -0
- package/dist/commands/permissions/add.d.ts.map +1 -1
- package/dist/commands/permissions/list.d.ts +1 -0
- package/dist/commands/permissions/list.d.ts.map +1 -1
- 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 +68 -1
- package/package.json +8 -8
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.15.0 linux-x64 node-v18.20.8
|
|
23
23
|
$ tray-cdk --help [COMMAND]
|
|
24
24
|
USAGE
|
|
25
25
|
$ tray-cdk COMMAND
|
|
@@ -32,6 +32,7 @@ USAGE
|
|
|
32
32
|
<!-- commands -->
|
|
33
33
|
* [`tray-cdk .`](#tray-cdk-)
|
|
34
34
|
* [`tray-cdk autocomplete [SHELL]`](#tray-cdk-autocomplete-shell)
|
|
35
|
+
* [`tray-cdk connector add-dynamic-output-schema OPERATIONNAME`](#tray-cdk-connector-add-dynamic-output-schema-operationname)
|
|
35
36
|
* [`tray-cdk connector add-operation [OPERATIONNAME] [OPERATIONTYPE]`](#tray-cdk-connector-add-operation-operationname-operationtype)
|
|
36
37
|
* [`tray-cdk connector build`](#tray-cdk-connector-build)
|
|
37
38
|
* [`tray-cdk connector import [OPENAPISPEC] [CONNECTORNAME]`](#tray-cdk-connector-import-openapispec-connectorname)
|
|
@@ -96,6 +97,26 @@ EXAMPLES
|
|
|
96
97
|
|
|
97
98
|
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.0.5/src/commands/autocomplete/index.ts)_
|
|
98
99
|
|
|
100
|
+
## `tray-cdk connector add-dynamic-output-schema OPERATIONNAME`
|
|
101
|
+
|
|
102
|
+
Add a dynamic output schema operation for an existing operation
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
USAGE
|
|
106
|
+
$ tray-cdk connector add-dynamic-output-schema OPERATIONNAME
|
|
107
|
+
|
|
108
|
+
ARGUMENTS
|
|
109
|
+
OPERATIONNAME Name of the parent operation to add dynamic output schema for
|
|
110
|
+
|
|
111
|
+
DESCRIPTION
|
|
112
|
+
Add a dynamic output schema operation for an existing operation
|
|
113
|
+
|
|
114
|
+
EXAMPLES
|
|
115
|
+
$ tray-cdk connector add-dynamic-output-schema get_posts
|
|
116
|
+
|
|
117
|
+
$ tray-cdk connector add-dynamic-output-schema fetch_user_data
|
|
118
|
+
```
|
|
119
|
+
|
|
99
120
|
## `tray-cdk connector add-operation [OPERATIONNAME] [OPERATIONTYPE]`
|
|
100
121
|
|
|
101
122
|
Add an operation to connector project
|
|
@@ -222,12 +243,13 @@ Creates a new deployment for a connector project
|
|
|
222
243
|
|
|
223
244
|
```
|
|
224
245
|
USAGE
|
|
225
|
-
$ tray-cdk deployment create [--us] [--eu] [--ap]
|
|
246
|
+
$ tray-cdk deployment create [--us] [--eu] [--ap] [--ap2]
|
|
226
247
|
|
|
227
248
|
FLAGS
|
|
228
|
-
--ap
|
|
229
|
-
--
|
|
230
|
-
--
|
|
249
|
+
--ap Use the Tray APAC region
|
|
250
|
+
--ap2 Use the Tray APAC 2 region
|
|
251
|
+
--eu Use the Tray EU region
|
|
252
|
+
--us Use the Tray US region
|
|
231
253
|
|
|
232
254
|
DESCRIPTION
|
|
233
255
|
Creates a new deployment for a connector project
|
|
@@ -239,7 +261,7 @@ Retrieves the status of a connector deployment
|
|
|
239
261
|
|
|
240
262
|
```
|
|
241
263
|
USAGE
|
|
242
|
-
$ tray-cdk deployment get [CONNECTORNAME] [CONNECTORVERSION] [UUID] [-t] [--us] [--eu] [--ap]
|
|
264
|
+
$ tray-cdk deployment get [CONNECTORNAME] [CONNECTORVERSION] [UUID] [-t] [--us] [--eu] [--ap] [--ap2]
|
|
243
265
|
|
|
244
266
|
ARGUMENTS
|
|
245
267
|
CONNECTORNAME The name of the connector
|
|
@@ -249,6 +271,7 @@ ARGUMENTS
|
|
|
249
271
|
FLAGS
|
|
250
272
|
-t, --tail Enables the command to run until the deployment is complete with either a success or failure.
|
|
251
273
|
--ap Use the Tray APAC region
|
|
274
|
+
--ap2 Use the Tray APAC 2 region
|
|
252
275
|
--eu Use the Tray EU region
|
|
253
276
|
--us Use the Tray US region
|
|
254
277
|
|
|
@@ -301,16 +324,17 @@ Creates a new connector namespace for your organization
|
|
|
301
324
|
|
|
302
325
|
```
|
|
303
326
|
USAGE
|
|
304
|
-
$ tray-cdk namespace create ORGID NAMESPACE [--us] [--eu] [--ap]
|
|
327
|
+
$ tray-cdk namespace create ORGID NAMESPACE [--us] [--eu] [--ap] [--ap2]
|
|
305
328
|
|
|
306
329
|
ARGUMENTS
|
|
307
330
|
ORGID The ID of the organization for which to create the namespace
|
|
308
331
|
NAMESPACE The name of the namespace to create
|
|
309
332
|
|
|
310
333
|
FLAGS
|
|
311
|
-
--ap
|
|
312
|
-
--
|
|
313
|
-
--
|
|
334
|
+
--ap Use the Tray APAC region
|
|
335
|
+
--ap2 Use the Tray APAC 2 region
|
|
336
|
+
--eu Use the Tray EU region
|
|
337
|
+
--us Use the Tray US region
|
|
314
338
|
|
|
315
339
|
DESCRIPTION
|
|
316
340
|
Creates a new connector namespace for your organization
|
|
@@ -327,15 +351,16 @@ Retrieves the connector namespace for your organization, if one exists
|
|
|
327
351
|
|
|
328
352
|
```
|
|
329
353
|
USAGE
|
|
330
|
-
$ tray-cdk namespace get ORGID [--us] [--eu] [--ap]
|
|
354
|
+
$ tray-cdk namespace get ORGID [--us] [--eu] [--ap] [--ap2]
|
|
331
355
|
|
|
332
356
|
ARGUMENTS
|
|
333
357
|
ORGID The ID of the organization you want to retrieve the namespace for
|
|
334
358
|
|
|
335
359
|
FLAGS
|
|
336
|
-
--ap
|
|
337
|
-
--
|
|
338
|
-
--
|
|
360
|
+
--ap Use the Tray APAC region
|
|
361
|
+
--ap2 Use the Tray APAC 2 region
|
|
362
|
+
--eu Use the Tray EU region
|
|
363
|
+
--us Use the Tray US region
|
|
339
364
|
|
|
340
365
|
DESCRIPTION
|
|
341
366
|
Retrieves the connector namespace for your organization, if one exists
|
|
@@ -352,7 +377,7 @@ Share your connector version with other users in your organization
|
|
|
352
377
|
|
|
353
378
|
```
|
|
354
379
|
USAGE
|
|
355
|
-
$ tray-cdk permissions add [CONNECTORNAME] [CONNECTORVERSION] [-e <value>] [--us] [--eu] [--ap]
|
|
380
|
+
$ tray-cdk permissions add [CONNECTORNAME] [CONNECTORVERSION] [-e <value>] [--us] [--eu] [--ap] [--ap2]
|
|
356
381
|
|
|
357
382
|
ARGUMENTS
|
|
358
383
|
CONNECTORNAME The name of the connector
|
|
@@ -361,6 +386,7 @@ ARGUMENTS
|
|
|
361
386
|
FLAGS
|
|
362
387
|
-e, --email=<value> Share with users by providing a list of emails
|
|
363
388
|
--ap Use the Tray APAC region
|
|
389
|
+
--ap2 Use the Tray APAC 2 region
|
|
364
390
|
--eu Use the Tray EU region
|
|
365
391
|
--us Use the Tray US region
|
|
366
392
|
|
|
@@ -385,16 +411,17 @@ Retrieves a list of emails that have access to a connector
|
|
|
385
411
|
|
|
386
412
|
```
|
|
387
413
|
USAGE
|
|
388
|
-
$ tray-cdk permissions list [CONNECTORNAME] [CONNECTORVERSION] [--us] [--eu] [--ap]
|
|
414
|
+
$ tray-cdk permissions list [CONNECTORNAME] [CONNECTORVERSION] [--us] [--eu] [--ap] [--ap2]
|
|
389
415
|
|
|
390
416
|
ARGUMENTS
|
|
391
417
|
CONNECTORNAME The name of the connector
|
|
392
418
|
CONNECTORVERSION The version of the connector
|
|
393
419
|
|
|
394
420
|
FLAGS
|
|
395
|
-
--ap
|
|
396
|
-
--
|
|
397
|
-
--
|
|
421
|
+
--ap Use the Tray APAC region
|
|
422
|
+
--ap2 Use the Tray APAC 2 region
|
|
423
|
+
--eu Use the Tray EU region
|
|
424
|
+
--us Use the Tray US region
|
|
398
425
|
|
|
399
426
|
DESCRIPTION
|
|
400
427
|
Retrieves a list of emails that have access to a connector
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class AddDynamicOutputSchema extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
operationName: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
private generator;
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
private validateParentOperation;
|
|
11
|
+
private detectAuthConfig;
|
|
12
|
+
private copyInputFromParent;
|
|
13
|
+
private updateParentOperationJson;
|
|
14
|
+
private findSrcDirectory;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=add-dynamic-output-schema.d.ts.map
|
|
@@ -0,0 +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;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"}
|
|
@@ -0,0 +1,163 @@
|
|
|
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
|
+
const core_1 = require("@oclif/core");
|
|
27
|
+
const fse = __importStar(require("fs-extra"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const StringExtensions_1 = require("@trayio/commons/string/StringExtensions");
|
|
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");
|
|
33
|
+
class AddDynamicOutputSchema extends core_1.Command {
|
|
34
|
+
static description = 'Add a dynamic output schema operation for an existing operation';
|
|
35
|
+
static examples = [
|
|
36
|
+
'<%= config.bin %> <%= command.id %> get_posts',
|
|
37
|
+
'<%= config.bin %> <%= command.id %> fetch_user_data',
|
|
38
|
+
];
|
|
39
|
+
static args = {
|
|
40
|
+
operationName: core_1.Args.string({
|
|
41
|
+
name: 'operationName',
|
|
42
|
+
required: true,
|
|
43
|
+
description: 'Name of the parent operation to add dynamic output schema for',
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
generator = new NodeFsGenerator_1.NodeFsGenerator();
|
|
47
|
+
async run() {
|
|
48
|
+
const { args } = await this.parse(AddDynamicOutputSchema);
|
|
49
|
+
const { operationName } = args;
|
|
50
|
+
const currentDirectory = process.cwd();
|
|
51
|
+
const srcDir = this.findSrcDirectory(currentDirectory);
|
|
52
|
+
// Validate parent operation exists
|
|
53
|
+
this.validateParentOperation(srcDir, operationName);
|
|
54
|
+
const parentOperationPath = path.join(srcDir, operationName);
|
|
55
|
+
const parentOperationJsonPath = path.join(parentOperationPath, 'operation.json');
|
|
56
|
+
this.log(`Checking for operation '${operationName}'... ✓`);
|
|
57
|
+
// Check if dynamic output schema operation already exists
|
|
58
|
+
const outputSchemaOpName = `${operationName}_output_schema`;
|
|
59
|
+
const outputSchemaOpPath = path.join(srcDir, outputSchemaOpName);
|
|
60
|
+
if (fse.existsSync(outputSchemaOpPath)) {
|
|
61
|
+
this.error((0, colorizeString_1.error)(`Dynamic output schema operation '${outputSchemaOpName}' already exists!`));
|
|
62
|
+
}
|
|
63
|
+
// Read parent operation.json
|
|
64
|
+
const parentOperationJson = await fse.readJson(parentOperationJsonPath);
|
|
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) {
|
|
117
|
+
const connectorJsonPath = path.join(path.dirname(srcDir), 'connector.json');
|
|
118
|
+
try {
|
|
119
|
+
const connectorJson = await fse.readJson(connectorJsonPath);
|
|
120
|
+
return await auth_detector_1.AuthDetector.detectAuthInfo(srcDir, connectorJson.name);
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
// If we can't read connector.json, use defaults
|
|
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);
|
|
126
|
+
}
|
|
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>;
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
await fse.writeFile(path.join(outputSchemaOpPath, 'input.ts'), inputTsContent);
|
|
143
|
+
this.log(' ✓ Generated input.ts from parent operation');
|
|
144
|
+
}
|
|
145
|
+
async updateParentOperationJson(parentOperationJsonPath, parentOperationJson) {
|
|
146
|
+
const updatedParentJson = {
|
|
147
|
+
...parentOperationJson,
|
|
148
|
+
dynamic_output: true,
|
|
149
|
+
};
|
|
150
|
+
await fse.writeJson(parentOperationJsonPath, updatedParentJson, {
|
|
151
|
+
spaces: 2,
|
|
152
|
+
});
|
|
153
|
+
this.log(' ✓ Updated parent operation.json with dynamic_output: true');
|
|
154
|
+
}
|
|
155
|
+
findSrcDirectory(currentDirectory) {
|
|
156
|
+
const { base } = path.parse(currentDirectory);
|
|
157
|
+
if (base === 'src') {
|
|
158
|
+
return currentDirectory;
|
|
159
|
+
}
|
|
160
|
+
return path.join(currentDirectory, 'src');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.default = AddDynamicOutputSchema;
|
|
@@ -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
|
+
});
|
|
@@ -6,6 +6,7 @@ export default class Create extends Command {
|
|
|
6
6
|
us: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
7
|
eu: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
ap: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
ap2: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
10
|
};
|
|
10
11
|
private regionHandler;
|
|
11
12
|
run(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/deployment/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAM,MAAM,aAAa,CAAC;AAoB1C,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAsD;IAExE,MAAM,CAAC,IAAI,KAAM;IAEjB,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/deployment/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAM,MAAM,aAAa,CAAC;AAoB1C,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAsD;IAExE,MAAM,CAAC,IAAI,KAAM;IAEjB,MAAM,CAAC,KAAK;;;;;MAEV;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEI,GAAG;CAiET"}
|
|
@@ -10,6 +10,7 @@ export default class Get extends Command {
|
|
|
10
10
|
us: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
11
11
|
eu: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
12
12
|
ap: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
13
|
+
ap2: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
13
14
|
tail: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
14
15
|
};
|
|
15
16
|
static examples: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/deployment/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAwBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SAAoD;IAEtE,MAAM,CAAC,IAAI;;;;MAiBT;IAEF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/deployment/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAwBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SAAoD;IAEtE,MAAM,CAAC,IAAI;;;;MAiBT;IAEF,MAAM,CAAC,KAAK;;;;;;MAOV;IAEF,MAAM,CAAC,QAAQ,WAUb;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEF,OAAO,CAAC,6BAA6B,CAkCnC;IAEF,OAAO,CAAC,qBAAqB,CAe3B;IAEI,GAAG;CAsGT"}
|
|
@@ -9,6 +9,7 @@ export default class Create extends Command {
|
|
|
9
9
|
us: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
eu: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
ap: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
ap2: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
};
|
|
13
14
|
static examples: string[];
|
|
14
15
|
private regionHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/namespace/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAevD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SACyC;IAE3D,MAAM,CAAC,IAAI;;;MAYT;IAEF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/namespace/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAevD,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SACyC;IAE3D,MAAM,CAAC,IAAI;;;MAYT;IAEF,MAAM,CAAC,KAAK;;;;;MAEV;IAEF,MAAM,CAAC,QAAQ,WAGb;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEI,GAAG;CAgDT"}
|
|
@@ -8,6 +8,7 @@ export default class Get extends Command {
|
|
|
8
8
|
us: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
eu: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
ap: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
ap2: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
static examples: string[];
|
|
13
14
|
private regionHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/namespace/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAgBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SACwD;IAE1E,MAAM,CAAC,IAAI;;MAOT;IAEF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/namespace/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,aAAa,CAAC;AAgBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SACwD;IAE1E,MAAM,CAAC,IAAI;;MAOT;IAEF,MAAM,CAAC,KAAK;;;;;MAEV;IAEF,MAAM,CAAC,QAAQ,WAGb;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEI,GAAG;CA6CT"}
|
|
@@ -10,6 +10,7 @@ export default class Add extends Command {
|
|
|
10
10
|
us: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
11
11
|
eu: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
12
12
|
ap: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
13
|
+
ap2: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
13
14
|
email: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
14
15
|
};
|
|
15
16
|
private regionHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/permissions/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAa,MAAM,aAAa,CAAC;AAkBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SACoD;IAEtE,MAAM,CAAC,QAAQ,WAQb;IAEF,MAAM,CAAC,IAAI;;;MAWT;IAEF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/permissions/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAa,MAAM,aAAa,CAAC;AAkBvD,MAAM,CAAC,OAAO,OAAO,GAAI,SAAQ,OAAO;IACvC,MAAM,CAAC,WAAW,SACoD;IAEtE,MAAM,CAAC,QAAQ,WAQb;IAEF,MAAM,CAAC,IAAI;;;MAWT;IAEF,MAAM,CAAC,KAAK;;;;;;MAaV;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YAgFnB,kBAAkB;YAkClB,sBAAsB;IAuCpC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,eAAe;CAGvB"}
|
|
@@ -10,6 +10,7 @@ export default class PermissionsList extends Command {
|
|
|
10
10
|
us: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
eu: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
ap: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
ap2: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
};
|
|
14
15
|
private regionHandler;
|
|
15
16
|
run(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/permissions/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAa,MAAM,aAAa,CAAC;AAYvD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IACnD,MAAM,CAAC,WAAW,SAC4C;IAG9D,MAAM,CAAC,QAAQ,WAIb;IAEF,MAAM,CAAC,IAAI;;;MAWT;IAEF,MAAM,CAAC,KAAK
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/permissions/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAa,MAAM,aAAa,CAAC;AAYvD,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IACnD,MAAM,CAAC,WAAW,SAC4C;IAG9D,MAAM,CAAC,QAAQ,WAIb;IAEF,MAAM,CAAC,IAAI;;;MAWT;IAEF,MAAM,CAAC,KAAK;;;;;MAaV;IAEF,OAAO,CAAC,aAAa,CAGnB;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAsDjC"}
|
|
@@ -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
|
@@ -17,6 +17,37 @@
|
|
|
17
17
|
"index.js"
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
|
+
"connector:add-dynamic-output-schema": {
|
|
21
|
+
"aliases": [],
|
|
22
|
+
"args": {
|
|
23
|
+
"operationName": {
|
|
24
|
+
"description": "Name of the parent operation to add dynamic output schema for",
|
|
25
|
+
"name": "operationName",
|
|
26
|
+
"required": true
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"description": "Add a dynamic output schema operation for an existing operation",
|
|
30
|
+
"examples": [
|
|
31
|
+
"<%= config.bin %> <%= command.id %> get_posts",
|
|
32
|
+
"<%= config.bin %> <%= command.id %> fetch_user_data"
|
|
33
|
+
],
|
|
34
|
+
"flags": {},
|
|
35
|
+
"hasDynamicHelp": false,
|
|
36
|
+
"hiddenAliases": [],
|
|
37
|
+
"id": "connector:add-dynamic-output-schema",
|
|
38
|
+
"pluginAlias": "@trayio/cdk-cli",
|
|
39
|
+
"pluginName": "@trayio/cdk-cli",
|
|
40
|
+
"pluginType": "core",
|
|
41
|
+
"strict": true,
|
|
42
|
+
"enableJsonFlag": false,
|
|
43
|
+
"isESM": false,
|
|
44
|
+
"relativePath": [
|
|
45
|
+
"dist",
|
|
46
|
+
"commands",
|
|
47
|
+
"connector",
|
|
48
|
+
"add-dynamic-output-schema.js"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
20
51
|
"connector:add-operation": {
|
|
21
52
|
"aliases": [],
|
|
22
53
|
"args": {
|
|
@@ -360,6 +391,12 @@
|
|
|
360
391
|
"name": "ap",
|
|
361
392
|
"allowNo": false,
|
|
362
393
|
"type": "boolean"
|
|
394
|
+
},
|
|
395
|
+
"ap2": {
|
|
396
|
+
"description": "Use the Tray APAC 2 region",
|
|
397
|
+
"name": "ap2",
|
|
398
|
+
"allowNo": false,
|
|
399
|
+
"type": "boolean"
|
|
363
400
|
}
|
|
364
401
|
},
|
|
365
402
|
"hasDynamicHelp": false,
|
|
@@ -434,6 +471,12 @@
|
|
|
434
471
|
"name": "ap",
|
|
435
472
|
"allowNo": false,
|
|
436
473
|
"type": "boolean"
|
|
474
|
+
},
|
|
475
|
+
"ap2": {
|
|
476
|
+
"description": "Use the Tray APAC 2 region",
|
|
477
|
+
"name": "ap2",
|
|
478
|
+
"allowNo": false,
|
|
479
|
+
"type": "boolean"
|
|
437
480
|
}
|
|
438
481
|
},
|
|
439
482
|
"hasDynamicHelp": false,
|
|
@@ -489,6 +532,12 @@
|
|
|
489
532
|
"name": "ap",
|
|
490
533
|
"allowNo": false,
|
|
491
534
|
"type": "boolean"
|
|
535
|
+
},
|
|
536
|
+
"ap2": {
|
|
537
|
+
"description": "Use the Tray APAC 2 region",
|
|
538
|
+
"name": "ap2",
|
|
539
|
+
"allowNo": false,
|
|
540
|
+
"type": "boolean"
|
|
492
541
|
}
|
|
493
542
|
},
|
|
494
543
|
"hasDynamicHelp": false,
|
|
@@ -539,6 +588,12 @@
|
|
|
539
588
|
"name": "ap",
|
|
540
589
|
"allowNo": false,
|
|
541
590
|
"type": "boolean"
|
|
591
|
+
},
|
|
592
|
+
"ap2": {
|
|
593
|
+
"description": "Use the Tray APAC 2 region",
|
|
594
|
+
"name": "ap2",
|
|
595
|
+
"allowNo": false,
|
|
596
|
+
"type": "boolean"
|
|
542
597
|
}
|
|
543
598
|
},
|
|
544
599
|
"hasDynamicHelp": false,
|
|
@@ -609,6 +664,12 @@
|
|
|
609
664
|
"name": "ap",
|
|
610
665
|
"allowNo": false,
|
|
611
666
|
"type": "boolean"
|
|
667
|
+
},
|
|
668
|
+
"ap2": {
|
|
669
|
+
"description": "Use the Tray APAC 2 region",
|
|
670
|
+
"name": "ap2",
|
|
671
|
+
"allowNo": false,
|
|
672
|
+
"type": "boolean"
|
|
612
673
|
}
|
|
613
674
|
},
|
|
614
675
|
"hasDynamicHelp": false,
|
|
@@ -665,6 +726,12 @@
|
|
|
665
726
|
"name": "ap",
|
|
666
727
|
"allowNo": false,
|
|
667
728
|
"type": "boolean"
|
|
729
|
+
},
|
|
730
|
+
"ap2": {
|
|
731
|
+
"description": "Use the Tray APAC 2 region",
|
|
732
|
+
"name": "ap2",
|
|
733
|
+
"allowNo": false,
|
|
734
|
+
"type": "boolean"
|
|
668
735
|
}
|
|
669
736
|
},
|
|
670
737
|
"hasDynamicHelp": false,
|
|
@@ -684,5 +751,5 @@
|
|
|
684
751
|
]
|
|
685
752
|
}
|
|
686
753
|
},
|
|
687
|
-
"version": "5.
|
|
754
|
+
"version": "5.15.0"
|
|
688
755
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trayio/cdk-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.15.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.15.0",
|
|
26
|
+
"@trayio/cdk-build": "5.15.0",
|
|
27
|
+
"@trayio/cdk-cli-commons": "5.15.0",
|
|
28
|
+
"@trayio/commons": "5.15.0",
|
|
29
|
+
"@trayio/generator": "5.15.0",
|
|
30
|
+
"@trayio/tray-client": "5.15.0",
|
|
31
|
+
"@trayio/tray-openapi": "5.15.0",
|
|
32
32
|
"chalk": "4.1.2",
|
|
33
33
|
"dotenv": "^16.0.0",
|
|
34
34
|
"inquirer": "8.2.6"
|