@contrail/cli 3.3.0-alpha → 3.3.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.
Files changed (43) hide show
  1. package/README.md +1 -142
  2. package/dist/api/types.d.ts +0 -35
  3. package/dist/api/types.js +1 -47
  4. package/dist/basecommand.d.ts +1 -3
  5. package/dist/basecommand.js +1 -1
  6. package/dist/commands/app/create.js +15 -0
  7. package/dist/commands/app/init.js +14 -0
  8. package/dist/commands/app/upgrade.js +6 -6
  9. package/dist/common.d.ts +1 -1
  10. package/dist/helpers/app/app-deployer.js +16 -20
  11. package/dist/helpers/app/setup-template.d.ts +2 -0
  12. package/dist/helpers/app/setup-template.js +2 -1
  13. package/dist/helpers/file-helpers.d.ts +0 -1
  14. package/dist/helpers/file-helpers.js +1 -19
  15. package/dist/interfaces.d.ts +2 -9
  16. package/dist/interfaces.js +1 -8
  17. package/dist/templates/typescript/app.yml +1 -0
  18. package/oclif.manifest.json +1 -341
  19. package/package.json +4 -5
  20. package/dist/commands/entities/create.d.ts +0 -37
  21. package/dist/commands/entities/create.js +0 -532
  22. package/dist/commands/entities/create.spec.d.ts +0 -1
  23. package/dist/commands/entities/create.spec.js +0 -514
  24. package/dist/commands/entities/delete.d.ts +0 -16
  25. package/dist/commands/entities/delete.js +0 -103
  26. package/dist/commands/entities/get.d.ts +0 -19
  27. package/dist/commands/entities/get.js +0 -151
  28. package/dist/commands/entities/update.d.ts +0 -17
  29. package/dist/commands/entities/update.js +0 -86
  30. package/dist/helpers/entities/assortment-items.d.ts +0 -10
  31. package/dist/helpers/entities/assortment-items.js +0 -86
  32. package/dist/helpers/entities/batchFetch.d.ts +0 -8
  33. package/dist/helpers/entities/batchFetch.js +0 -41
  34. package/dist/helpers/entities/index.d.ts +0 -3
  35. package/dist/helpers/entities/index.js +0 -6
  36. package/dist/helpers/entities/items.d.ts +0 -10
  37. package/dist/helpers/entities/items.js +0 -84
  38. package/dist/helpers/entities/project-items.d.ts +0 -3
  39. package/dist/helpers/entities/project-items.js +0 -65
  40. package/dist/helpers/propertySpecifications/propertySpecifications.d.ts +0 -26
  41. package/dist/helpers/propertySpecifications/propertySpecifications.js +0 -58
  42. package/dist/helpers/propertySpecifications/propertySpecifications.spec.d.ts +0 -1
  43. package/dist/helpers/propertySpecifications/propertySpecifications.spec.js +0 -266
@@ -1,151 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const fs_1 = tslib_1.__importDefault(require("fs"));
5
- const core_1 = require("@oclif/core");
6
- const basecommand_1 = require("../../basecommand");
7
- const sdk_1 = require("@contrail/sdk");
8
- const login_1 = require("../../auth/login");
9
- const types_1 = require("../../api/types");
10
- const propertySpecifications_1 = require("../../helpers/propertySpecifications/propertySpecifications");
11
- let SHOULD_USE_PAGINATED_FIND = false;
12
- class GetEntity extends basecommand_1.BaseCommand {
13
- static description = '(BETA) Get an entity';
14
- static examples = [`contrail entities get color -- id=123`];
15
- static flags = {
16
- ...basecommand_1.BaseCommand.baseFlags,
17
- outputFile: core_1.Flags.string({
18
- char: 'o',
19
- description: 'File to save the output (optional)',
20
- required: false,
21
- }),
22
- skipHydrateRelationships: core_1.Flags.boolean({
23
- char: 's',
24
- description: 'Skip hydrating relationships when fetching the entity',
25
- required: false,
26
- default: false,
27
- }),
28
- relations: core_1.Flags.string({
29
- char: 'r',
30
- description: 'Comma-separated list of relations to include in the output',
31
- required: false,
32
- }),
33
- propertySlugs: core_1.Flags.string({
34
- char: 'p',
35
- description: 'Comma-separated list of property slugs to include in the output',
36
- required: false,
37
- }),
38
- paginated: core_1.Flags.boolean({
39
- char: 'P',
40
- description: 'If true, fetches all entities in a paginated manner',
41
- required: false,
42
- default: false,
43
- }),
44
- };
45
- static args = {
46
- typePath: core_1.Args.string({
47
- description: 'The name of the entity type to fetch',
48
- required: true,
49
- }),
50
- };
51
- static strict = false;
52
- async run() {
53
- this.log('🚨 This command is in BETA and may change or be removed at any time.');
54
- await (0, login_1.authUser)();
55
- const { args, flags, argv } = await this.parse(GetEntity);
56
- const { typePath } = args;
57
- const { outputFile, propertySlugs, relations: relationString, skipHydrateRelationships, paginated: shouldUsePaginatedFind, } = flags;
58
- SHOULD_USE_PAGINATED_FIND = shouldUsePaginatedFind;
59
- const propertySpecificationArgs = argv
60
- .slice(1, argv.length)
61
- .filter(propertySpecifications_1.isValidPropertySpecification);
62
- const propertySpecBySlug = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(propertySpecificationArgs);
63
- const relations = relationString
64
- ? relationString
65
- .split(',')
66
- .map((r) => r.trim())
67
- .filter(Boolean)
68
- : [];
69
- const propertySlugsArray = propertySlugs
70
- ? propertySlugs
71
- .split(',')
72
- .map((s) => s.trim())
73
- .filter(Boolean)
74
- : [];
75
- try {
76
- const response = await getEntityByTypePath(typePath, propertySpecBySlug, {
77
- skipHydrateRelationships,
78
- relations,
79
- propertySlugs: propertySlugsArray,
80
- });
81
- if (outputFile) {
82
- fs_1.default.writeFileSync(outputFile, JSON.stringify(response, null, 2));
83
- this.log(`Output saved to ${outputFile}`);
84
- }
85
- else {
86
- this.log(JSON.stringify(response, null, 2));
87
- }
88
- }
89
- catch (e) {
90
- this.error(`Error fetching entity: ${e.message}`);
91
- }
92
- }
93
- }
94
- exports.default = GetEntity;
95
- async function getEntityByTypePath(typePath, propertySpec, options = {}) {
96
- const { propertySlugs, relations, skipHydrateRelationships } = options;
97
- const id = propertySpec?.get('id')?.toString() || undefined;
98
- const { root: entityName } = (0, types_1.parseTypePath)(typePath);
99
- let criteria = {};
100
- if (entityName === 'custom-entity' && !id) {
101
- criteria.typePath = typePath;
102
- }
103
- else {
104
- criteria = convertPropertySpecIntoCriteria(propertySpec || new Map());
105
- }
106
- return SHOULD_USE_PAGINATED_FIND
107
- ? paginatedFind(entityName, { skipHydrateRelationships, relations, propertySlugs, criteria })
108
- : find(entityName, { id, skipHydrateRelationships, relations, propertySlugs, criteria });
109
- }
110
- function convertPropertySpecIntoCriteria(propertySpec) {
111
- const criteria = {};
112
- propertySpec.forEach((value, slug) => {
113
- criteria[slug] = value;
114
- });
115
- return criteria;
116
- }
117
- async function find(entityName, options = {}) {
118
- const client = new sdk_1.Entities();
119
- const { criteria, id, propertySlugs, skipHydrateRelationships, relations } = options;
120
- const queryOptions = {
121
- entityName,
122
- skipHydrateRelationships,
123
- relations,
124
- };
125
- if (propertySlugs && propertySlugs.length > 0) {
126
- queryOptions.customParams = { propertySlugs: propertySlugs.join(',') };
127
- }
128
- return id ? client.get({ id, ...queryOptions }) : client.get({ criteria, ...queryOptions });
129
- }
130
- async function paginatedFind(entityName, options = {}) {
131
- const client = new sdk_1.Entities();
132
- const entities = [];
133
- let nextPageKey = undefined;
134
- while (true) {
135
- const response = await client.get({
136
- ...options,
137
- entityName,
138
- apiVersion: sdk_1.API_VERSION.V2,
139
- nextPageKey,
140
- customParams: {
141
- propertySlugs: options.propertySlugs?.join(','),
142
- },
143
- });
144
- nextPageKey = response.nextPageKey;
145
- if (!response.results || response.results?.length === 0) {
146
- break;
147
- }
148
- entities.push(...response.results);
149
- }
150
- return entities;
151
- }
@@ -1,17 +0,0 @@
1
- import { BaseCommand } from '../../basecommand';
2
- export default class UpdateEntity extends BaseCommand {
3
- static description: string;
4
- static examples: string[];
5
- static flags: {
6
- skipHydrateRelationships: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
- dryRun: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
- alwaysConfirmEnv: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
9
- logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
10
- };
11
- static args: {
12
- entityName: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
13
- id: import("@oclif/core/lib/interfaces/parser").Arg<string, Record<string, unknown>>;
14
- };
15
- static strict: boolean;
16
- run(): Promise<void>;
17
- }
@@ -1,86 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const core_1 = require("@oclif/core");
4
- const basecommand_1 = require("../../basecommand");
5
- const sdk_1 = require("@contrail/sdk");
6
- const login_1 = require("../../auth/login");
7
- const propertySpecifications_1 = require("../../helpers/propertySpecifications/propertySpecifications");
8
- class UpdateEntity extends basecommand_1.BaseCommand {
9
- static description = '(BETA) Update an entity';
10
- static examples = ['contrail entities update color 123 -- name=obsidian hex=000000'];
11
- static flags = {
12
- ...basecommand_1.BaseCommand.baseFlags,
13
- skipHydrateRelationships: core_1.Flags.boolean({
14
- char: 's',
15
- description: 'Skip hydrating relationships when updating the entity',
16
- required: false,
17
- default: false,
18
- }),
19
- dryRun: core_1.Flags.boolean({
20
- char: 'd',
21
- description: 'If true, does not create the entity but simulates the creation',
22
- required: false,
23
- default: false,
24
- }),
25
- };
26
- static args = {
27
- entityName: core_1.Args.string({
28
- description: 'The name of the entity type to update',
29
- required: true,
30
- }),
31
- id: core_1.Args.string({
32
- description: 'The unique identifier of the entity',
33
- required: true,
34
- }),
35
- };
36
- static strict = false;
37
- async run() {
38
- this.log('🚨 This command is in BETA and may change or be removed at any time.');
39
- await (0, login_1.authUser)();
40
- const { args, argv } = await this.parse(UpdateEntity);
41
- const { id, entityName } = args;
42
- const { dryRun: isDryRun, skipHydrateRelationships } = this.flags;
43
- const propertySpecArgs = argv.slice(1, argv.length).filter(propertySpecifications_1.isValidPropertySpecification);
44
- const propertySpec = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(propertySpecArgs);
45
- if (propertySpec.size === 0) {
46
- throw new Error('No valid properties provided for update');
47
- }
48
- if (propertySpec.has('id') && propertySpec.get('id') !== id) {
49
- throw new Error(`Provided ID ${propertySpec.get('id')} does not match the entity ID ${id}`);
50
- }
51
- const changes = [...propertySpec.entries()].reduce((acc, [key, value]) => {
52
- if (key === 'id') {
53
- return acc;
54
- }
55
- acc[key] = value;
56
- return acc;
57
- }, {});
58
- try {
59
- const response = isDryRun
60
- ? await mockUpdateById(entityName, id, changes, { skipHydrateRelationships })
61
- : await updateEntityById(entityName, id, changes, { skipHydrateRelationships });
62
- const messagePrefix = isDryRun
63
- ? 'Dry run. Update skipped. Changes would be:'
64
- : 'Entity updated successfully:';
65
- this.log(`${messagePrefix}\n\n${JSON.stringify(response, null, 2)}`);
66
- }
67
- catch (e) {
68
- this.error(`Error fetching entity: ${e.message}`);
69
- }
70
- }
71
- }
72
- exports.default = UpdateEntity;
73
- async function updateEntityById(entityName, id, changes, options = {}) {
74
- const client = new sdk_1.Entities();
75
- const { skipHydrateRelationships } = options;
76
- return client.update({ entityName, id, object: changes, skipHydrateRelationships });
77
- }
78
- async function mockUpdateById(entityName, id, changes, options = {}) {
79
- const client = new sdk_1.Entities();
80
- const { skipHydrateRelationships } = options;
81
- const entity = await client.get({ entityName, id, skipHydrateRelationships });
82
- if (!entity) {
83
- return null;
84
- }
85
- return { ...entity, ...changes };
86
- }
@@ -1,10 +0,0 @@
1
- import { Item } from '@contrail/entity-types';
2
- export declare function throwIfInvalidAssortmentId(assortmentId: string): Promise<void>;
3
- export declare function createAssortmentItem(assortmentItem: {
4
- assortmentId: string;
5
- itemId: string;
6
- [key: string]: any;
7
- }, { skipHydrateRelationships }?: {
8
- skipHydrateRelationships: boolean;
9
- }): Promise<any>;
10
- export declare function findItemsNotInAssortment(assortmentId: string): Promise<Item[]>;
@@ -1,86 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findItemsNotInAssortment = exports.createAssortmentItem = exports.throwIfInvalidAssortmentId = void 0;
4
- const sdk_1 = require("@contrail/sdk");
5
- const batchFetch_1 = require("./batchFetch");
6
- const items_1 = require("./items");
7
- async function throwIfInvalidAssortmentId(assortmentId) {
8
- if (!(await doesAssortmentExistById(assortmentId))) {
9
- throw new Error(`Assortment with ID ${assortmentId} does not exist`);
10
- }
11
- }
12
- exports.throwIfInvalidAssortmentId = throwIfInvalidAssortmentId;
13
- async function doesAssortmentExistById(id) {
14
- const client = new sdk_1.Entities();
15
- const assortment = await client.get({ entityName: 'assortment', id });
16
- return !!assortment;
17
- }
18
- async function createAssortmentItem(assortmentItem, { skipHydrateRelationships } = { skipHydrateRelationships: false }) {
19
- const client = new sdk_1.Entities();
20
- const { assortmentId, itemId } = assortmentItem;
21
- // add item to assortment
22
- await client.create({
23
- entityName: 'assortment',
24
- id: assortmentId,
25
- relation: 'items',
26
- object: { itemIds: [itemId] },
27
- });
28
- // Update assortment item with properties
29
- const updated = await client.update({
30
- entityName: 'assortment-item',
31
- id: `${assortmentId}:${itemId}`,
32
- object: assortmentItem,
33
- skipHydrateRelationships,
34
- });
35
- return updated;
36
- }
37
- exports.createAssortmentItem = createAssortmentItem;
38
- // Methods to find an item not in the assortment
39
- const ASSORTMENT_ITEMS_CACHE_BY_ASSORTMENT_ID = new Map();
40
- const ASSORTMENT_ITEMS_CACHE_BY_ITEM_ID = new Map();
41
- async function cacheAssortmentItemsByAssortmentId(assortmentId) {
42
- if (!assortmentId) {
43
- throw new Error('Assortment ID is required to cache assortment items');
44
- }
45
- if (ASSORTMENT_ITEMS_CACHE_BY_ASSORTMENT_ID.has(assortmentId)) {
46
- return; // Already cached
47
- }
48
- const assortmentItems = await (0, batchFetch_1.batchFetch)('assortment-item', {
49
- criteria: { assortmentId },
50
- customParams: { propertySlugs: 'id,assortmentId,itemId' },
51
- });
52
- ASSORTMENT_ITEMS_CACHE_BY_ASSORTMENT_ID.set(assortmentId, assortmentItems);
53
- assortmentItems.forEach((item) => {
54
- if (!ASSORTMENT_ITEMS_CACHE_BY_ITEM_ID.has(item.itemId)) {
55
- ASSORTMENT_ITEMS_CACHE_BY_ITEM_ID.set(item.itemId, []);
56
- }
57
- ASSORTMENT_ITEMS_CACHE_BY_ITEM_ID.get(item.itemId).push(item);
58
- });
59
- }
60
- async function getAssortmentItemsByAssortmentId(assortmentId) {
61
- if (!assortmentId) {
62
- throw new Error('Assortment ID is required to get assortment items');
63
- }
64
- await cacheAssortmentItemsByAssortmentId(assortmentId);
65
- const assortmentItems = ASSORTMENT_ITEMS_CACHE_BY_ASSORTMENT_ID.get(assortmentId);
66
- if (!assortmentItems) {
67
- throw new Error(`No assortment items found for assortment ID ${assortmentId}`);
68
- }
69
- return assortmentItems;
70
- }
71
- async function findItemsNotInAssortment(assortmentId) {
72
- if (!assortmentId) {
73
- throw new Error('Assortment ID is required to find items not in assortment');
74
- }
75
- const [assortmentItemsInAssortment, allItems] = await Promise.all([
76
- getAssortmentItemsByAssortmentId(assortmentId),
77
- (0, items_1.getAllItems)(),
78
- ]);
79
- const assortmentItemIds = new Set(assortmentItemsInAssortment.map((ai) => ai.itemId));
80
- const itemsNotInAssortment = allItems.filter((item) => !assortmentItemIds.has(item.id));
81
- if (itemsNotInAssortment.length === 0) {
82
- throw new Error(`All items are already in assortment ${assortmentId}`);
83
- }
84
- return itemsNotInAssortment.sort((a, b) => a.id.localeCompare(b.id)); // sorting ensures consistent order of response
85
- }
86
- exports.findItemsNotInAssortment = findItemsNotInAssortment;
@@ -1,8 +0,0 @@
1
- import { AssortmentItem, Item, ProjectItem } from '@contrail/entity-types';
2
- import { EntitiesClientGetOptions } from '@contrail/sdk';
3
- export interface BatchFetchableEntityMap {
4
- item: Item;
5
- 'project-item': ProjectItem;
6
- 'assortment-item': AssortmentItem;
7
- }
8
- export declare function batchFetch<K extends keyof BatchFetchableEntityMap>(entityName: K, options: EntitiesClientGetOptions): Promise<BatchFetchableEntityMap[K][]>;
@@ -1,41 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.batchFetch = void 0;
4
- const sdk_1 = require("@contrail/sdk");
5
- const util_1 = require("@contrail/util");
6
- async function batchFetch(entityName, options) {
7
- const response = await requestBatchFetch(entityName, options);
8
- return parseBatchFetchResponse(response);
9
- }
10
- exports.batchFetch = batchFetch;
11
- async function requestBatchFetch(entityName, options) {
12
- const client = new sdk_1.Entities();
13
- // NOTE: There is probably a helper somewhere else that manages this conversion
14
- const optionsClone = { ...options };
15
- if (optionsClone.criteria) {
16
- optionsClone.where = optionsClone.criteria;
17
- }
18
- return client.create({
19
- entityName: entityName,
20
- suffix: 'batch-fetch',
21
- object: optionsClone,
22
- });
23
- }
24
- async function parseBatchFetchResponse(response) {
25
- if ('results' in response) {
26
- return response.results;
27
- }
28
- else if ('resultsCompressedString' in response) {
29
- const compressedString = response.resultsCompressedString;
30
- const jsonData = (0, util_1.decompressFromString)(compressedString);
31
- return jsonData;
32
- }
33
- else if ('resultsDownloadUrl' in response) {
34
- const downloadUrl = response.resultsDownloadUrl;
35
- const data = await fetch(downloadUrl).then((res) => res.json());
36
- return data;
37
- }
38
- else {
39
- throw new Error('Invalid batch fetch response format');
40
- }
41
- }
@@ -1,3 +0,0 @@
1
- export * from './assortment-items';
2
- export * from './items';
3
- export * from './project-items';
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./assortment-items"), exports);
5
- tslib_1.__exportStar(require("./items"), exports);
6
- tslib_1.__exportStar(require("./project-items"), exports);
@@ -1,10 +0,0 @@
1
- import { Item } from '@contrail/entity-types';
2
- export declare function throwIfInvalidItemId(itemId: string): Promise<void>;
3
- export type SparseItem = Pick<Item, 'id' | 'familyId' | 'roles' | 'name'>;
4
- export declare function getAllItemsUsingCacheFallback(): Promise<SparseItem[]>;
5
- export declare function getAllItems(): Promise<SparseItem[]>;
6
- export declare function getItemFamilies(): Promise<SparseItem[] | undefined>;
7
- export declare function getFamilyName(item: SparseItem): Promise<string[] | undefined>;
8
- export declare const Roles: readonly ["option", "family"];
9
- export type Role = (typeof Roles)[number];
10
- export declare function throwIfInvalidItemLevel(role: string): asserts role is Role;
@@ -1,84 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.throwIfInvalidItemLevel = exports.Roles = exports.getFamilyName = exports.getItemFamilies = exports.getAllItems = exports.getAllItemsUsingCacheFallback = exports.throwIfInvalidItemId = void 0;
4
- const sdk_1 = require("@contrail/sdk");
5
- async function throwIfInvalidItemId(itemId) {
6
- if (!(await doesItemExistById(itemId))) {
7
- throw new Error(`Item with ID ${itemId} does not exist`);
8
- }
9
- }
10
- exports.throwIfInvalidItemId = throwIfInvalidItemId;
11
- async function doesItemExistById(id) {
12
- const client = new sdk_1.Entities();
13
- const item = await client.get({ entityName: 'item', id });
14
- return !!item;
15
- }
16
- const ITEMS_CACHE_BY_ID = new Map();
17
- async function getAllItemsUsingCacheFallback() {
18
- if (ITEMS_CACHE_BY_ID.size > 0) {
19
- return Array.from(ITEMS_CACHE_BY_ID.values());
20
- }
21
- const items = await getAllItems();
22
- items.forEach((item) => {
23
- ITEMS_CACHE_BY_ID.set(item.id, item);
24
- });
25
- return items;
26
- }
27
- exports.getAllItemsUsingCacheFallback = getAllItemsUsingCacheFallback;
28
- async function getAllItems() {
29
- const client = new sdk_1.Entities();
30
- const MAX_ITEMS = 100000;
31
- // paginate to get all items
32
- // Note: This will only return the first 100 assortments by default.
33
- const items = [];
34
- let nextPageKey = undefined;
35
- while (true) {
36
- const response = await client.get({
37
- entityName: 'item',
38
- apiVersion: sdk_1.API_VERSION.V2,
39
- // customParams: { propertySlugs: 'id,familyId,roles,name' }, // not compatible with V2 for some reason
40
- nextPageKey,
41
- });
42
- nextPageKey = response.nextPageKey;
43
- if (response.results.length === 0) {
44
- break; // No more assortments to fetch
45
- }
46
- items.push(...response.results);
47
- if (items.length >= MAX_ITEMS) {
48
- console.warn(`Reached maximum item limit of ${MAX_ITEMS}. Some items may not be included.`);
49
- break; // Stop if we reach the maximum limit
50
- }
51
- }
52
- return items;
53
- }
54
- exports.getAllItems = getAllItems;
55
- async function getItemFamilies() {
56
- const allItems = await getAllItemsUsingCacheFallback();
57
- const allItemFamiles = allItems.filter(({ roles }) => roles.includes('family'));
58
- return allItemFamiles;
59
- }
60
- exports.getItemFamilies = getItemFamilies;
61
- async function getFamilyName(item) {
62
- if (!item.roles.includes('option')) {
63
- return undefined;
64
- }
65
- if (!item.familyId) {
66
- return undefined;
67
- }
68
- await ensureItemCacheIsPopulated();
69
- const family = ITEMS_CACHE_BY_ID.get(item.familyId);
70
- return family ? [family.name] : ['placeholder']; // placeholder if family not found
71
- }
72
- exports.getFamilyName = getFamilyName;
73
- async function ensureItemCacheIsPopulated() {
74
- if (ITEMS_CACHE_BY_ID.size === 0) {
75
- await getAllItemsUsingCacheFallback();
76
- }
77
- }
78
- exports.Roles = ['option', 'family'];
79
- function throwIfInvalidItemLevel(role) {
80
- if (!exports.Roles.includes(role)) {
81
- throw new Error(`Invalid role: ${role}. Valid roles are: ${exports.Roles.join(', ')}`);
82
- }
83
- }
84
- exports.throwIfInvalidItemLevel = throwIfInvalidItemLevel;
@@ -1,3 +0,0 @@
1
- import { Item } from '@contrail/entity-types';
2
- export declare function throwIfInvalidProjectId(projectId: string): Promise<void>;
3
- export declare function findItemsNotInProject(projectId: string): Promise<Item[]>;
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findItemsNotInProject = exports.throwIfInvalidProjectId = void 0;
4
- const sdk_1 = require("@contrail/sdk");
5
- const batchFetch_1 = require("./batchFetch");
6
- const items_1 = require("./items");
7
- const PROJECT_ITEMS_CACHE_BY_PROJECT_ID = new Map();
8
- const PROJECT_ITEMS_CACHE_BY_ITEM_ID = new Map();
9
- async function throwIfInvalidProjectId(projectId) {
10
- if (!(await doesProjectExistById(projectId))) {
11
- throw new Error(`Project with ID ${projectId} does not exist`);
12
- }
13
- }
14
- exports.throwIfInvalidProjectId = throwIfInvalidProjectId;
15
- async function doesProjectExistById(id) {
16
- const client = new sdk_1.Entities();
17
- const project = await client
18
- .get({
19
- entityName: 'project',
20
- id,
21
- customParams: { propertySlugs: 'id' },
22
- })
23
- .catch((e) => {
24
- console.error(e);
25
- return null; // Return null if project does not exist
26
- });
27
- return !!project;
28
- }
29
- async function cacheProjectItemsByProjectId(projectId) {
30
- if (PROJECT_ITEMS_CACHE_BY_PROJECT_ID.has(projectId)) {
31
- return; // Already cached
32
- }
33
- const projectItems = await (0, batchFetch_1.batchFetch)('project-item', {
34
- criteria: { projectId },
35
- customParams: { propertySlugs: 'id,projectId,assortmentId' },
36
- });
37
- PROJECT_ITEMS_CACHE_BY_PROJECT_ID.set(projectId, projectItems);
38
- projectItems.forEach((item) => {
39
- if (!PROJECT_ITEMS_CACHE_BY_ITEM_ID.has(item.itemId)) {
40
- PROJECT_ITEMS_CACHE_BY_ITEM_ID.set(item.itemId, []);
41
- }
42
- PROJECT_ITEMS_CACHE_BY_ITEM_ID.get(item.itemId).push(item);
43
- });
44
- }
45
- async function getProjectItemsByProjectId(projectId) {
46
- await cacheProjectItemsByProjectId(projectId);
47
- const projectItems = PROJECT_ITEMS_CACHE_BY_PROJECT_ID.get(projectId);
48
- if (!projectItems) {
49
- throw new Error(`No project items found for project ID ${projectId}`);
50
- }
51
- return projectItems;
52
- }
53
- async function findItemsNotInProject(projectId) {
54
- const [projectItemsInProject, allItems] = await Promise.all([
55
- getProjectItemsByProjectId(projectId),
56
- (0, items_1.getAllItems)(),
57
- ]);
58
- const projectItemIds = new Set(projectItemsInProject.map((item) => item.itemId));
59
- const itemsNotInProject = allItems.filter((item) => !projectItemIds.has(item.id));
60
- if (itemsNotInProject.length === 0) {
61
- throw new Error(`All items are already in project ${projectId}`);
62
- }
63
- return itemsNotInProject.sort((a, b) => a.id.localeCompare(b.id)); // sorting ensures consistent order of response
64
- }
65
- exports.findItemsNotInProject = findItemsNotInProject;
@@ -1,26 +0,0 @@
1
- /**
2
- * Property Specification
3
- *
4
- * Property Specifications is an argument pattern used to express that
5
- * a specific property has a specific value. In GET requests, this is used
6
- * to specify the query parameters. In PUT requests, this is used to
7
- * specify the properties to update.
8
- *
9
- * Each follows the format: slug=value
10
- *
11
- * It is typically used as the argv in a command.
12
- *
13
- * Examples:
14
- *
15
- * contrail entities get color -- id=123
16
- * contrail entities update color 123 -- name=obsidian hex=000000
17
- */
18
- export type PropertySpecification = {
19
- slug: string;
20
- value: string;
21
- };
22
- export type PropertySpecificationBySlug = Map<string, string | number | string[] | number[]>;
23
- export type PropertySpecificationString = `${string}=${string}`;
24
- export declare function parsePropertySpecification(spec: PropertySpecificationString): PropertySpecification;
25
- export declare function parsePropertySpecificationsIntoMap(propertySpecifications: PropertySpecificationString[]): PropertySpecificationBySlug;
26
- export declare function isValidPropertySpecification(maybeSpec: string): maybeSpec is PropertySpecificationString;
@@ -1,58 +0,0 @@
1
- "use strict";
2
- /**
3
- * Property Specification
4
- *
5
- * Property Specifications is an argument pattern used to express that
6
- * a specific property has a specific value. In GET requests, this is used
7
- * to specify the query parameters. In PUT requests, this is used to
8
- * specify the properties to update.
9
- *
10
- * Each follows the format: slug=value
11
- *
12
- * It is typically used as the argv in a command.
13
- *
14
- * Examples:
15
- *
16
- * contrail entities get color -- id=123
17
- * contrail entities update color 123 -- name=obsidian hex=000000
18
- */
19
- Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.isValidPropertySpecification = exports.parsePropertySpecificationsIntoMap = exports.parsePropertySpecification = void 0;
21
- function parsePropertySpecification(spec) {
22
- const equalsIndex = spec.indexOf('=');
23
- if (equalsIndex === -1) {
24
- throw new Error(`Invalid property specification: ${spec}`);
25
- }
26
- const slug = spec.substring(0, equalsIndex);
27
- const value = spec.substring(equalsIndex + 1);
28
- if (!slug || !value) {
29
- throw new Error(`Invalid property specification: ${spec}`);
30
- }
31
- return { slug, value };
32
- }
33
- exports.parsePropertySpecification = parsePropertySpecification;
34
- function parsePropertySpecificationsIntoMap(propertySpecifications) {
35
- const propertySpecBySlug = new Map();
36
- for (const spec of propertySpecifications) {
37
- const { slug, value } = parsePropertySpecification(spec);
38
- if (slug === 'roles') {
39
- // Special handling for roles, which can be an array
40
- const rolesArray = value.split(',').map((role) => role.trim());
41
- propertySpecBySlug.set(slug, rolesArray);
42
- continue;
43
- }
44
- propertySpecBySlug.set(slug, value);
45
- }
46
- return propertySpecBySlug;
47
- }
48
- exports.parsePropertySpecificationsIntoMap = parsePropertySpecificationsIntoMap;
49
- function isValidPropertySpecification(maybeSpec) {
50
- try {
51
- const { slug, value } = parsePropertySpecification(maybeSpec);
52
- return !!slug && !!value;
53
- }
54
- catch (e) {
55
- return false;
56
- }
57
- }
58
- exports.isValidPropertySpecification = isValidPropertySpecification;