@unito/integration-cli 0.66.0 → 1.0.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.
@@ -16,6 +16,9 @@ export default class Graph extends BaseCommand<typeof Graph> {
16
16
  'credential-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
17
  'config-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
18
  output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ body: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ 'body-file': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
21
+ yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
22
  };
20
23
  run(): Promise<void>;
21
24
  }
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
4
4
  const crypto_1 = tslib_1.__importDefault(require("crypto"));
5
5
  const fs_1 = tslib_1.__importDefault(require("fs"));
6
6
  const core_1 = require("@oclif/core");
7
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
7
8
  const baseCommand_1 = require("../baseCommand");
8
9
  const errors_1 = require("../errors");
9
10
  const GlobalConfiguration = tslib_1.__importStar(require("../resources/globalConfiguration"));
@@ -11,18 +12,28 @@ const integrations_1 = require("../resources/integrations");
11
12
  const configuration_1 = require("../resources/configuration");
12
13
  const decryption_1 = require("../resources/decryption");
13
14
  const credentials_1 = require("../resources/credentials");
15
+ const METHOD_MAP = {
16
+ getItem: 'GET',
17
+ getCollection: 'GET',
18
+ createItem: 'POST',
19
+ updateItem: 'PATCH',
20
+ deleteItem: 'DELETE',
21
+ };
14
22
  class Graph extends baseCommand_1.BaseCommand {
15
23
  static description = 'Query a running integration graph and print the response';
16
24
  static examples = [
17
- '<%= config.bin %> <%= command.id %> --path=/sobjects/Opportunity/records/abc123',
18
- '<%= config.bin %> <%= command.id %> get --path=/sobjects/Opportunity --port=9201',
25
+ '<%= config.bin %> <%= command.id %> getItem --path=/sobjects/Opportunity/records/abc123',
26
+ '<%= config.bin %> <%= command.id %> getCollection --path=/sobjects/Opportunity --port=9201',
27
+ `<%= config.bin %> <%= command.id %> createItem --path=/sobjects/Task/records --body='{"Name":"New Task"}'`,
28
+ '<%= config.bin %> <%= command.id %> updateItem --path=/sobjects/Task/records/abc123 --body=\'{"Name":"Updated"}\'',
29
+ '<%= config.bin %> <%= command.id %> deleteItem --path=/sobjects/Task/records/abc123',
19
30
  ];
20
31
  static args = {
21
32
  operation: core_1.Args.string({
22
33
  description: 'Operation to perform on the graph path',
23
34
  required: false,
24
- default: 'get',
25
- options: ['get', 'getItem', 'getCollection', 'createItem', 'updateItem', 'deleteItem'],
35
+ default: 'getItem',
36
+ options: ['getItem', 'getCollection', 'createItem', 'updateItem', 'deleteItem'],
26
37
  }),
27
38
  };
28
39
  async catch(error) {
@@ -72,13 +83,32 @@ class Graph extends baseCommand_1.BaseCommand {
72
83
  char: 'o',
73
84
  description: 'Write response body to file instead of stdout',
74
85
  }),
86
+ body: core_1.Flags.string({
87
+ char: 'b',
88
+ description: 'JSON request body for createItem/updateItem operations',
89
+ exclusive: ['body-file'],
90
+ }),
91
+ 'body-file': core_1.Flags.string({
92
+ description: 'Path to a JSON file to use as request body',
93
+ exclusive: ['body'],
94
+ }),
95
+ yes: core_1.Flags.boolean({
96
+ char: 'y',
97
+ description: 'Skip confirmation prompt for destructive operations (deleteItem)',
98
+ default: false,
99
+ }),
75
100
  };
76
101
  async run() {
77
102
  (0, integrations_1.validateIsIntegrationDirectory)();
78
103
  const { args, flags } = await this.parse(Graph);
79
- const operation = args.operation ?? 'get';
80
- if (operation === 'createItem' || operation === 'updateItem' || operation === 'deleteItem') {
81
- this.error(`Operation "${operation}" is not yet implemented`, { exit: 1 });
104
+ const operation = args.operation;
105
+ const method = METHOD_MAP[operation];
106
+ const needsBody = method === 'POST' || method === 'PATCH';
107
+ if (needsBody && !flags.body && !flags['body-file']) {
108
+ this.error('--body or --body-file is required for ' + operation, { exit: 1 });
109
+ }
110
+ if (operation === 'deleteItem' && (flags.body || flags['body-file'])) {
111
+ this.error('--body and --body-file are not supported for deleteItem', { exit: 1 });
82
112
  }
83
113
  const environment = flags.environment ?? GlobalConfiguration.Environment.Production;
84
114
  const configuration = await (0, configuration_1.getConfiguration)(environment, flags['config-path']);
@@ -122,22 +152,65 @@ class Graph extends baseCommand_1.BaseCommand {
122
152
  'X-Unito-Correlation-Id': crypto_1.default.randomUUID(),
123
153
  'Content-Type': 'application/json',
124
154
  };
155
+ let body;
156
+ if (needsBody) {
157
+ if (flags.body) {
158
+ try {
159
+ JSON.parse(flags.body);
160
+ body = flags.body;
161
+ }
162
+ catch {
163
+ this.error('Invalid JSON in --body: ' + flags.body, { exit: 1 });
164
+ }
165
+ }
166
+ else if (flags['body-file']) {
167
+ const raw = await fs_1.default.promises.readFile(flags['body-file'], 'utf8').catch(() => {
168
+ this.error('Could not read --body-file: ' + flags['body-file'], { exit: 1 });
169
+ });
170
+ try {
171
+ JSON.parse(raw);
172
+ body = raw;
173
+ }
174
+ catch {
175
+ this.error('Invalid JSON in --body-file: ' + flags['body-file'], { exit: 1 });
176
+ }
177
+ }
178
+ }
125
179
  const url = `http://localhost:${flags.port}${flags.path}`;
126
- const response = await fetch(url, { headers });
180
+ if (operation === 'deleteItem' && !flags.yes) {
181
+ const { proceed } = await inquirer_1.default.prompt({
182
+ name: 'proceed',
183
+ message: `About to DELETE ${flags.path}. Continue?`,
184
+ type: 'confirm',
185
+ default: false,
186
+ });
187
+ if (!proceed) {
188
+ this.log('Aborted.');
189
+ return;
190
+ }
191
+ }
192
+ const fetchOptions = { method, headers };
193
+ if (body) {
194
+ fetchOptions.body = body;
195
+ }
196
+ const response = await fetch(url, fetchOptions);
127
197
  if (!response.ok) {
128
- const body = await response.json().catch(() => undefined);
129
- if (body !== undefined) {
130
- this.logToStderr(JSON.stringify(body, null, 2));
198
+ const errorBody = await response.json().catch(() => undefined);
199
+ if (errorBody !== undefined) {
200
+ this.logToStderr(JSON.stringify(errorBody, null, 2));
131
201
  }
132
202
  this.error(`HTTP ${response.status} from ${url}`, { exit: response.status });
133
203
  }
134
- const body = (await response.json());
135
- const json = JSON.stringify(body, null, 2);
136
- if (flags.output) {
137
- await fs_1.default.promises.writeFile(flags.output, json, 'utf8');
138
- }
139
- else {
140
- this.log(json);
204
+ const hasContent = response.status !== 204;
205
+ if (hasContent) {
206
+ const responseBody = (await response.json());
207
+ const json = JSON.stringify(responseBody, null, 2);
208
+ if (flags.output) {
209
+ await fs_1.default.promises.writeFile(flags.output, json, 'utf8');
210
+ }
211
+ else {
212
+ this.log(json);
213
+ }
141
214
  }
142
215
  }
143
216
  }
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const fs_1 = tslib_1.__importDefault(require("fs"));
5
5
  const test_1 = require("@oclif/test");
6
+ const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
6
7
  const sinon_1 = tslib_1.__importDefault(require("sinon"));
7
8
  const Configuration = tslib_1.__importStar(require("../../src/resources/configuration"));
8
9
  const Decryption = tslib_1.__importStar(require("../../src/resources/decryption"));
9
10
  const Integrations = tslib_1.__importStar(require("../../src/resources/integrations"));
11
+ const originalReadFile = fs_1.default.promises.readFile.bind(fs_1.default.promises);
10
12
  const MOCK_CONFIG = {
11
13
  name: 'salesforce-v2',
12
14
  testAccounts: {
@@ -141,8 +143,8 @@ describe('graph', () => {
141
143
  json: () => Promise.resolve(MOCK_RESPONSE),
142
144
  }))
143
145
  .stdout()
144
- .command(['graph', 'get', '--path=/sobjects/Opportunity'])
145
- .it('accepts explicit "get" operation arg', ctx => {
146
+ .command(['graph', 'getItem', '--path=/sobjects/Opportunity'])
147
+ .it('accepts explicit "getItem" operation arg', ctx => {
146
148
  (0, test_1.expect)(ctx.stdout).to.contain('"label": "Opportunity"');
147
149
  });
148
150
  test_1.test
@@ -169,15 +171,203 @@ describe('graph', () => {
169
171
  .it('treats "getCollection" as a get operation', ctx => {
170
172
  (0, test_1.expect)(ctx.stdout).to.contain('"label": "Opportunity"');
171
173
  });
172
- for (const op of ['createItem', 'updateItem', 'deleteItem']) {
173
- test_1.test
174
- .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
175
- .command(['graph', op, '--path=/sobjects/Opportunity'])
176
- .catch(err => {
177
- (0, test_1.expect)(err.message).to.contain(`Operation "${op}" is not yet implemented`);
178
- })
179
- .it(`rejects "${op}" as not yet implemented`);
180
- }
174
+ // --- createItem ---
175
+ test_1.test
176
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
177
+ .stub(global, 'fetch', stub => stub.resolves({
178
+ ok: true,
179
+ status: 201,
180
+ json: () => Promise.resolve({ path: '/sobjects/Task/records/new123' }),
181
+ }))
182
+ .stdout()
183
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records', '--body={"Name":"Test Task"}'])
184
+ .it('createItem sends POST with parsed JSON body', ctx => {
185
+ const fetchStub = global.fetch;
186
+ (0, test_1.expect)(fetchStub.calledOnce).to.be.true;
187
+ const [url, options] = fetchStub.firstCall.args;
188
+ (0, test_1.expect)(url).to.equal('http://localhost:9200/sobjects/Task/records');
189
+ (0, test_1.expect)(options.method).to.equal('POST');
190
+ (0, test_1.expect)(JSON.parse(options.body)).to.deep.equal({ Name: 'Test Task' });
191
+ (0, test_1.expect)(ctx.stdout).to.contain('/sobjects/Task/records/new123');
192
+ });
193
+ test_1.test
194
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
195
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records'])
196
+ .catch(err => {
197
+ (0, test_1.expect)(err.message).to.contain('--body or --body-file is required');
198
+ })
199
+ .it('createItem without --body or --body-file errors');
200
+ test_1.test
201
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
202
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records', '--body=not-json'])
203
+ .catch(err => {
204
+ (0, test_1.expect)(err.message).to.contain('Invalid JSON in --body');
205
+ })
206
+ .it('createItem with invalid JSON in --body errors');
207
+ test_1.test
208
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
209
+ .stub(global, 'fetch', stub => stub.resolves({
210
+ ok: true,
211
+ status: 201,
212
+ json: () => Promise.resolve({ path: '/sobjects/Task/records/new456' }),
213
+ }))
214
+ .stub(fs_1.default.promises, 'readFile', stub => stub.callsFake((...args) => {
215
+ if (args[0] === '/tmp/body.json')
216
+ return Promise.resolve('{"Name":"From File"}');
217
+ return originalReadFile(...args);
218
+ }))
219
+ .stdout()
220
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records', '--body-file=/tmp/body.json'])
221
+ .it('--body-file reads and parses file as request body', () => {
222
+ const fetchStub = global.fetch;
223
+ const [, options] = fetchStub.firstCall.args;
224
+ (0, test_1.expect)(options.method).to.equal('POST');
225
+ (0, test_1.expect)(JSON.parse(options.body)).to.deep.equal({ Name: 'From File' });
226
+ });
227
+ test_1.test
228
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
229
+ .stub(fs_1.default.promises, 'readFile', stub => stub.callsFake((...args) => {
230
+ if (args[0] === '/tmp/bad.json')
231
+ return Promise.resolve('not valid json');
232
+ return originalReadFile(...args);
233
+ }))
234
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records', '--body-file=/tmp/bad.json'])
235
+ .catch(err => {
236
+ (0, test_1.expect)(err.message).to.contain('Invalid JSON in --body-file');
237
+ })
238
+ .it('--body-file with invalid JSON errors');
239
+ test_1.test
240
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
241
+ .stub(fs_1.default.promises, 'readFile', stub => stub.callsFake((...args) => {
242
+ if (args[0] === '/tmp/missing.json')
243
+ return Promise.reject(new Error('ENOENT: no such file'));
244
+ return originalReadFile(...args);
245
+ }))
246
+ .command(['graph', 'createItem', '--path=/sobjects/Task/records', '--body-file=/tmp/missing.json'])
247
+ .catch(err => {
248
+ (0, test_1.expect)(err.message).to.contain('Could not read --body-file');
249
+ })
250
+ .it('--body-file with non-existent file errors');
251
+ // --- updateItem ---
252
+ test_1.test
253
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
254
+ .stub(global, 'fetch', stub => stub.resolves({
255
+ ok: true,
256
+ status: 200,
257
+ json: () => Promise.resolve({ path: '/sobjects/Task/records/abc123' }),
258
+ }))
259
+ .stdout()
260
+ .command(['graph', 'updateItem', '--path=/sobjects/Task/records/abc123', '--body={"Name":"Updated"}'])
261
+ .it('updateItem sends PATCH with parsed JSON body', () => {
262
+ const fetchStub = global.fetch;
263
+ const [url, options] = fetchStub.firstCall.args;
264
+ (0, test_1.expect)(url).to.equal('http://localhost:9200/sobjects/Task/records/abc123');
265
+ (0, test_1.expect)(options.method).to.equal('PATCH');
266
+ (0, test_1.expect)(JSON.parse(options.body)).to.deep.equal({ Name: 'Updated' });
267
+ });
268
+ test_1.test
269
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
270
+ .command(['graph', 'updateItem', '--path=/sobjects/Task/records/abc123'])
271
+ .catch(err => {
272
+ (0, test_1.expect)(err.message).to.contain('--body or --body-file is required');
273
+ })
274
+ .it('updateItem without --body or --body-file errors');
275
+ // --- deleteItem ---
276
+ test_1.test
277
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
278
+ .stub(global, 'fetch', stub => stub.resolves({
279
+ ok: true,
280
+ status: 204,
281
+ json: () => Promise.reject(new Error('No body')),
282
+ }))
283
+ .stdout()
284
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123', '--yes'])
285
+ .it('deleteItem sends DELETE with no body and handles 204', ctx => {
286
+ const fetchStub = global.fetch;
287
+ const [url, options] = fetchStub.firstCall.args;
288
+ (0, test_1.expect)(url).to.equal('http://localhost:9200/sobjects/Task/records/abc123');
289
+ (0, test_1.expect)(options.method).to.equal('DELETE');
290
+ (0, test_1.expect)(options.body).to.be.undefined;
291
+ (0, test_1.expect)(ctx.stdout).to.equal('');
292
+ });
293
+ test_1.test
294
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
295
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123', '--body={"x":1}'])
296
+ .catch(err => {
297
+ (0, test_1.expect)(err.message).to.contain('--body and --body-file are not supported for deleteItem');
298
+ })
299
+ .it('deleteItem rejects --body flag');
300
+ test_1.test
301
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
302
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123', '--body-file=/tmp/body.json'])
303
+ .catch(err => {
304
+ (0, test_1.expect)(err.message).to.contain('--body and --body-file are not supported for deleteItem');
305
+ })
306
+ .it('deleteItem rejects --body-file flag');
307
+ // --- deleteItem confirmation prompt ---
308
+ test_1.test
309
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
310
+ .stub(global, 'fetch', stub => stub.resolves({
311
+ ok: true,
312
+ status: 204,
313
+ json: () => Promise.reject(new Error('No body')),
314
+ }))
315
+ .stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
316
+ .stdout()
317
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123'])
318
+ .it('deleteItem prompts for confirmation and proceeds when accepted', () => {
319
+ const promptStub = inquirer_1.default.prompt;
320
+ (0, test_1.expect)(promptStub.calledOnce).to.be.true;
321
+ const [question] = promptStub.firstCall.args;
322
+ (0, test_1.expect)(question.message).to.contain('About to DELETE /sobjects/Task/records/abc123');
323
+ const fetchStub = global.fetch;
324
+ (0, test_1.expect)(fetchStub.calledOnce).to.be.true;
325
+ });
326
+ test_1.test
327
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
328
+ .stub(global, 'fetch', stub => stub.resolves({
329
+ ok: true,
330
+ status: 204,
331
+ json: () => Promise.reject(new Error('No body')),
332
+ }))
333
+ .stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: false }))
334
+ .stdout()
335
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123'])
336
+ .it('deleteItem aborts when confirmation is declined', ctx => {
337
+ (0, test_1.expect)(ctx.stdout).to.contain('Aborted.');
338
+ const fetchStub = global.fetch;
339
+ (0, test_1.expect)(fetchStub.called).to.be.false;
340
+ });
341
+ test_1.test
342
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
343
+ .stub(global, 'fetch', stub => stub.resolves({
344
+ ok: true,
345
+ status: 204,
346
+ json: () => Promise.reject(new Error('No body')),
347
+ }))
348
+ .stdout()
349
+ .command(['graph', 'deleteItem', '--path=/sobjects/Task/records/abc123', '--yes'])
350
+ .it('deleteItem --yes bypasses confirmation prompt', () => {
351
+ const fetchStub = global.fetch;
352
+ (0, test_1.expect)(fetchStub.calledOnce).to.be.true;
353
+ });
354
+ // --- GET ignores body ---
355
+ test_1.test
356
+ .stub(Configuration, 'getConfiguration', stub => stub.resolves(MOCK_CONFIG))
357
+ .stub(global, 'fetch', stub => stub.resolves({
358
+ ok: true,
359
+ status: 200,
360
+ json: () => Promise.resolve(MOCK_RESPONSE),
361
+ }))
362
+ .stdout()
363
+ .command(['graph', 'getItem', '--path=/sobjects/Opportunity', '--body={"ignored":true}'])
364
+ .it('getItem operations ignore --body flag', () => {
365
+ const fetchStub = global.fetch;
366
+ const [, options] = fetchStub.firstCall.args;
367
+ (0, test_1.expect)(options.method).to.equal('GET');
368
+ (0, test_1.expect)(options.body).to.be.undefined;
369
+ });
370
+ // --- invalid operation ---
181
371
  test_1.test
182
372
  .stderr()
183
373
  .command(['graph', 'put', '--path=/sobjects/Opportunity'])
@@ -257,11 +257,10 @@
257
257
  "aliases": [],
258
258
  "args": {
259
259
  "operation": {
260
- "default": "get",
260
+ "default": "getItem",
261
261
  "description": "Operation to perform on the graph path",
262
262
  "name": "operation",
263
263
  "options": [
264
- "get",
265
264
  "getItem",
266
265
  "getCollection",
267
266
  "createItem",
@@ -273,8 +272,11 @@
273
272
  },
274
273
  "description": "Query a running integration graph and print the response",
275
274
  "examples": [
276
- "<%= config.bin %> <%= command.id %> --path=/sobjects/Opportunity/records/abc123",
277
- "<%= config.bin %> <%= command.id %> get --path=/sobjects/Opportunity --port=9201"
275
+ "<%= config.bin %> <%= command.id %> getItem --path=/sobjects/Opportunity/records/abc123",
276
+ "<%= config.bin %> <%= command.id %> getCollection --path=/sobjects/Opportunity --port=9201",
277
+ "<%= config.bin %> <%= command.id %> createItem --path=/sobjects/Task/records --body='{\"Name\":\"New Task\"}'",
278
+ "<%= config.bin %> <%= command.id %> updateItem --path=/sobjects/Task/records/abc123 --body='{\"Name\":\"Updated\"}'",
279
+ "<%= config.bin %> <%= command.id %> deleteItem --path=/sobjects/Task/records/abc123"
278
280
  ],
279
281
  "flags": {
280
282
  "json": {
@@ -360,6 +362,34 @@
360
362
  "hasDynamicHelp": false,
361
363
  "multiple": false,
362
364
  "type": "option"
365
+ },
366
+ "body": {
367
+ "char": "b",
368
+ "description": "JSON request body for createItem/updateItem operations",
369
+ "exclusive": [
370
+ "body-file"
371
+ ],
372
+ "name": "body",
373
+ "hasDynamicHelp": false,
374
+ "multiple": false,
375
+ "type": "option"
376
+ },
377
+ "body-file": {
378
+ "description": "Path to a JSON file to use as request body",
379
+ "exclusive": [
380
+ "body"
381
+ ],
382
+ "name": "body-file",
383
+ "hasDynamicHelp": false,
384
+ "multiple": false,
385
+ "type": "option"
386
+ },
387
+ "yes": {
388
+ "char": "y",
389
+ "description": "Skip confirmation prompt for destructive operations (deleteItem)",
390
+ "name": "yes",
391
+ "allowNo": false,
392
+ "type": "boolean"
363
393
  }
364
394
  },
365
395
  "hasDynamicHelp": false,
@@ -969,5 +999,5 @@
969
999
  ]
970
1000
  }
971
1001
  },
972
- "version": "0.66.0"
1002
+ "version": "1.0.0"
973
1003
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unito/integration-cli",
3
- "version": "0.66.0",
3
+ "version": "1.0.0",
4
4
  "description": "Integration CLI",
5
5
  "bin": {
6
6
  "integration-cli": "./bin/run"