@rippling/rippling-sdk 0.2.0-alpha.40 → 0.2.0-alpha.42

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 (111) hide show
  1. package/lib/manifest/_existing-component-fields.d.mts +9 -0
  2. package/lib/manifest/_existing-component-fields.d.mts.map +1 -0
  3. package/lib/manifest/_existing-component-fields.d.ts +9 -0
  4. package/lib/manifest/_existing-component-fields.d.ts.map +1 -0
  5. package/lib/manifest/_existing-component-fields.js +51 -0
  6. package/lib/manifest/_existing-component-fields.js.map +1 -0
  7. package/lib/manifest/_existing-component-fields.mjs +45 -0
  8. package/lib/manifest/_existing-component-fields.mjs.map +1 -0
  9. package/lib/manifest/app.d.mts.map +1 -1
  10. package/lib/manifest/app.d.ts.map +1 -1
  11. package/lib/manifest/app.js +3 -2
  12. package/lib/manifest/app.js.map +1 -1
  13. package/lib/manifest/app.mjs +3 -2
  14. package/lib/manifest/app.mjs.map +1 -1
  15. package/lib/manifest/category.d.mts +1 -1
  16. package/lib/manifest/category.d.mts.map +1 -1
  17. package/lib/manifest/category.d.ts +1 -1
  18. package/lib/manifest/category.d.ts.map +1 -1
  19. package/lib/manifest/category.js +7 -4
  20. package/lib/manifest/category.js.map +1 -1
  21. package/lib/manifest/category.mjs +7 -4
  22. package/lib/manifest/category.mjs.map +1 -1
  23. package/lib/manifest/custom-object-field-section.d.mts.map +1 -1
  24. package/lib/manifest/custom-object-field-section.d.ts.map +1 -1
  25. package/lib/manifest/custom-object-field-section.js +3 -2
  26. package/lib/manifest/custom-object-field-section.js.map +1 -1
  27. package/lib/manifest/custom-object-field-section.mjs +3 -2
  28. package/lib/manifest/custom-object-field-section.mjs.map +1 -1
  29. package/lib/manifest/custom-object-page-layout.d.mts +3 -3
  30. package/lib/manifest/custom-object-page-layout.d.mts.map +1 -1
  31. package/lib/manifest/custom-object-page-layout.d.ts +3 -3
  32. package/lib/manifest/custom-object-page-layout.d.ts.map +1 -1
  33. package/lib/manifest/custom-object-page-layout.js +20 -12
  34. package/lib/manifest/custom-object-page-layout.js.map +1 -1
  35. package/lib/manifest/custom-object-page-layout.mjs +20 -12
  36. package/lib/manifest/custom-object-page-layout.mjs.map +1 -1
  37. package/lib/manifest/custom-object.d.mts +3 -4
  38. package/lib/manifest/custom-object.d.mts.map +1 -1
  39. package/lib/manifest/custom-object.d.ts +3 -4
  40. package/lib/manifest/custom-object.d.ts.map +1 -1
  41. package/lib/manifest/custom-object.js +11 -5
  42. package/lib/manifest/custom-object.js.map +1 -1
  43. package/lib/manifest/custom-object.mjs +11 -5
  44. package/lib/manifest/custom-object.mjs.map +1 -1
  45. package/lib/manifest/existing-manifest-context.d.mts +3 -0
  46. package/lib/manifest/existing-manifest-context.d.mts.map +1 -1
  47. package/lib/manifest/existing-manifest-context.d.ts +3 -0
  48. package/lib/manifest/existing-manifest-context.d.ts.map +1 -1
  49. package/lib/manifest/existing-manifest-context.js +68 -26
  50. package/lib/manifest/existing-manifest-context.js.map +1 -1
  51. package/lib/manifest/existing-manifest-context.mjs +68 -26
  52. package/lib/manifest/existing-manifest-context.mjs.map +1 -1
  53. package/lib/manifest/field.d.mts +2 -2
  54. package/lib/manifest/field.d.mts.map +1 -1
  55. package/lib/manifest/field.d.ts +2 -2
  56. package/lib/manifest/field.d.ts.map +1 -1
  57. package/lib/manifest/field.js +27 -14
  58. package/lib/manifest/field.js.map +1 -1
  59. package/lib/manifest/field.mjs +27 -14
  60. package/lib/manifest/field.mjs.map +1 -1
  61. package/lib/manifest/list-view.d.mts.map +1 -1
  62. package/lib/manifest/list-view.d.ts.map +1 -1
  63. package/lib/manifest/list-view.js +5 -4
  64. package/lib/manifest/list-view.js.map +1 -1
  65. package/lib/manifest/list-view.mjs +5 -4
  66. package/lib/manifest/list-view.mjs.map +1 -1
  67. package/lib/manifest/manifest-function.d.mts.map +1 -1
  68. package/lib/manifest/manifest-function.d.ts.map +1 -1
  69. package/lib/manifest/manifest-function.js +3 -2
  70. package/lib/manifest/manifest-function.js.map +1 -1
  71. package/lib/manifest/manifest-function.mjs +3 -2
  72. package/lib/manifest/manifest-function.mjs.map +1 -1
  73. package/lib/manifest/rule.d.mts.map +1 -1
  74. package/lib/manifest/rule.d.ts.map +1 -1
  75. package/lib/manifest/rule.js +4 -3
  76. package/lib/manifest/rule.js.map +1 -1
  77. package/lib/manifest/rule.mjs +4 -3
  78. package/lib/manifest/rule.mjs.map +1 -1
  79. package/lib/manifest/sdui-page.d.mts +1 -1
  80. package/lib/manifest/sdui-page.d.mts.map +1 -1
  81. package/lib/manifest/sdui-page.d.ts +1 -1
  82. package/lib/manifest/sdui-page.d.ts.map +1 -1
  83. package/lib/manifest/sdui-page.js +5 -4
  84. package/lib/manifest/sdui-page.js.map +1 -1
  85. package/lib/manifest/sdui-page.mjs +5 -4
  86. package/lib/manifest/sdui-page.mjs.map +1 -1
  87. package/lib/manifest/validation.d.mts.map +1 -1
  88. package/lib/manifest/validation.d.ts.map +1 -1
  89. package/lib/manifest/validation.js +12 -7
  90. package/lib/manifest/validation.js.map +1 -1
  91. package/lib/manifest/validation.mjs +12 -7
  92. package/lib/manifest/validation.mjs.map +1 -1
  93. package/package.json +1 -1
  94. package/src/lib/manifest/_existing-component-fields.ts +73 -0
  95. package/src/lib/manifest/app.ts +3 -2
  96. package/src/lib/manifest/category.ts +7 -4
  97. package/src/lib/manifest/custom-object-field-section.ts +3 -2
  98. package/src/lib/manifest/custom-object-page-layout.ts +32 -14
  99. package/src/lib/manifest/custom-object.ts +20 -10
  100. package/src/lib/manifest/existing-manifest-context.ts +125 -37
  101. package/src/lib/manifest/field.ts +36 -19
  102. package/src/lib/manifest/list-view.ts +11 -4
  103. package/src/lib/manifest/manifest-function.ts +3 -2
  104. package/src/lib/manifest/rule.ts +4 -3
  105. package/src/lib/manifest/sdui-page.ts +10 -5
  106. package/src/lib/manifest/validation.ts +12 -7
  107. package/src/version.ts +1 -1
  108. package/version.d.mts +1 -1
  109. package/version.d.ts +1 -1
  110. package/version.js +1 -1
  111. package/version.mjs +1 -1
@@ -10,6 +10,7 @@ import { ManifestFunction } from './manifest-function';
10
10
  import { Rule } from './rule';
11
11
  import { SduiPage } from './sdui-page';
12
12
  import { Validation } from './validation';
13
+ import { requireObjectComponentField, requireStringComponentField } from './_existing-component-fields';
13
14
 
14
15
  export interface ExistingManifest {
15
16
  metadata?: Record<string, any>;
@@ -316,37 +317,52 @@ export class ExistingManifestContext {
316
317
  }
317
318
 
318
319
  private loadCategoryComponent(component: Record<string, any>): Category {
319
- const cacheKey = this.cacheKey('CUSTOM_CATEGORY', component['api_name']);
320
+ const apiName = requireStringComponentField(component, 'api_name', Category.componentType);
321
+ const cacheKey = this.cacheKey('CUSTOM_CATEGORY', apiName);
320
322
  return this.getOrLoad(cacheKey, () =>
321
323
  Category._fromExistingComponent(this.getManifestBuilder(), component),
322
324
  );
323
325
  }
324
326
 
325
327
  private loadCustomObjectComponent(component: Record<string, any>): CustomObject {
326
- const cacheKey = this.cacheKey('CUSTOM_OBJECT', component['api_name']);
328
+ const customObjectApiName = requireStringComponentField(
329
+ component,
330
+ 'api_name',
331
+ CustomObject.componentType,
332
+ );
333
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT', customObjectApiName);
327
334
  return this.getOrLoad(cacheKey, () => {
328
335
  return CustomObject._fromExistingComponent(this.getManifestBuilder(), component, (categoryApiName) =>
329
- this.hasComponent('CUSTOM_CATEGORY', (c) => c['api_name'] === categoryApiName) ?
330
- this.loadCategory(categoryApiName)
331
- : categoryApiName,
336
+ this.loadRequiredCategoryForCustomObject(categoryApiName, customObjectApiName),
332
337
  );
333
338
  });
334
339
  }
335
340
 
336
341
  private loadFieldSectionComponent(component: Record<string, any>): CustomObjectFieldSection {
337
- const cacheKey = this.cacheKey(
338
- 'CUSTOM_OBJECT_FIELD_SECTION',
339
- `${component['model_name']}.${component['section_id']}`,
342
+ const modelName = requireStringComponentField(
343
+ component,
344
+ 'model_name',
345
+ CustomObjectFieldSection.componentType,
340
346
  );
347
+ const sectionId = requireStringComponentField(
348
+ component,
349
+ 'section_id',
350
+ CustomObjectFieldSection.componentType,
351
+ );
352
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT_FIELD_SECTION', `${modelName}.${sectionId}`);
341
353
  return this.getOrLoad(cacheKey, () => {
342
- const customObject = this.loadCustomObject(component['model_name']);
354
+ const customObject = this.loadCustomObject(modelName);
343
355
  return CustomObjectFieldSection._fromExistingComponent(customObject, component);
344
356
  });
345
357
  }
346
358
 
347
359
  private loadFieldComponent(component: Record<string, any>): Field {
348
- const customObjectApiName = component['custom_object_api_name'];
349
- const fieldApiName = component['field_api_name'];
360
+ const customObjectApiName = requireStringComponentField(
361
+ component,
362
+ 'custom_object_api_name',
363
+ Field.componentType,
364
+ );
365
+ const fieldApiName = requireStringComponentField(component, 'field_api_name', Field.componentType);
350
366
  if (component['is_standard'] === true) {
351
367
  this.loadCustomObject(customObjectApiName);
352
368
  return this.loadFieldReferenceComponent(component);
@@ -357,7 +373,11 @@ export class ExistingManifestContext {
357
373
  const customObject = this.loadCustomObject(customObjectApiName);
358
374
  const sectionId = component['section'];
359
375
  if (typeof sectionId === 'string') {
360
- this.loadFieldSectionIfPresent(customObjectApiName, sectionId);
376
+ this.loadRequiredFieldSection(
377
+ customObjectApiName,
378
+ sectionId,
379
+ `CUSTOM_OBJECT_FIELD ${customObjectApiName}.${fieldApiName}`,
380
+ );
361
381
  }
362
382
  this.loadFieldRelationshipDependencies(component);
363
383
  return Field._fromExistingComponent(customObject, component);
@@ -365,12 +385,14 @@ export class ExistingManifestContext {
365
385
  }
366
386
 
367
387
  private loadListViewComponent(component: Record<string, any>): ListViewDef {
368
- const cacheKey = this.cacheKey(
369
- 'CUSTOM_OBJECT_LIST_VIEW',
370
- `${component['object_rql_name']}.${component['view_id']}`,
388
+ const customObjectApiName = requireStringComponentField(
389
+ component,
390
+ 'object_rql_name',
391
+ ListViewDef.componentType,
371
392
  );
393
+ const viewId = requireStringComponentField(component, 'view_id', ListViewDef.componentType);
394
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT_LIST_VIEW', `${customObjectApiName}.${viewId}`);
372
395
  return this.getOrLoad(cacheKey, () => {
373
- const customObjectApiName = component['object_rql_name'];
374
396
  const customObject = this.loadCustomObject(customObjectApiName);
375
397
  return ListViewDef._fromExistingComponent(customObject, component, (fieldApiName) =>
376
398
  this.loadFieldByObjectAndApi(customObjectApiName, fieldApiName),
@@ -379,12 +401,18 @@ export class ExistingManifestContext {
379
401
  }
380
402
 
381
403
  private loadPageLayoutComponent(component: Record<string, any>): CustomObjectPageLayout {
382
- const cacheKey = this.cacheKey(
383
- 'CUSTOM_OBJECT_PAGE_LAYOUT',
384
- component['layout_id'] ?? `${component['object_rql_name']}.${component['api_name']}`,
404
+ const layoutId = requireStringComponentField(
405
+ component,
406
+ 'layout_id',
407
+ CustomObjectPageLayout.componentType,
408
+ );
409
+ const customObjectApiName = requireStringComponentField(
410
+ component,
411
+ 'object_rql_name',
412
+ CustomObjectPageLayout.componentType,
385
413
  );
414
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT_PAGE_LAYOUT', layoutId);
386
415
  return this.getOrLoad(cacheKey, () => {
387
- const customObjectApiName = component['object_rql_name'];
388
416
  const customObject = this.loadCustomObject(customObjectApiName);
389
417
  this.loadPageLayoutDependencies(customObjectApiName, component);
390
418
  return CustomObjectPageLayout._fromExistingComponent(customObject, component);
@@ -392,12 +420,14 @@ export class ExistingManifestContext {
392
420
  }
393
421
 
394
422
  private loadValidationComponent(component: Record<string, any>): Validation {
395
- const cacheKey = this.cacheKey(
396
- 'CUSTOM_OBJECT_VALIDATION_RULE',
397
- `${component['model_rql_name']}.${component['rule_id']}`,
423
+ const customObjectApiName = requireStringComponentField(
424
+ component,
425
+ 'model_rql_name',
426
+ Validation.componentType,
398
427
  );
428
+ const ruleId = requireStringComponentField(component, 'rule_id', Validation.componentType);
429
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT_VALIDATION_RULE', `${customObjectApiName}.${ruleId}`);
399
430
  return this.getOrLoad(cacheKey, () => {
400
- const customObjectApiName = component['model_rql_name'];
401
431
  const customObject = this.loadCustomObject(customObjectApiName);
402
432
  return Validation._fromExistingComponent(customObject, component, (fieldApiName) =>
403
433
  this.loadFieldByObjectAndApi(customObjectApiName, fieldApiName),
@@ -406,12 +436,10 @@ export class ExistingManifestContext {
406
436
  }
407
437
 
408
438
  private loadRuleComponent(component: Record<string, any>): Rule {
409
- const cacheKey = this.cacheKey(
410
- 'CUSTOM_OBJECT_RECORD_TRIGGERED_FLOW',
411
- `${component['model_rql_name']}.${component['flow_id']}`,
412
- );
439
+ const customObjectApiName = requireStringComponentField(component, 'model_rql_name', Rule.componentType);
440
+ const flowId = requireStringComponentField(component, 'flow_id', Rule.componentType);
441
+ const cacheKey = this.cacheKey('CUSTOM_OBJECT_RECORD_TRIGGERED_FLOW', `${customObjectApiName}.${flowId}`);
413
442
  return this.getOrLoad(cacheKey, () => {
414
- const customObjectApiName = component['model_rql_name'];
415
443
  const customObject = this.loadCustomObject(customObjectApiName);
416
444
  return Rule._fromExistingComponent(customObject, component, (fieldApiName) =>
417
445
  this.loadFieldByObjectAndApi(customObjectApiName, fieldApiName),
@@ -420,25 +448,26 @@ export class ExistingManifestContext {
420
448
  }
421
449
 
422
450
  private loadFunctionComponent(component: Record<string, any>): ManifestFunction {
423
- const cacheKey = this.cacheKey('FUNCTION', component['api_name']);
451
+ const apiName = requireStringComponentField(component, 'api_name', ManifestFunction.componentType);
452
+ const cacheKey = this.cacheKey('FUNCTION', apiName);
424
453
  return this.getOrLoad(cacheKey, () =>
425
454
  ManifestFunction._fromExistingComponent(this.getManifestBuilder(), component),
426
455
  );
427
456
  }
428
457
 
429
458
  private loadSduiPageComponent(component: Record<string, any>): SduiPage {
430
- const cacheKey = this.cacheKey('SDUI_PAGE', component['sdui_page_id']);
459
+ const sduiPageId = requireStringComponentField(component, 'sdui_page_id', SduiPage.componentType);
460
+ const cacheKey = this.cacheKey('SDUI_PAGE', sduiPageId);
431
461
  return this.getOrLoad(cacheKey, () => {
432
462
  return SduiPage._fromExistingComponent(this.getManifestBuilder(), component, (functionApiName) =>
433
- this.hasComponent('FUNCTION', (c) => c['api_name'] === functionApiName) ?
434
- this.loadFunction(functionApiName)
435
- : functionApiName,
463
+ this.loadRequiredFunctionForSduiPage(functionApiName, component),
436
464
  );
437
465
  });
438
466
  }
439
467
 
440
468
  private loadAppComponent(component: Record<string, any>): App {
441
- const cacheKey = this.cacheKey('CUSTOM_APP', component['api_name']);
469
+ const apiName = requireStringComponentField(component, 'api_name', App.componentType);
470
+ const cacheKey = this.cacheKey('CUSTOM_APP', apiName);
442
471
  return this.getOrLoad(cacheKey, () => {
443
472
  this.loadAppDependencies(component);
444
473
  return App._fromExistingComponent(this.getManifestBuilder(), component);
@@ -495,13 +524,48 @@ export class ExistingManifestContext {
495
524
  return this.getOrLoad(cacheKey, () => Field._referenceFromExistingComponent(component));
496
525
  }
497
526
 
527
+ private loadRequiredCategoryForCustomObject(
528
+ categoryApiName: string,
529
+ customObjectApiName: string,
530
+ ): Category {
531
+ const component = this.ofType('CUSTOM_CATEGORY').find(
532
+ (candidate) => candidate['api_name'] === categoryApiName,
533
+ );
534
+ if (component == null) {
535
+ throw new Error(
536
+ `CUSTOM_OBJECT ${customObjectApiName} references CUSTOM_CATEGORY ${categoryApiName}, ` +
537
+ 'but that category component is not present. Pass the full existing component extraction ' +
538
+ 'to ManifestBuilder.loadFromExistingJson(...).',
539
+ );
540
+ }
541
+ return this.loadCategoryComponent(component);
542
+ }
543
+
544
+ private loadRequiredFunctionForSduiPage(
545
+ functionApiName: string,
546
+ component: Record<string, any>,
547
+ ): ManifestFunction {
548
+ const sduiPageId = component['sdui_page_id'] ?? 'unknown';
549
+ const functionComponent = this.ofType('FUNCTION').find(
550
+ (candidate) => candidate['api_name'] === functionApiName,
551
+ );
552
+ if (functionComponent == null) {
553
+ throw new Error(
554
+ `SDUI_PAGE ${sduiPageId} references FUNCTION ${functionApiName}, ` +
555
+ 'but that function component is not present. Pass the full existing component extraction ' +
556
+ 'to ManifestBuilder.loadFromExistingJson(...).',
557
+ );
558
+ }
559
+ return this.loadFunctionComponent(functionComponent);
560
+ }
561
+
498
562
  private loadSyntheticFieldReference(customObjectApiName: string, fieldApiName: string): Field {
499
563
  const cacheKey = this.cacheKey('CUSTOM_OBJECT_FIELD_REF', `${customObjectApiName}.${fieldApiName}`);
500
564
  return this.getOrLoad(cacheKey, () => Field._syntheticReference(customObjectApiName, fieldApiName));
501
565
  }
502
566
 
503
567
  private loadFieldRelationshipDependencies(component: Record<string, any>): void {
504
- const dataType = component['data_type'] ?? {};
568
+ const dataType = requireObjectComponentField(component, 'data_type', Field.componentType);
505
569
  const targetApiName = dataType['og_model_rql_name'];
506
570
  if (
507
571
  typeof targetApiName === 'string' &&
@@ -600,7 +664,17 @@ export class ExistingManifestContext {
600
664
  }
601
665
  if (field == null || typeof field !== 'object') return;
602
666
  const record = field as Record<string, any>;
603
- this.loadFieldDependencyIfString(customObjectApiName, record['fieldRqlName'] ?? record['field_rql_name']);
667
+ const fieldSection = record['fieldSection'] ?? record['field_section'];
668
+ const fieldApiName = record['fieldRqlName'] ?? record['field_rql_name'];
669
+ if (typeof fieldSection === 'string') {
670
+ const fieldLabel = typeof fieldApiName === 'string' ? ` ${fieldApiName}` : '';
671
+ this.loadRequiredFieldSection(
672
+ customObjectApiName,
673
+ fieldSection,
674
+ `CUSTOM_OBJECT_PAGE_LAYOUT field${fieldLabel} on ${customObjectApiName}`,
675
+ );
676
+ }
677
+ this.loadFieldDependencyIfString(customObjectApiName, fieldApiName);
604
678
  }
605
679
 
606
680
  private loadFieldDependencyIfString(customObjectApiName: string, fieldApiName: unknown): void {
@@ -619,6 +693,20 @@ export class ExistingManifestContext {
619
693
  }
620
694
  }
621
695
 
696
+ private loadRequiredFieldSection(customObjectApiName: string, sectionId: string, ownerLabel: string): void {
697
+ const component = this.ofType('CUSTOM_OBJECT_FIELD_SECTION').find(
698
+ (candidate) => candidate['model_name'] === customObjectApiName && candidate['section_id'] === sectionId,
699
+ );
700
+ if (component == null) {
701
+ throw new Error(
702
+ `${ownerLabel} references CUSTOM_OBJECT_FIELD_SECTION ${sectionId}, ` +
703
+ 'but that field section component is not present. Pass the full existing component extraction ' +
704
+ 'to ManifestBuilder.loadFromExistingJson(...).',
705
+ );
706
+ }
707
+ this.loadFieldSectionComponent(component);
708
+ }
709
+
622
710
  private loadAppDependencies(component: Record<string, any>): void {
623
711
  for (const page of component['pages'] ?? []) {
624
712
  if (page == null || typeof page !== 'object') continue;
@@ -9,6 +9,7 @@ import type { CustomObject } from './custom-object';
9
9
  import type { CustomObjectFieldSection } from './custom-object-field-section';
10
10
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
11
11
  import type { ManifestComponentDeletion } from './manifest-builder';
12
+ import { requireObjectComponentField, requireStringComponentField } from './_existing-component-fields';
12
13
 
13
14
  export interface CustomObjectFieldDeletionIdentifier {
14
15
  customObjectApiName: string;
@@ -70,7 +71,7 @@ interface CommonFieldProps {
70
71
  apiName: string;
71
72
  displayName: string;
72
73
  description?: string;
73
- section?: CustomObjectFieldSection | string;
74
+ section?: CustomObjectFieldSection;
74
75
  }
75
76
 
76
77
  /**
@@ -93,7 +94,7 @@ export interface FieldProps {
93
94
  formulaAttrMetas?: Record<string, any> | null | undefined;
94
95
  derivedAggregatedField?: Record<string, any> | null | undefined;
95
96
  derivedFieldFormula?: string | null | undefined;
96
- section?: CustomObjectFieldSection | string | null | undefined;
97
+ section?: CustomObjectFieldSection | null | undefined;
97
98
  maxLength?: number | undefined;
98
99
  decimalPlaces?: number | undefined;
99
100
  currency?: string | undefined;
@@ -106,6 +107,17 @@ export interface FieldLoadFromExistingOptions extends ExistingManifestContextOpt
106
107
  customObjectApiName?: string;
107
108
  }
108
109
 
110
+ function normalizeSectionInput(section: CustomObjectFieldSection | string | null | undefined): string | null {
111
+ if (section == null) return null;
112
+ if (typeof section === 'string') {
113
+ throw new TypeError(
114
+ `Field section must be a CustomObjectFieldSection object; received raw section id "${section}". ` +
115
+ 'Load/include the existing field section first.',
116
+ );
117
+ }
118
+ return section.getSectionId();
119
+ }
120
+
109
121
  class ExistingFieldReference {
110
122
  private _section: string | null;
111
123
 
@@ -113,15 +125,19 @@ class ExistingFieldReference {
113
125
  private readonly customObjectApiName: string,
114
126
  private readonly component: Record<string, any>,
115
127
  ) {
128
+ requireStringComponentField(component, 'custom_object_api_name', Field.componentType);
129
+ requireStringComponentField(component, 'field_api_name', Field.componentType);
130
+ requireStringComponentField(component, 'field_display_name', Field.componentType);
131
+ requireObjectComponentField(component, 'data_type', Field.componentType);
116
132
  this._section = (component['section'] as string | null | undefined) ?? null;
117
133
  }
118
134
 
119
135
  getApiName(): string {
120
- return this.component['field_api_name'];
136
+ return this.component['field_api_name'] as string;
121
137
  }
122
138
 
123
139
  getDisplayName(): string {
124
- return this.component['field_display_name'] ?? this.getApiName();
140
+ return this.component['field_display_name'] as string;
125
141
  }
126
142
 
127
143
  getCustomObjectApiName(): string {
@@ -133,7 +149,7 @@ class ExistingFieldReference {
133
149
  }
134
150
 
135
151
  getDataType(): Readonly<Record<string, any>> {
136
- return this.component['data_type'] ?? {};
152
+ return this.component['data_type'] as Record<string, any>;
137
153
  }
138
154
 
139
155
  isFormula(): boolean {
@@ -240,11 +256,8 @@ export class Field {
240
256
  this._derivedFieldFormula = props.derivedFieldFormula ?? null;
241
257
  this._summarySpec = props.summarySpec ?? null;
242
258
 
243
- const rawSection = props.section;
244
- this._section =
245
- rawSection == null ? null
246
- : typeof rawSection === 'string' ? rawSection
247
- : rawSection.getSectionId();
259
+ const rawSection = props.section as CustomObjectFieldSection | string | null | undefined;
260
+ this._section = normalizeSectionInput(rawSection);
248
261
 
249
262
  customObject._register(this);
250
263
  }
@@ -262,10 +275,10 @@ export class Field {
262
275
  /** @internal Hydrates a custom object field from existing manifest wire JSON. */
263
276
  static _fromExistingComponent(customObject: CustomObject, component: Record<string, any>): Field {
264
277
  const props: FieldProps = {
265
- apiName: component['field_api_name'],
266
- displayName: component['field_display_name'] ?? component['field_api_name'],
278
+ apiName: requireStringComponentField(component, 'field_api_name', Field.componentType),
279
+ displayName: requireStringComponentField(component, 'field_display_name', Field.componentType),
280
+ dataType: cloneJson(requireObjectComponentField(component, 'data_type', Field.componentType)),
267
281
  };
268
- if (component['data_type'] !== undefined) props.dataType = cloneJson(component['data_type'] ?? {});
269
282
  if (component['description'] !== undefined) props.description = component['description'];
270
283
  if (component['is_required'] !== undefined) props.required = component['is_required'];
271
284
  if (component['is_unique'] !== undefined) props.unique = component['is_unique'];
@@ -278,16 +291,20 @@ export class Field {
278
291
  }
279
292
  if (component['derived_field_formula'] !== undefined)
280
293
  props.derivedFieldFormula = component['derived_field_formula'];
281
- if (component['section'] !== undefined) props.section = component['section'];
282
- return new Field(customObject, props);
294
+ const field = new Field(customObject, props);
295
+ if (typeof component['section'] === 'string') field._assignSection(component['section']);
296
+ return field;
283
297
  }
284
298
 
285
299
  /** @internal Creates a non-registered reference for standard or external fields. */
286
300
  static _referenceFromExistingComponent(component: Record<string, any>): Field {
287
- return new ExistingFieldReference(
288
- component['custom_object_api_name'],
289
- cloneJson(component),
290
- ) as unknown as Field;
301
+ const customObjectApiName = requireStringComponentField(
302
+ component,
303
+ 'custom_object_api_name',
304
+ Field.componentType,
305
+ );
306
+ requireStringComponentField(component, 'field_api_name', Field.componentType);
307
+ return new ExistingFieldReference(customObjectApiName, cloneJson(component)) as unknown as Field;
291
308
  }
292
309
 
293
310
  /** @internal Creates a non-registered reference for a known wire field name. */
@@ -3,6 +3,11 @@ import type { CustomObject } from './custom-object';
3
3
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
4
4
  import type { Field } from './field';
5
5
  import type { ManifestComponentDeletion } from './manifest-builder';
6
+ import {
7
+ requireArrayComponentField,
8
+ requireBooleanComponentField,
9
+ requireStringComponentField,
10
+ } from './_existing-component-fields';
6
11
 
7
12
  export interface ListViewDeletionIdentifier {
8
13
  viewId: string;
@@ -178,10 +183,12 @@ export class ListViewDef {
178
183
  resolveField: (apiName: string) => Field,
179
184
  ): ListViewDef {
180
185
  const props: ListViewDefProps = {
181
- viewId: component['view_id'],
182
- name: component['name'] ?? component['view_id'],
183
- fields: (component['fields'] ?? []).map((fieldApiName: string) => resolveField(fieldApiName)),
184
- isPublic: Boolean(component['public']),
186
+ viewId: requireStringComponentField(component, 'view_id', ListViewDef.componentType),
187
+ name: requireStringComponentField(component, 'name', ListViewDef.componentType),
188
+ fields: requireArrayComponentField<string>(component, 'fields', ListViewDef.componentType).map(
189
+ (fieldApiName: string) => resolveField(fieldApiName),
190
+ ),
191
+ isPublic: requireBooleanComponentField(component, 'public', ListViewDef.componentType),
185
192
  };
186
193
  if (component['description'] !== undefined) props.description = component['description'];
187
194
  if (component['object_scope'] !== undefined) props.objectScope = component['object_scope'];
@@ -1,6 +1,7 @@
1
1
  import type { FunctionRuntime } from './_helpers';
2
2
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
3
3
  import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder';
4
+ import { requireStringComponentField } from './_existing-component-fields';
4
5
 
5
6
  /**
6
7
  * Initialization properties for {@link ManifestFunction}.
@@ -148,8 +149,8 @@ export class ManifestFunction {
148
149
  /** @internal Hydrates a function from existing manifest wire JSON. */
149
150
  static _fromExistingComponent(scope: ManifestScope, component: Record<string, any>): ManifestFunction {
150
151
  const props: ManifestFunctionProps = {
151
- apiName: component['api_name'],
152
- name: component['name'] ?? component['api_name'],
152
+ apiName: requireStringComponentField(component, 'api_name', ManifestFunction.componentType),
153
+ name: requireStringComponentField(component, 'name', ManifestFunction.componentType),
153
154
  };
154
155
  if (component['code_draft'] !== undefined) props.code = component['code_draft'];
155
156
  if (component['description'] !== undefined) props.description = component['description'];
@@ -3,6 +3,7 @@ import type { CustomObject } from './custom-object';
3
3
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
4
4
  import type { Field } from './field';
5
5
  import type { ManifestComponentDeletion } from './manifest-builder';
6
+ import { requireStringComponentField } from './_existing-component-fields';
6
7
 
7
8
  export interface RuleDeletionIdentifier {
8
9
  flowId: string;
@@ -193,9 +194,9 @@ export class Rule {
193
194
  resolveField: (apiName: string) => Field,
194
195
  ): Rule {
195
196
  const props: RuleProps = {
196
- flowId: component['flow_id'],
197
- flowName: component['flow_name'] ?? component['flow_id'],
198
- triggerType: component['trigger_type'],
197
+ flowId: requireStringComponentField(component, 'flow_id', Rule.componentType),
198
+ flowName: requireStringComponentField(component, 'flow_name', Rule.componentType),
199
+ triggerType: requireStringComponentField(component, 'trigger_type', Rule.componentType) as TriggerType,
199
200
  actions: (component['actions'] ?? []).map((action: Record<string, any>): RuleAction => {
200
201
  const out: RuleAction = {
201
202
  targetField: resolveField(action['target_field']),
@@ -1,6 +1,7 @@
1
1
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
2
2
  import type { ManifestFunction } from './manifest-function';
3
3
  import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder';
4
+ import { requireStringComponentField } from './_existing-component-fields';
4
5
 
5
6
  /**
6
7
  * Initialization properties for {@link SduiPage}.
@@ -101,13 +102,17 @@ export class SduiPage {
101
102
  static _fromExistingComponent(
102
103
  scope: ManifestScope,
103
104
  component: Record<string, any>,
104
- resolveFunction: (apiName: string) => ManifestFunction | string,
105
+ resolveFunction: (apiName: string) => ManifestFunction,
105
106
  ): SduiPage {
106
- const functionApiName = component['function_api_name'];
107
+ const functionApiName = requireStringComponentField(
108
+ component,
109
+ 'function_api_name',
110
+ SduiPage.componentType,
111
+ );
107
112
  const props: SduiPageProps = {
108
- sduiPageId: component['sdui_page_id'],
109
- name: component['name'] ?? component['sdui_page_id'],
110
- function: typeof functionApiName === 'string' ? resolveFunction(functionApiName) : functionApiName,
113
+ sduiPageId: requireStringComponentField(component, 'sdui_page_id', SduiPage.componentType),
114
+ name: requireStringComponentField(component, 'name', SduiPage.componentType),
115
+ function: resolveFunction(functionApiName),
111
116
  };
112
117
  if (component['description'] !== undefined) {
113
118
  props.description = component['description'];
@@ -3,6 +3,7 @@ import type { CustomObject } from './custom-object';
3
3
  import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
4
4
  import type { Field } from './field';
5
5
  import type { ManifestComponentDeletion } from './manifest-builder';
6
+ import { requireStringComponentField } from './_existing-component-fields';
6
7
 
7
8
  export interface ValidationDeletionIdentifier {
8
9
  ruleId: string;
@@ -147,13 +148,17 @@ export class Validation {
147
148
  resolveField: (apiName: string) => Field,
148
149
  ): Validation {
149
150
  const props: ValidationProps = {
150
- ruleId: component['rule_id'],
151
- displayName: component['display_name'] ?? component['rule_id'],
152
- rqlFormula: component['rql_formula'] ?? '',
153
- errorMessage: component['custom_error_message'] ?? '',
154
- state: component['state'],
155
- level: component['level'],
156
- ruleDescription: component['rule_description'] ?? '',
151
+ ruleId: requireStringComponentField(component, 'rule_id', Validation.componentType),
152
+ displayName: requireStringComponentField(component, 'display_name', Validation.componentType),
153
+ rqlFormula: requireStringComponentField(component, 'rql_formula', Validation.componentType),
154
+ errorMessage: requireStringComponentField(component, 'custom_error_message', Validation.componentType, {
155
+ allowEmpty: true,
156
+ }),
157
+ state: requireStringComponentField(component, 'state', Validation.componentType) as ValidationState,
158
+ level: requireStringComponentField(component, 'level', Validation.componentType) as ValidationLevel,
159
+ ruleDescription: requireStringComponentField(component, 'rule_description', Validation.componentType, {
160
+ allowEmpty: true,
161
+ }),
157
162
  };
158
163
  if (component['field_rql_name'] != null) props.fieldRef = resolveField(component['field_rql_name']);
159
164
  return new Validation(customObject, props);
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.2.0-alpha.40'; // x-release-please-version
1
+ export const VERSION = '0.2.0-alpha.42'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.2.0-alpha.40";
1
+ export declare const VERSION = "0.2.0-alpha.42";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.2.0-alpha.40";
1
+ export declare const VERSION = "0.2.0-alpha.42";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.2.0-alpha.40'; // x-release-please-version
4
+ exports.VERSION = '0.2.0-alpha.42'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.2.0-alpha.40'; // x-release-please-version
1
+ export const VERSION = '0.2.0-alpha.42'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map