@contrail/cli 3.6.0-alpha-2 → 3.6.0-alpha-3

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 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-2 darwin-arm64 node-v22.19.0
20
+ @contrail/cli/3.6.0-alpha-3 darwin-arm64 node-v22.19.0
21
21
  $ contrail --help [COMMAND]
22
22
  USAGE
23
23
  $ contrail COMMAND
@@ -683,7 +683,7 @@ DESCRIPTION
683
683
  EXAMPLES
684
684
  $ contrail entities update color 123 -- name=obsidian hex=000000
685
685
 
686
- $ contrail entities update color 123 -- description= notes='""' data=null # Unset description, empty notes, null data
686
+ $ contrail entities update color 123 -- description= notes='""' # Unset description, set notes to empty string
687
687
  ```
688
688
 
689
689
  ## `contrail file upload FILELOCATION CONTENTTYPE`
@@ -8,6 +8,7 @@ const sdk_1 = require("@contrail/sdk");
8
8
  const login_1 = require("../../auth/login");
9
9
  const types_1 = require("../../api/types");
10
10
  const propertySpecifications_1 = require("../../helpers/propertySpecifications/propertySpecifications");
11
+ const batchFetch_1 = require("../../helpers/entities/batchFetch");
11
12
  let SHOULD_USE_PAGINATED_FIND = false;
12
13
  let MAX_NUMBER_OF_ENTITIES_TO_FETCH = undefined;
13
14
  class GetEntity extends basecommand_1.BaseCommand {
@@ -162,7 +163,13 @@ async function find(entityName, options = {}) {
162
163
  if (propertySlugs && propertySlugs.length > 0) {
163
164
  queryOptions.customParams = { propertySlugs: propertySlugs.join(',') };
164
165
  }
165
- return id ? client.get({ id, ...queryOptions }) : client.get({ criteria, ...queryOptions });
166
+ const payload = id ? { id, ...queryOptions } : { criteria, ...queryOptions };
167
+ if ((0, batchFetch_1.canBatchFetchEntity)(entityName)) {
168
+ return (0, batchFetch_1.batchFetch)(entityName, payload);
169
+ }
170
+ else {
171
+ return client.get(payload);
172
+ }
166
173
  }
167
174
  async function* streamPaginatedFind(typePath, options = {}) {
168
175
  const client = new sdk_1.Entities();
@@ -12,7 +12,7 @@ class UpdateEntity extends basecommand_1.BaseCommand {
12
12
  static description = '(BETA) Update an entity';
13
13
  static examples = [
14
14
  'contrail entities update color 123 -- name=obsidian hex=000000',
15
- 'contrail entities update color 123 -- description= notes=\'""\' data=null # Unset description, empty notes, null data',
15
+ 'contrail entities update color 123 -- description= notes=\'""\' # Unset description, set notes to empty string',
16
16
  ];
17
17
  static flags = {
18
18
  ...basecommand_1.BaseCommand.baseFlags,
@@ -1,7 +1,7 @@
1
- import { AssortmentItem, Item, ProjectItem } from '@contrail/entity-types';
1
+ import { AssortmentItem, ProjectItem } from '@contrail/entity-types';
2
2
  import { EntitiesClientGetOptions } from '@contrail/sdk';
3
+ export declare function canBatchFetchEntity(entityName: string): entityName is keyof BatchFetchableEntityMap;
3
4
  export interface BatchFetchableEntityMap {
4
- item: Item;
5
5
  'project-item': ProjectItem;
6
6
  'assortment-item': AssortmentItem;
7
7
  }
@@ -1,8 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.batchFetch = void 0;
3
+ exports.batchFetch = exports.canBatchFetchEntity = void 0;
4
4
  const sdk_1 = require("@contrail/sdk");
5
5
  const util_1 = require("@contrail/util");
6
+ // Maps entity names to their types for batch fetching.
7
+ // This allows for type-safe batch fetching of entities
8
+ // such that the Type returned always matches the entity name.
9
+ const BATCH_FETCHABLE_ENTITIES = ['assortment-item', 'project-item'];
10
+ function canBatchFetchEntity(entityName) {
11
+ return BATCH_FETCHABLE_ENTITIES.includes(entityName);
12
+ }
13
+ exports.canBatchFetchEntity = canBatchFetchEntity;
6
14
  async function batchFetch(entityName, options) {
7
15
  const response = await requestBatchFetch(entityName, options);
8
16
  return parseBatchFetchResponse(response);
@@ -10,24 +10,22 @@
10
10
  *
11
11
  * It is typically used as the argv in a command.
12
12
  *
13
- * Special handling for empty values and null:
13
+ * Special handling for empty values:
14
14
  * - slug= (empty value) → property is set to undefined (unset)
15
15
  * - slug='""' or slug="''" → property is set to empty string ""
16
- * - slug=null → property is set to null
17
- * - slug="null" → property is set to the string "null"
18
16
  *
19
17
  * Examples:
20
18
  *
21
19
  * contrail entities get color -- id=123
22
20
  * contrail entities update color 123 -- name=obsidian hex=000000
23
- * contrail entities update color 123 -- description= notes='""' data=null
21
+ * contrail entities update color 123 -- description= notes='""'
24
22
  * contrail entities get loader-processes -- createdOn=2025-09-15..2025-09-16
25
23
  */
26
24
  export type PropertySpecification = {
27
25
  slug: string;
28
- value: string | undefined | null;
26
+ value: string | undefined;
29
27
  };
30
- export type PropertySpecificationBySlug = Map<string, string | number | string[] | number[] | undefined | null>;
28
+ export type PropertySpecificationBySlug = Map<string, string | number | string[] | number[] | undefined>;
31
29
  export type PropertySpecificationString = `${string}=${string}`;
32
30
  export declare function parsePropertySpecification(spec: PropertySpecificationString): PropertySpecification;
33
31
  export declare function parsePropertySpecificationsIntoMap(propertySpecifications: PropertySpecificationString[]): PropertySpecificationBySlug;
@@ -11,17 +11,15 @@
11
11
  *
12
12
  * It is typically used as the argv in a command.
13
13
  *
14
- * Special handling for empty values and null:
14
+ * Special handling for empty values:
15
15
  * - slug= (empty value) → property is set to undefined (unset)
16
16
  * - slug='""' or slug="''" → property is set to empty string ""
17
- * - slug=null → property is set to null
18
- * - slug="null" → property is set to the string "null"
19
17
  *
20
18
  * Examples:
21
19
  *
22
20
  * contrail entities get color -- id=123
23
21
  * contrail entities update color 123 -- name=obsidian hex=000000
24
- * contrail entities update color 123 -- description= notes='""' data=null
22
+ * contrail entities update color 123 -- description= notes='""'
25
23
  * contrail entities get loader-processes -- createdOn=2025-09-15..2025-09-16
26
24
  */
27
25
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -40,11 +38,9 @@ function parsePropertySpecification(spec) {
40
38
  if (!slug) {
41
39
  throw new Error(`Invalid property specification: ${spec}`);
42
40
  }
43
- // Handle special cases for empty strings and null:
41
+ // Handle special cases for empty strings:
44
42
  // - x= means undefined (unset the property)
45
43
  // - x='""' or x="''" means empty string ""
46
- // - x=null means null value
47
- // - x="null" means the string "null"
48
44
  let finalValue;
49
45
  if (value === '') {
50
46
  finalValue = undefined;
@@ -52,9 +48,6 @@ function parsePropertySpecification(spec) {
52
48
  else if (value === DOUBLE_QUOTED_EMPTY || value === SINGLE_QUOTED_EMPTY) {
53
49
  finalValue = '';
54
50
  }
55
- else if (value === 'null') {
56
- finalValue = null;
57
- }
58
51
  else {
59
52
  finalValue = value;
60
53
  }
@@ -78,28 +78,6 @@ describe('parsePropertySpecification', () => {
78
78
  value: '',
79
79
  });
80
80
  });
81
- it('should parse property specification with null value', () => {
82
- const spec = 'description=null';
83
- const result = (0, propertySpecifications_1.parsePropertySpecification)(spec);
84
- expect(result).toEqual({
85
- slug: 'description',
86
- value: null,
87
- });
88
- });
89
- it('should distinguish between null and the string "null"', () => {
90
- const nullSpec = 'field=null';
91
- const stringNullSpec = 'field="null"';
92
- const nullResult = (0, propertySpecifications_1.parsePropertySpecification)(nullSpec);
93
- const stringNullResult = (0, propertySpecifications_1.parsePropertySpecification)(stringNullSpec);
94
- expect(nullResult).toEqual({
95
- slug: 'field',
96
- value: null,
97
- });
98
- expect(stringNullResult).toEqual({
99
- slug: 'field',
100
- value: '"null"',
101
- });
102
- });
103
81
  it('should throw error for spec without equals sign', () => {
104
82
  const spec = 'invalidspec';
105
83
  expect(() => (0, propertySpecifications_1.parsePropertySpecification)(spec)).toThrow('Invalid property specification: invalidspec');
@@ -175,23 +153,9 @@ describe('parsePropertySpecificationsIntoMap', () => {
175
153
  const result = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(specs);
176
154
  expect(result.get('name')).toBe('john');
177
155
  expect(result.get('description')).toBeUndefined();
178
- expect(result.get('notes')).toBe('');
156
+ expect(result.get('notes')).toBe(''); // Empty quotes are converted to empty string
179
157
  expect(result.size).toBe(3);
180
158
  });
181
- it('should handle property specifications with null values', () => {
182
- const specs = [
183
- 'name=john',
184
- 'description=null',
185
- 'notes="null"',
186
- 'empty=',
187
- ];
188
- const result = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(specs);
189
- expect(result.get('name')).toBe('john');
190
- expect(result.get('description')).toBeNull();
191
- expect(result.get('notes')).toBe('"null"');
192
- expect(result.get('empty')).toBeUndefined();
193
- expect(result.size).toBe(4);
194
- });
195
159
  it('should throw error for invalid property specifications', () => {
196
160
  const specs = [
197
161
  'name=john',
@@ -278,21 +242,13 @@ describe('integration tests', () => {
278
242
  const quotedSpecs = ['description=""'];
279
243
  const quotedMap = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(quotedSpecs);
280
244
  expect(quotedMap.get('description')).toBe(''); // Quoted empty = empty string
281
- // Test case 3: Mixed usage with null
282
- const mixedSpecs = [
283
- 'name=test',
284
- 'description=',
285
- 'notes=""',
286
- 'data=null',
287
- 'status="null"',
288
- ];
245
+ // Test case 3: Mixed usage
246
+ const mixedSpecs = ['name=test', 'description=', 'notes=""'];
289
247
  const mixedMap = (0, propertySpecifications_1.parsePropertySpecificationsIntoMap)(mixedSpecs);
290
248
  expect(mixedMap.get('name')).toBe('test');
291
249
  expect(mixedMap.get('description')).toBeUndefined(); // Unset
292
250
  expect(mixedMap.get('notes')).toBe(''); // Empty string
293
- expect(mixedMap.get('data')).toBeNull(); // null value
294
- expect(mixedMap.get('status')).toBe('"null"'); // String "null"
295
- expect(mixedMap.size).toBe(5);
251
+ expect(mixedMap.size).toBe(3);
296
252
  });
297
253
  });
298
254
  describe('edge cases and limitations', () => {
@@ -362,20 +318,4 @@ describe('edge cases and limitations', () => {
362
318
  value: 'value',
363
319
  });
364
320
  });
365
- it('should document all special value types', () => {
366
- // This test documents all the special value types and their parsing behavior
367
- const specs = [
368
- { input: 'a=value', expected: 'value', description: 'regular string' },
369
- { input: 'b=', expected: undefined, description: 'undefined (unset)' },
370
- { input: 'c=""', expected: '', description: 'empty string' },
371
- { input: 'd=null', expected: null, description: 'null value' },
372
- { input: 'e="null"', expected: '"null"', description: 'string "null"' },
373
- { input: 'f=123', expected: '123', description: 'numeric string' },
374
- { input: 'g=true', expected: 'true', description: 'boolean string' },
375
- ];
376
- for (const { input, expected } of specs) {
377
- const result = (0, propertySpecifications_1.parsePropertySpecification)(input);
378
- expect(result.value).toBe(expected);
379
- }
380
- });
381
321
  });
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.6.0-alpha-2",
2
+ "version": "3.6.0-alpha-3",
3
3
  "commands": {
4
4
  "app:create": {
5
5
  "id": "app:create",
@@ -964,7 +964,7 @@
964
964
  "aliases": [],
965
965
  "examples": [
966
966
  "contrail entities update color 123 -- name=obsidian hex=000000",
967
- "contrail entities update color 123 -- description= notes='\"\"' data=null # Unset description, empty notes, null data"
967
+ "contrail entities update color 123 -- description= notes='\"\"' # Unset description, set notes to empty string"
968
968
  ],
969
969
  "flags": {
970
970
  "logLevel": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "3.6.0-alpha-2",
3
+ "version": "3.6.0-alpha-3",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "bin": {
6
6
  "contrail-cli": "./bin/run",