@contrail/cli 3.6.0-alpha-8-alpha.2c2e640 → 3.6.0-alpha-8-alpha.f16d816
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/auth/login.js +7 -5
- package/dist/commands/app/getApiKey.js +2 -2
- package/dist/commands/entities/create.d.ts +1 -0
- package/dist/commands/entities/create.js +10 -4
- package/dist/commands/entities/create.spec.js +4 -0
- package/dist/commands/entities/delete.d.ts +1 -0
- package/dist/commands/entities/delete.js +18 -37
- package/dist/commands/entities/get.d.ts +1 -0
- package/dist/commands/entities/get.js +7 -3
- package/dist/commands/entities/update.d.ts +1 -0
- package/dist/commands/entities/update.js +4 -1
- package/dist/helpers/entities/assortment-items.d.ts +4 -2
- package/dist/helpers/entities/assortment-items.js +4 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ $ npm install -g @contrail/cli
|
|
|
17
17
|
$ contrail COMMAND
|
|
18
18
|
running command...
|
|
19
19
|
$ contrail (--version)
|
|
20
|
-
@contrail/cli/3.6.0-alpha-8-alpha.
|
|
20
|
+
@contrail/cli/3.6.0-alpha-8-alpha.f16d816 linux-x64 node-v24.21.0
|
|
21
21
|
$ contrail --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ contrail COMMAND
|
package/dist/auth/login.js
CHANGED
|
@@ -161,7 +161,7 @@ async function refreshCurrentUserOrg() {
|
|
|
161
161
|
const currentUser = await (0, sdk_1.getCurrentUser)().catch((e) => {
|
|
162
162
|
console.error('error getting current user', e.message);
|
|
163
163
|
if (isExpiredTokenError(e)) {
|
|
164
|
-
console.
|
|
164
|
+
console.error('access token expired; attempting refresh');
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
167
|
throw e;
|
|
@@ -176,7 +176,7 @@ async function refreshCurrentUserOrg() {
|
|
|
176
176
|
apiGateway: config.apiGateway,
|
|
177
177
|
orgSlug: config.orgSlug,
|
|
178
178
|
};
|
|
179
|
-
|
|
179
|
+
(0, sdk_1.setConfig)(sdk_1.Auth.config);
|
|
180
180
|
}
|
|
181
181
|
catch (e) {
|
|
182
182
|
throw Error(`Could not get refresh token: ${e}`);
|
|
@@ -215,9 +215,11 @@ async function requestRefreshedAccessToken(vibeRefreshToken, apiGateway) {
|
|
|
215
215
|
},
|
|
216
216
|
body: JSON.stringify({ refreshToken: vibeRefreshToken }),
|
|
217
217
|
});
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
const data = await response.json();
|
|
219
|
+
if (!response.ok || !data.accessToken) {
|
|
220
|
+
throw new Error(`jwt_refresh returned ${response.status} with no access token`);
|
|
221
|
+
}
|
|
222
|
+
return data.accessToken;
|
|
221
223
|
}
|
|
222
224
|
function getVersionFromPackageJson() {
|
|
223
225
|
// Get the path to the package.json file
|
|
@@ -35,7 +35,7 @@ class GetAPIKeyApp extends basecommand_1.BaseCommand {
|
|
|
35
35
|
},
|
|
36
36
|
];
|
|
37
37
|
const answers = await inquirer_1.default.prompt(questions);
|
|
38
|
-
|
|
38
|
+
this.log(`App API key: (app:${answers.appApiKey})`);
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
41
|
const appFound = installedApps.find((x) => x.app.identifier === this.flags.appIdentifier);
|
|
@@ -43,7 +43,7 @@ class GetAPIKeyApp extends basecommand_1.BaseCommand {
|
|
|
43
43
|
logger_1.default.info('You do not have such an app installed');
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
this.log(`App API key: (app:${appFound.apiKey.apiKey})`);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -23,6 +23,7 @@ export default class CreateEntity extends BaseCommand {
|
|
|
23
23
|
path: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
24
24
|
};
|
|
25
25
|
static strict: boolean;
|
|
26
|
+
init(): Promise<void>;
|
|
26
27
|
run(): Promise<void>;
|
|
27
28
|
}
|
|
28
29
|
export type CreateSummary = {
|
|
@@ -218,8 +218,11 @@ class CreateEntity extends basecommand_1.BaseCommand {
|
|
|
218
218
|
}),
|
|
219
219
|
};
|
|
220
220
|
static strict = false;
|
|
221
|
-
async
|
|
221
|
+
async init() {
|
|
222
222
|
(0, common_1.routeConsoleLogToStderr)();
|
|
223
|
+
await super.init();
|
|
224
|
+
}
|
|
225
|
+
async run() {
|
|
223
226
|
await (0, login_1.authUser)();
|
|
224
227
|
const { flags, argv, args } = await this.parse(CreateEntity);
|
|
225
228
|
const { count, dryRun: isDryRun, inputFile: inputFilename, outputFile: outputFilename, generateValues: shouldGenerateMissingValues, readableIds: shouldUseReadableIds, skipHydrateRelationships, suffix, apiVersion, } = flags;
|
|
@@ -371,8 +374,8 @@ function createEntityWithPopulatedValues(type, typeReferencesCache, objectRefere
|
|
|
371
374
|
// Handle property specifications
|
|
372
375
|
for (const [propertySlug, specifiedValue] of propertySpecificationBySlug.entries()) {
|
|
373
376
|
const correspondingProperty = type.typeProperties.find((prop) => getPropertySlug(prop) === propertySlug);
|
|
374
|
-
if (
|
|
375
|
-
|
|
377
|
+
if (specifiedValue === undefined) {
|
|
378
|
+
continue;
|
|
376
379
|
}
|
|
377
380
|
entity[propertySlug] = castValueToPropertyType(specifiedValue, correspondingProperty?.propertyType || types_1.PropertyType.String);
|
|
378
381
|
}
|
|
@@ -521,6 +524,9 @@ function generateRandomDateString() {
|
|
|
521
524
|
return new Date().toISOString();
|
|
522
525
|
}
|
|
523
526
|
function castValueToPropertyType(value, propertyType) {
|
|
527
|
+
if (Array.isArray(value) && propertyType !== types_1.PropertyType.MultiSelect) {
|
|
528
|
+
return value.map((element) => castValueToPropertyType(element, propertyType));
|
|
529
|
+
}
|
|
524
530
|
switch (propertyType) {
|
|
525
531
|
case types_1.PropertyType.Boolean:
|
|
526
532
|
return value.toString().toLowerCase() === 'true';
|
|
@@ -553,7 +559,7 @@ async function createEntity(entityName, entity, routing = {}) {
|
|
|
553
559
|
const skipHydrateRelationships = SHOULD_SKIP_HYDRATE_RELATIONSHIPS;
|
|
554
560
|
const { suffix, apiVersion } = routing;
|
|
555
561
|
if (entityName === 'assortment-item' && !suffix)
|
|
556
|
-
return (0, entities_1.createAssortmentItem)(entity, { skipHydrateRelationships }); // special case
|
|
562
|
+
return (0, entities_1.createAssortmentItem)(entity, { skipHydrateRelationships, apiVersion }); // special case
|
|
557
563
|
const response = await client.create({
|
|
558
564
|
entityName,
|
|
559
565
|
object: entity,
|
|
@@ -532,6 +532,10 @@ describe('castValueToPropertyType array coercion', () => {
|
|
|
532
532
|
expect(consoleError).toHaveBeenCalledWith(expect.stringContaining('slug=option slug=family'));
|
|
533
533
|
consoleError.mockRestore();
|
|
534
534
|
});
|
|
535
|
+
it('should cast each element of a repeated-key array on scalar property types', () => {
|
|
536
|
+
expect((0, create_1.castValueToPropertyType)(['1', '2'], types_1.PropertyType.Number)).toEqual([1, 2]);
|
|
537
|
+
expect((0, create_1.castValueToPropertyType)(['true', 'false'], types_1.PropertyType.Boolean)).toEqual([true, false]);
|
|
538
|
+
});
|
|
535
539
|
it('should keep commas literal on string properties without warning', () => {
|
|
536
540
|
const consoleError = jest.spyOn(console, 'error').mockImplementation(() => undefined);
|
|
537
541
|
expect((0, create_1.castValueToPropertyType)('my,name', types_1.PropertyType.String)).toBe('my,name');
|
|
@@ -51,8 +51,11 @@ class DeleteEntity extends basecommand_1.BaseCommand {
|
|
|
51
51
|
}),
|
|
52
52
|
};
|
|
53
53
|
static strict = false;
|
|
54
|
-
async
|
|
54
|
+
async init() {
|
|
55
55
|
(0, common_1.routeConsoleLogToStderr)();
|
|
56
|
+
await super.init();
|
|
57
|
+
}
|
|
58
|
+
async run() {
|
|
56
59
|
await (0, login_1.authUser)();
|
|
57
60
|
const { args, flags, argv } = await this.parse(DeleteEntity);
|
|
58
61
|
const { entityName } = args;
|
|
@@ -91,8 +94,8 @@ class DeleteEntity extends basecommand_1.BaseCommand {
|
|
|
91
94
|
console.error('deleted entities:');
|
|
92
95
|
}
|
|
93
96
|
this.log(JSON.stringify(response, null, 2));
|
|
94
|
-
if (response.
|
|
95
|
-
console.error(`${response.
|
|
97
|
+
if (response.failed.length > 0) {
|
|
98
|
+
console.error(`${response.failed.length} of ${ids.length} deletes failed.`);
|
|
96
99
|
process.exitCode = 1;
|
|
97
100
|
}
|
|
98
101
|
}
|
|
@@ -103,54 +106,32 @@ class DeleteEntity extends basecommand_1.BaseCommand {
|
|
|
103
106
|
}
|
|
104
107
|
exports.default = DeleteEntity;
|
|
105
108
|
async function deleteEntityByIds(entityName, ids, routing = {}) {
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
+
const deletedIds = [];
|
|
110
|
+
const notFoundIds = [];
|
|
111
|
+
const failed = [];
|
|
109
112
|
const limit = (0, p_limit_1.default)(10);
|
|
110
113
|
const deletePromises = ids.map((id) => limit(() => deleteEntityById(entityName, id, routing).then((entity) => {
|
|
111
114
|
if (!entity) {
|
|
112
|
-
|
|
113
|
-
return
|
|
115
|
+
notFoundIds.push(id);
|
|
116
|
+
return;
|
|
114
117
|
}
|
|
115
|
-
|
|
116
|
-
return entity;
|
|
118
|
+
deletedIds.push(id);
|
|
117
119
|
}, (error) => {
|
|
118
|
-
if (error.message
|
|
119
|
-
|
|
120
|
+
if (error.message?.includes('not found')) {
|
|
121
|
+
notFoundIds.push(id);
|
|
120
122
|
}
|
|
121
123
|
else {
|
|
122
|
-
|
|
124
|
+
failed.push({ id, error: (0, common_1.sdkErrorMessage)(error) });
|
|
123
125
|
}
|
|
124
|
-
return null;
|
|
125
126
|
})));
|
|
126
127
|
await Promise.all(deletePromises);
|
|
127
|
-
return {
|
|
128
|
-
idsDeleted: Array.from(idsDeleted),
|
|
129
|
-
idsNotFound: Array.from(idsNotFound),
|
|
130
|
-
idsErrored: Array.from(idsErrored),
|
|
131
|
-
};
|
|
128
|
+
return { deletedIds, notFoundIds, failed };
|
|
132
129
|
}
|
|
133
130
|
async function deleteEntityById(entityName, id, routing = {}) {
|
|
134
131
|
const client = new sdk_1.Entities();
|
|
135
132
|
if (IS_DRY_RUN) {
|
|
136
|
-
return client.get({ entityName, id, ignore404: true })
|
|
133
|
+
return client.get({ entityName, id, ignore404: true });
|
|
137
134
|
}
|
|
138
135
|
const { suffix, apiVersion } = routing;
|
|
139
|
-
return client
|
|
140
|
-
.delete({ entityName, id, ignore404: true, suffix, apiVersion })
|
|
141
|
-
.catch(throwIfNot404);
|
|
142
|
-
}
|
|
143
|
-
function throwIfNot404(e) {
|
|
144
|
-
const { statusCode } = parseSDKErrorMessage(e);
|
|
145
|
-
if (statusCode === 404) {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
throw e;
|
|
149
|
-
}
|
|
150
|
-
function parseSDKErrorMessage(e) {
|
|
151
|
-
const parsed = JSON.parse(e.details);
|
|
152
|
-
return {
|
|
153
|
-
statusCode: parsed.statusCode,
|
|
154
|
-
message: parsed.message,
|
|
155
|
-
};
|
|
136
|
+
return client.delete({ entityName, id, ignore404: true, suffix, apiVersion });
|
|
156
137
|
}
|
|
@@ -83,8 +83,11 @@ class GetEntity extends basecommand_1.BaseCommand {
|
|
|
83
83
|
}),
|
|
84
84
|
};
|
|
85
85
|
static strict = false;
|
|
86
|
-
async
|
|
86
|
+
async init() {
|
|
87
87
|
(0, common_1.routeConsoleLogToStderr)();
|
|
88
|
+
await super.init();
|
|
89
|
+
}
|
|
90
|
+
async run() {
|
|
88
91
|
await (0, login_1.authUser)();
|
|
89
92
|
const { args, flags, argv } = await this.parse(GetEntity);
|
|
90
93
|
const { typePath } = args;
|
|
@@ -224,8 +227,9 @@ async function find(entityName, options = {}) {
|
|
|
224
227
|
queryOptions.customParams = { propertySlugs: propertySlugs.join(',') };
|
|
225
228
|
}
|
|
226
229
|
const payload = id ? { id, ...queryOptions } : { criteria, ...queryOptions };
|
|
227
|
-
// a suffix names a specific sub-route
|
|
228
|
-
|
|
230
|
+
// a suffix names a specific sub-route and an id names one entity; both always go
|
|
231
|
+
// through the plain client (batch-fetch only understands criteria)
|
|
232
|
+
if ((0, batchFetch_1.canBatchFetchEntity)(entityName) && !suffix && !id) {
|
|
229
233
|
return (0, batchFetch_1.batchFetch)(entityName, payload);
|
|
230
234
|
}
|
|
231
235
|
else {
|
|
@@ -16,6 +16,7 @@ export default class UpdateEntity extends BaseCommand {
|
|
|
16
16
|
ids: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
|
|
17
17
|
};
|
|
18
18
|
static strict: boolean;
|
|
19
|
+
init(): Promise<void>;
|
|
19
20
|
run(): Promise<void>;
|
|
20
21
|
}
|
|
21
22
|
export type UpdateSummary = {
|
|
@@ -57,8 +57,11 @@ class UpdateEntity extends basecommand_1.BaseCommand {
|
|
|
57
57
|
}),
|
|
58
58
|
};
|
|
59
59
|
static strict = false;
|
|
60
|
-
async
|
|
60
|
+
async init() {
|
|
61
61
|
(0, common_1.routeConsoleLogToStderr)();
|
|
62
|
+
await super.init();
|
|
63
|
+
}
|
|
64
|
+
async run() {
|
|
62
65
|
await (0, login_1.authUser)();
|
|
63
66
|
const { args, argv } = await this.parse(UpdateEntity);
|
|
64
67
|
const { entityName } = args;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Item } from '@contrail/entity-types';
|
|
2
|
+
import { API_VERSION } from '@contrail/sdk';
|
|
2
3
|
export declare function throwIfInvalidAssortmentId(assortmentId: string): Promise<void>;
|
|
3
4
|
export declare function createAssortmentItem(assortmentItem: {
|
|
4
5
|
assortmentId: string;
|
|
5
6
|
itemId: string;
|
|
6
7
|
[key: string]: any;
|
|
7
|
-
},
|
|
8
|
-
skipHydrateRelationships
|
|
8
|
+
}, options?: {
|
|
9
|
+
skipHydrateRelationships?: boolean;
|
|
10
|
+
apiVersion?: API_VERSION;
|
|
9
11
|
}): Promise<any>;
|
|
10
12
|
export declare function findItemsNotInAssortment(assortmentId: string, count?: number): Promise<Item[]>;
|
|
@@ -15,15 +15,17 @@ async function doesAssortmentExistById(id) {
|
|
|
15
15
|
const assortment = await client.get({ entityName: 'assortment', id });
|
|
16
16
|
return !!assortment;
|
|
17
17
|
}
|
|
18
|
-
async function createAssortmentItem(assortmentItem,
|
|
18
|
+
async function createAssortmentItem(assortmentItem, options = {}) {
|
|
19
19
|
const client = new sdk_1.Entities();
|
|
20
20
|
const { assortmentId, itemId } = assortmentItem;
|
|
21
|
+
const { skipHydrateRelationships = false, apiVersion } = options;
|
|
21
22
|
// add item to assortment
|
|
22
23
|
await client.create({
|
|
23
24
|
entityName: 'assortment',
|
|
24
25
|
id: assortmentId,
|
|
25
26
|
relation: 'items',
|
|
26
27
|
object: { itemIds: [itemId] },
|
|
28
|
+
apiVersion,
|
|
27
29
|
});
|
|
28
30
|
// Update assortment item with properties
|
|
29
31
|
const updated = await client.update({
|
|
@@ -31,6 +33,7 @@ async function createAssortmentItem(assortmentItem, { skipHydrateRelationships }
|
|
|
31
33
|
id: `${assortmentId}:${itemId}`,
|
|
32
34
|
object: assortmentItem,
|
|
33
35
|
skipHydrateRelationships,
|
|
36
|
+
apiVersion,
|
|
34
37
|
});
|
|
35
38
|
return updated;
|
|
36
39
|
}
|
package/oclif.manifest.json
CHANGED