@rippling/rippling-sdk 0.2.0-alpha.38 → 0.2.0-alpha.39
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/lib/manifest/app.d.mts +11 -1
- package/lib/manifest/app.d.mts.map +1 -1
- package/lib/manifest/app.d.ts +11 -1
- package/lib/manifest/app.d.ts.map +1 -1
- package/lib/manifest/app.js +42 -1
- package/lib/manifest/app.js.map +1 -1
- package/lib/manifest/app.mjs +42 -1
- package/lib/manifest/app.mjs.map +1 -1
- package/lib/manifest/category.d.mts +10 -1
- package/lib/manifest/category.d.mts.map +1 -1
- package/lib/manifest/category.d.ts +10 -1
- package/lib/manifest/category.d.ts.map +1 -1
- package/lib/manifest/category.js +23 -1
- package/lib/manifest/category.js.map +1 -1
- package/lib/manifest/category.mjs +23 -1
- package/lib/manifest/category.mjs.map +1 -1
- package/lib/manifest/custom-object-field-section.d.mts +13 -0
- package/lib/manifest/custom-object-field-section.d.mts.map +1 -1
- package/lib/manifest/custom-object-field-section.d.ts +13 -0
- package/lib/manifest/custom-object-field-section.d.ts.map +1 -1
- package/lib/manifest/custom-object-field-section.js +22 -1
- package/lib/manifest/custom-object-field-section.js.map +1 -1
- package/lib/manifest/custom-object-field-section.mjs +22 -1
- package/lib/manifest/custom-object-field-section.mjs.map +1 -1
- package/lib/manifest/custom-object-page-layout.d.mts +21 -0
- package/lib/manifest/custom-object-page-layout.d.mts.map +1 -1
- package/lib/manifest/custom-object-page-layout.d.ts +21 -0
- package/lib/manifest/custom-object-page-layout.d.ts.map +1 -1
- package/lib/manifest/custom-object-page-layout.js +41 -1
- package/lib/manifest/custom-object-page-layout.js.map +1 -1
- package/lib/manifest/custom-object-page-layout.mjs +41 -1
- package/lib/manifest/custom-object-page-layout.mjs.map +1 -1
- package/lib/manifest/custom-object.d.mts +11 -1
- package/lib/manifest/custom-object.d.mts.map +1 -1
- package/lib/manifest/custom-object.d.ts +11 -1
- package/lib/manifest/custom-object.d.ts.map +1 -1
- package/lib/manifest/custom-object.js +55 -2
- package/lib/manifest/custom-object.js.map +1 -1
- package/lib/manifest/custom-object.mjs +55 -2
- package/lib/manifest/custom-object.mjs.map +1 -1
- package/lib/manifest/existing-manifest-context.d.mts +87 -0
- package/lib/manifest/existing-manifest-context.d.mts.map +1 -0
- package/lib/manifest/existing-manifest-context.d.ts +87 -0
- package/lib/manifest/existing-manifest-context.d.ts.map +1 -0
- package/lib/manifest/existing-manifest-context.js +511 -0
- package/lib/manifest/existing-manifest-context.js.map +1 -0
- package/lib/manifest/existing-manifest-context.mjs +506 -0
- package/lib/manifest/existing-manifest-context.mjs.map +1 -0
- package/lib/manifest/field.d.mts +24 -0
- package/lib/manifest/field.d.mts.map +1 -1
- package/lib/manifest/field.d.ts +24 -0
- package/lib/manifest/field.d.ts.map +1 -1
- package/lib/manifest/field.js +114 -1
- package/lib/manifest/field.js.map +1 -1
- package/lib/manifest/field.mjs +114 -1
- package/lib/manifest/field.mjs.map +1 -1
- package/lib/manifest/index.d.mts +8 -7
- package/lib/manifest/index.d.mts.map +1 -1
- package/lib/manifest/index.d.ts +8 -7
- package/lib/manifest/index.d.ts.map +1 -1
- package/lib/manifest/index.js +3 -1
- package/lib/manifest/index.js.map +1 -1
- package/lib/manifest/index.mjs +5 -4
- package/lib/manifest/index.mjs.map +1 -1
- package/lib/manifest/list-view.d.mts +17 -0
- package/lib/manifest/list-view.d.mts.map +1 -1
- package/lib/manifest/list-view.d.ts +17 -0
- package/lib/manifest/list-view.d.ts.map +1 -1
- package/lib/manifest/list-view.js +38 -1
- package/lib/manifest/list-view.js.map +1 -1
- package/lib/manifest/list-view.mjs +38 -1
- package/lib/manifest/list-view.mjs.map +1 -1
- package/lib/manifest/manifest-builder.d.mts +59 -6
- package/lib/manifest/manifest-builder.d.mts.map +1 -1
- package/lib/manifest/manifest-builder.d.ts +59 -6
- package/lib/manifest/manifest-builder.d.ts.map +1 -1
- package/lib/manifest/manifest-builder.js +61 -3
- package/lib/manifest/manifest-builder.js.map +1 -1
- package/lib/manifest/manifest-builder.mjs +61 -3
- package/lib/manifest/manifest-builder.mjs.map +1 -1
- package/lib/manifest/manifest-function.d.mts +10 -1
- package/lib/manifest/manifest-function.d.mts.map +1 -1
- package/lib/manifest/manifest-function.d.ts +10 -1
- package/lib/manifest/manifest-function.d.ts.map +1 -1
- package/lib/manifest/manifest-function.js +36 -1
- package/lib/manifest/manifest-function.js.map +1 -1
- package/lib/manifest/manifest-function.mjs +36 -1
- package/lib/manifest/manifest-function.mjs.map +1 -1
- package/lib/manifest/rule.d.mts +17 -0
- package/lib/manifest/rule.d.mts.map +1 -1
- package/lib/manifest/rule.d.ts +17 -0
- package/lib/manifest/rule.d.ts.map +1 -1
- package/lib/manifest/rule.js +45 -1
- package/lib/manifest/rule.js.map +1 -1
- package/lib/manifest/rule.mjs +45 -1
- package/lib/manifest/rule.mjs.map +1 -1
- package/lib/manifest/sdui-page.d.mts +10 -1
- package/lib/manifest/sdui-page.d.mts.map +1 -1
- package/lib/manifest/sdui-page.d.ts +10 -1
- package/lib/manifest/sdui-page.d.ts.map +1 -1
- package/lib/manifest/sdui-page.js +28 -1
- package/lib/manifest/sdui-page.js.map +1 -1
- package/lib/manifest/sdui-page.mjs +28 -1
- package/lib/manifest/sdui-page.mjs.map +1 -1
- package/lib/manifest/validation.d.mts +17 -0
- package/lib/manifest/validation.d.mts.map +1 -1
- package/lib/manifest/validation.d.ts +17 -0
- package/lib/manifest/validation.d.ts.map +1 -1
- package/lib/manifest/validation.js +31 -1
- package/lib/manifest/validation.js.map +1 -1
- package/lib/manifest/validation.mjs +31 -1
- package/lib/manifest/validation.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/manifest/app.ts +46 -2
- package/src/lib/manifest/category.ts +28 -2
- package/src/lib/manifest/custom-object-field-section.ts +37 -1
- package/src/lib/manifest/custom-object-page-layout.ts +61 -1
- package/src/lib/manifest/custom-object.ts +58 -3
- package/src/lib/manifest/existing-manifest-context.ts +673 -0
- package/src/lib/manifest/field.ts +140 -1
- package/src/lib/manifest/index.ts +39 -4
- package/src/lib/manifest/list-view.ts +50 -1
- package/src/lib/manifest/manifest-builder.ts +114 -4
- package/src/lib/manifest/manifest-function.ts +36 -2
- package/src/lib/manifest/rule.ts +60 -1
- package/src/lib/manifest/sdui-page.ts +37 -2
- package/src/lib/manifest/validation.ts +48 -1
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { generateId } from "./_helpers.mjs";
|
|
2
|
+
import { getExistingManifestContext } from "./existing-manifest-context.mjs";
|
|
2
3
|
/**
|
|
3
4
|
* Defines a validation rule and registers it with the manifest.
|
|
4
5
|
*
|
|
@@ -25,6 +26,13 @@ import { generateId } from "./_helpers.mjs";
|
|
|
25
26
|
* ```
|
|
26
27
|
*/
|
|
27
28
|
export class Validation {
|
|
29
|
+
static toDeletionIdentifier(identifier) {
|
|
30
|
+
return {
|
|
31
|
+
type: Validation.componentType,
|
|
32
|
+
rule_id: identifier.ruleId,
|
|
33
|
+
model_rql_name: identifier.modelRqlName,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
28
36
|
/**
|
|
29
37
|
* @param customObject - The custom object this rule applies to.
|
|
30
38
|
* @param props - Initialization properties.
|
|
@@ -41,6 +49,27 @@ export class Validation {
|
|
|
41
49
|
this._fieldRef = props.fieldRef;
|
|
42
50
|
customObject._register(this);
|
|
43
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Loads this validation rule from the active existing-manifest JSON context.
|
|
54
|
+
*/
|
|
55
|
+
static loadFromExisting(ruleId, options = {}) {
|
|
56
|
+
return getExistingManifestContext(options).loadValidation(ruleId, options);
|
|
57
|
+
}
|
|
58
|
+
/** @internal Hydrates a validation rule from existing manifest wire JSON. */
|
|
59
|
+
static _fromExistingComponent(customObject, component, resolveField) {
|
|
60
|
+
const props = {
|
|
61
|
+
ruleId: component['rule_id'],
|
|
62
|
+
displayName: component['display_name'] ?? component['rule_id'],
|
|
63
|
+
rqlFormula: component['rql_formula'] ?? '',
|
|
64
|
+
errorMessage: component['custom_error_message'] ?? '',
|
|
65
|
+
state: component['state'],
|
|
66
|
+
level: component['level'],
|
|
67
|
+
ruleDescription: component['rule_description'] ?? '',
|
|
68
|
+
};
|
|
69
|
+
if (component['field_rql_name'] != null)
|
|
70
|
+
props.fieldRef = resolveField(component['field_rql_name']);
|
|
71
|
+
return new Validation(customObject, props);
|
|
72
|
+
}
|
|
44
73
|
/**
|
|
45
74
|
* Returns the stable identifier for this validation rule (e.g. `'gym_session_end_after_start'`).
|
|
46
75
|
*/
|
|
@@ -61,7 +90,7 @@ export class Validation {
|
|
|
61
90
|
*/
|
|
62
91
|
toDict() {
|
|
63
92
|
const component = {
|
|
64
|
-
type:
|
|
93
|
+
type: Validation.componentType,
|
|
65
94
|
model_rql_name: this._customObjectApiName,
|
|
66
95
|
rule_id: this._ruleId,
|
|
67
96
|
state: this._state,
|
|
@@ -76,4 +105,5 @@ export class Validation {
|
|
|
76
105
|
return component;
|
|
77
106
|
}
|
|
78
107
|
}
|
|
108
|
+
Validation.componentType = 'CUSTOM_OBJECT_VALIDATION_RULE';
|
|
79
109
|
//# sourceMappingURL=validation.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.mjs","sourceRoot":"","sources":["../../src/lib/manifest/validation.ts"],"names":[],"mappings":"OAAO,EAAE,UAAU,EAA8C;
|
|
1
|
+
{"version":3,"file":"validation.mjs","sourceRoot":"","sources":["../../src/lib/manifest/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/lib/manifest/app.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CustomObject } from './custom-object';
|
|
2
|
-
import type
|
|
2
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
3
|
+
import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder';
|
|
3
4
|
import { SduiPage } from './sdui-page';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -82,6 +83,11 @@ function resolvePage(entry: AppPage): Record<string, any> {
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
function cloneJson<T>(value: T): T {
|
|
87
|
+
if (value == null) return value;
|
|
88
|
+
return JSON.parse(JSON.stringify(value)) as T;
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
/**
|
|
86
92
|
* Defines a Rippling app and registers it with the manifest.
|
|
87
93
|
*
|
|
@@ -105,6 +111,15 @@ function resolvePage(entry: AppPage): Record<string, any> {
|
|
|
105
111
|
* @see {@link SduiPage} — SDUI surface tab source.
|
|
106
112
|
*/
|
|
107
113
|
export class App {
|
|
114
|
+
static readonly componentType = 'CUSTOM_APP' as const;
|
|
115
|
+
|
|
116
|
+
static toDeletionIdentifier(apiName: string): ManifestComponentDeletion {
|
|
117
|
+
return {
|
|
118
|
+
type: App.componentType,
|
|
119
|
+
api_name: apiName,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
108
123
|
private readonly _apiName: string;
|
|
109
124
|
private readonly _name: string;
|
|
110
125
|
private readonly _description: string | undefined;
|
|
@@ -127,6 +142,35 @@ export class App {
|
|
|
127
142
|
scope._register(this);
|
|
128
143
|
}
|
|
129
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Loads this app from the active existing-manifest JSON context.
|
|
147
|
+
*/
|
|
148
|
+
static loadFromExisting(apiName: string, options: ExistingManifestContextOptions = {}): App {
|
|
149
|
+
return getExistingManifestContext(options).loadApp(apiName);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** @internal Hydrates an app from existing manifest wire JSON. */
|
|
153
|
+
static _fromExistingComponent(scope: ManifestScope, component: Record<string, any>): App {
|
|
154
|
+
const app = Object.create(App.prototype) as App;
|
|
155
|
+
Object.assign(app as Record<string, any>, {
|
|
156
|
+
_apiName: component['api_name'],
|
|
157
|
+
_name: component['name'] ?? component['api_name'],
|
|
158
|
+
_description: component['description'],
|
|
159
|
+
_appType: component['app_type'],
|
|
160
|
+
_icon: App.appIconFromExistingComponent(component['icon']),
|
|
161
|
+
_pages: cloneJson(component['pages'] ?? []),
|
|
162
|
+
});
|
|
163
|
+
scope._register(app);
|
|
164
|
+
return app;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static appIconFromExistingComponent(value: unknown): AppIcon | undefined {
|
|
168
|
+
if (value == null || typeof value !== 'object') return undefined;
|
|
169
|
+
const wire = value as Record<string, any>;
|
|
170
|
+
if (typeof wire['s3_bucket'] !== 'string' || typeof wire['s3_key'] !== 'string') return undefined;
|
|
171
|
+
return { s3Bucket: wire['s3_bucket'], s3Key: wire['s3_key'] };
|
|
172
|
+
}
|
|
173
|
+
|
|
130
174
|
/**
|
|
131
175
|
* Returns the api_name of this app (e.g. `'gym_membership_management_app'`).
|
|
132
176
|
*/
|
|
@@ -148,7 +192,7 @@ export class App {
|
|
|
148
192
|
*/
|
|
149
193
|
toDict(): Record<string, any> {
|
|
150
194
|
const component: Record<string, any> = {
|
|
151
|
-
type:
|
|
195
|
+
type: App.componentType,
|
|
152
196
|
api_name: this._apiName,
|
|
153
197
|
name: this._name,
|
|
154
198
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
2
|
+
import type { ManifestComponentDeletion, ManifestScope } from './manifest-builder';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Initialization properties for {@link Category}.
|
|
@@ -57,6 +58,15 @@ export interface CategoryProps {
|
|
|
57
58
|
* @see {@link CustomObject} — references this category via instance or api_name string.
|
|
58
59
|
*/
|
|
59
60
|
export class Category {
|
|
61
|
+
static readonly componentType = 'CUSTOM_CATEGORY' as const;
|
|
62
|
+
|
|
63
|
+
static toDeletionIdentifier(apiName: string): ManifestComponentDeletion {
|
|
64
|
+
return {
|
|
65
|
+
type: Category.componentType,
|
|
66
|
+
api_name: apiName,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
60
70
|
private readonly _apiName: string;
|
|
61
71
|
private readonly _name: string;
|
|
62
72
|
private readonly _description: string;
|
|
@@ -72,6 +82,22 @@ export class Category {
|
|
|
72
82
|
scope._register(this);
|
|
73
83
|
}
|
|
74
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Loads this category from the active existing-manifest JSON context.
|
|
87
|
+
*/
|
|
88
|
+
static loadFromExisting(apiName: string, options: ExistingManifestContextOptions = {}): Category {
|
|
89
|
+
return getExistingManifestContext(options).loadCategory(apiName);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** @internal Hydrates a category from existing manifest wire JSON. */
|
|
93
|
+
static _fromExistingComponent(scope: ManifestScope, component: Record<string, any>): Category {
|
|
94
|
+
return new Category(scope, {
|
|
95
|
+
apiName: component['api_name'],
|
|
96
|
+
name: component['name'] ?? component['api_name'],
|
|
97
|
+
description: component['description'] ?? '',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
75
101
|
/**
|
|
76
102
|
* Returns the api_name of this category (e.g. `'gym__c'`).
|
|
77
103
|
*/
|
|
@@ -93,7 +119,7 @@ export class Category {
|
|
|
93
119
|
*/
|
|
94
120
|
toDict(): Record<string, any> {
|
|
95
121
|
return {
|
|
96
|
-
type:
|
|
122
|
+
type: Category.componentType,
|
|
97
123
|
api_name: this._apiName,
|
|
98
124
|
name: this._name,
|
|
99
125
|
description: this._description,
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { generateId } from './_helpers';
|
|
2
2
|
import type { CustomObject } from './custom-object';
|
|
3
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
4
|
+
import type { ManifestComponentDeletion } from './manifest-builder';
|
|
5
|
+
|
|
6
|
+
export interface CustomObjectFieldSectionLoadFromExistingOptions extends ExistingManifestContextOptions {
|
|
7
|
+
customObjectApiName?: string;
|
|
8
|
+
}
|
|
3
9
|
|
|
4
10
|
/**
|
|
5
11
|
* Initialization properties for {@link CustomObjectFieldSection}.
|
|
@@ -45,6 +51,15 @@ export interface CustomObjectFieldSectionProps {
|
|
|
45
51
|
* @see {@link CustomObjectPageLayout} — controls which sections appear on which tab.
|
|
46
52
|
*/
|
|
47
53
|
export class CustomObjectFieldSection {
|
|
54
|
+
static readonly componentType = 'CUSTOM_OBJECT_FIELD_SECTION' as const;
|
|
55
|
+
|
|
56
|
+
static toDeletionIdentifier(sectionId: string): ManifestComponentDeletion {
|
|
57
|
+
return {
|
|
58
|
+
type: CustomObjectFieldSection.componentType,
|
|
59
|
+
section_id: sectionId,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
private readonly _sectionId: string;
|
|
49
64
|
private readonly _name: string;
|
|
50
65
|
private readonly _model: CustomObject;
|
|
@@ -60,6 +75,27 @@ export class CustomObjectFieldSection {
|
|
|
60
75
|
customObject._register(this);
|
|
61
76
|
}
|
|
62
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Loads this field section from the active existing-manifest JSON context.
|
|
80
|
+
*/
|
|
81
|
+
static loadFromExisting(
|
|
82
|
+
sectionId: string,
|
|
83
|
+
options: CustomObjectFieldSectionLoadFromExistingOptions = {},
|
|
84
|
+
): CustomObjectFieldSection {
|
|
85
|
+
return getExistingManifestContext(options).loadFieldSection(sectionId, options);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** @internal Hydrates a field section from existing manifest wire JSON. */
|
|
89
|
+
static _fromExistingComponent(
|
|
90
|
+
customObject: CustomObject,
|
|
91
|
+
component: Record<string, any>,
|
|
92
|
+
): CustomObjectFieldSection {
|
|
93
|
+
return new CustomObjectFieldSection(customObject, {
|
|
94
|
+
sectionId: component['section_id'],
|
|
95
|
+
name: component['name'] ?? component['section_id'],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
63
99
|
/**
|
|
64
100
|
* Returns the stable identifier for this section (e.g. `'sec_gm_profile'`).
|
|
65
101
|
*
|
|
@@ -91,7 +127,7 @@ export class CustomObjectFieldSection {
|
|
|
91
127
|
*/
|
|
92
128
|
toDict(): Record<string, any> {
|
|
93
129
|
return {
|
|
94
|
-
type:
|
|
130
|
+
type: CustomObjectFieldSection.componentType,
|
|
95
131
|
section_id: this._sectionId,
|
|
96
132
|
model_name: this._model.getApiName(),
|
|
97
133
|
name: this._name,
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { generateId } from './_helpers';
|
|
2
2
|
import { CustomObjectFieldSection } from './custom-object-field-section';
|
|
3
3
|
import type { CustomObject } from './custom-object';
|
|
4
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
4
5
|
import type { Field } from './field';
|
|
6
|
+
import type { ManifestComponentDeletion } from './manifest-builder';
|
|
7
|
+
|
|
8
|
+
export interface PageLayoutDeletionIdentifier {
|
|
9
|
+
layoutId: string;
|
|
10
|
+
objectRqlName: string;
|
|
11
|
+
}
|
|
5
12
|
|
|
6
13
|
// ---------------------------------------------------------------------------
|
|
7
14
|
// header_edits — HeaderEditsDTO
|
|
@@ -267,6 +274,10 @@ export interface CustomObjectPageLayoutProps {
|
|
|
267
274
|
blueprintKey?: string;
|
|
268
275
|
}
|
|
269
276
|
|
|
277
|
+
export interface CustomObjectPageLayoutLoadFromExistingOptions extends ExistingManifestContextOptions {
|
|
278
|
+
customObjectApiName?: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
270
281
|
interface SerializedSectionField extends SectionFieldOptions {
|
|
271
282
|
fieldRqlName: string;
|
|
272
283
|
}
|
|
@@ -458,6 +469,11 @@ function normalizeTabEdits(customObject: CustomObject, tabEdits: TabEdits): Seri
|
|
|
458
469
|
return normalized;
|
|
459
470
|
}
|
|
460
471
|
|
|
472
|
+
function cloneJson<T>(value: T): T {
|
|
473
|
+
if (value == null) return value;
|
|
474
|
+
return JSON.parse(JSON.stringify(value)) as T;
|
|
475
|
+
}
|
|
476
|
+
|
|
461
477
|
// ---------------------------------------------------------------------------
|
|
462
478
|
// Class
|
|
463
479
|
// ---------------------------------------------------------------------------
|
|
@@ -503,6 +519,16 @@ function normalizeTabEdits(customObject: CustomObject, tabEdits: TabEdits): Seri
|
|
|
503
519
|
* @see {@link CustomObjectPageLayout.basic} — factory for simple single-tab layouts.
|
|
504
520
|
*/
|
|
505
521
|
export class CustomObjectPageLayout {
|
|
522
|
+
static readonly componentType = 'CUSTOM_OBJECT_PAGE_LAYOUT' as const;
|
|
523
|
+
|
|
524
|
+
static toDeletionIdentifier(identifier: PageLayoutDeletionIdentifier): ManifestComponentDeletion {
|
|
525
|
+
return {
|
|
526
|
+
type: CustomObjectPageLayout.componentType,
|
|
527
|
+
layout_id: identifier.layoutId,
|
|
528
|
+
object_rql_name: identifier.objectRqlName,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
506
532
|
private readonly _layoutId: string;
|
|
507
533
|
private readonly _apiName: string;
|
|
508
534
|
private readonly _customObjectApiName: string;
|
|
@@ -531,6 +557,40 @@ export class CustomObjectPageLayout {
|
|
|
531
557
|
customObject._register(this);
|
|
532
558
|
}
|
|
533
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Loads this page layout from the active existing-manifest JSON context.
|
|
562
|
+
*
|
|
563
|
+
* `id` resolves against `layout_id` first, then `api_name`. When loading by
|
|
564
|
+
* api_name such as `'default'`, pass `customObjectApiName` if multiple objects
|
|
565
|
+
* have a layout with the same api_name.
|
|
566
|
+
*/
|
|
567
|
+
static loadFromExisting(
|
|
568
|
+
layoutIdOrApiName: string,
|
|
569
|
+
options: CustomObjectPageLayoutLoadFromExistingOptions = {},
|
|
570
|
+
): CustomObjectPageLayout {
|
|
571
|
+
return getExistingManifestContext(options).loadPageLayout(layoutIdOrApiName, options);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** @internal Hydrates a page layout from existing manifest wire JSON. */
|
|
575
|
+
static _fromExistingComponent(
|
|
576
|
+
customObject: CustomObject,
|
|
577
|
+
component: Record<string, any>,
|
|
578
|
+
): CustomObjectPageLayout {
|
|
579
|
+
const layout = Object.create(CustomObjectPageLayout.prototype) as CustomObjectPageLayout;
|
|
580
|
+
Object.assign(layout as Record<string, any>, {
|
|
581
|
+
_layoutId: component['layout_id'],
|
|
582
|
+
_apiName: component['api_name'],
|
|
583
|
+
_customObjectApiName: component['object_rql_name'],
|
|
584
|
+
_name: component['name'] ?? component['api_name'],
|
|
585
|
+
_tabEdits: cloneJson(component['tab_edits'] ?? {}),
|
|
586
|
+
_headerEdits: cloneJson(component['header_edits'] ?? {}),
|
|
587
|
+
_visibilityConditions: cloneJson(component['visibility_conditions'] ?? {}),
|
|
588
|
+
_blueprintKey: component['blueprint_key'],
|
|
589
|
+
});
|
|
590
|
+
customObject._register(layout);
|
|
591
|
+
return layout;
|
|
592
|
+
}
|
|
593
|
+
|
|
534
594
|
/**
|
|
535
595
|
* Returns the stable identifier for this layout record (e.g. `'layout_gym_member'`).
|
|
536
596
|
*/
|
|
@@ -559,7 +619,7 @@ export class CustomObjectPageLayout {
|
|
|
559
619
|
*/
|
|
560
620
|
toDict(): Record<string, any> {
|
|
561
621
|
const d: Record<string, any> = {
|
|
562
|
-
type:
|
|
622
|
+
type: CustomObjectPageLayout.componentType,
|
|
563
623
|
layout_id: this._layoutId,
|
|
564
624
|
api_name: this._apiName,
|
|
565
625
|
object_rql_name: this._customObjectApiName,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Category } from './category';
|
|
2
|
-
import
|
|
2
|
+
import { getExistingManifestContext, type ExistingManifestContextOptions } from './existing-manifest-context';
|
|
3
|
+
import type { ManifestComponent, ManifestComponentDeletion, ManifestScope } from './manifest-builder';
|
|
3
4
|
|
|
4
5
|
// ────────────────────────────────────────────────────────────────────────
|
|
5
6
|
// Platform-managed standard fields — mirrors
|
|
@@ -113,6 +114,8 @@ const STANDARD_FIELD_SPECS: ReadonlyArray<{
|
|
|
113
114
|
* (`id`, `created_at`, …) don't carry the custom-field suffix.
|
|
114
115
|
*/
|
|
115
116
|
class _StandardField implements ManifestComponent {
|
|
117
|
+
static readonly componentType = 'CUSTOM_OBJECT_FIELD' as const;
|
|
118
|
+
|
|
116
119
|
constructor(
|
|
117
120
|
private readonly customObjectApiName: string,
|
|
118
121
|
private readonly spec: (typeof STANDARD_FIELD_SPECS)[number],
|
|
@@ -120,7 +123,7 @@ class _StandardField implements ManifestComponent {
|
|
|
120
123
|
|
|
121
124
|
toDict(): Record<string, any> {
|
|
122
125
|
return {
|
|
123
|
-
type:
|
|
126
|
+
type: _StandardField.componentType,
|
|
124
127
|
custom_object_api_name: this.customObjectApiName,
|
|
125
128
|
field_api_name: this.spec.apiName,
|
|
126
129
|
field_display_name: this.spec.displayName,
|
|
@@ -297,6 +300,15 @@ export interface CustomObjectProps {
|
|
|
297
300
|
* can fragment ownership and complicate the permission story.
|
|
298
301
|
*/
|
|
299
302
|
export class CustomObject implements ManifestScope {
|
|
303
|
+
static readonly componentType = 'CUSTOM_OBJECT' as const;
|
|
304
|
+
|
|
305
|
+
static toDeletionIdentifier(apiName: string): ManifestComponentDeletion {
|
|
306
|
+
return {
|
|
307
|
+
type: CustomObject.componentType,
|
|
308
|
+
api_name: apiName,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
300
312
|
private readonly _scope: ManifestScope;
|
|
301
313
|
private readonly _apiName: string;
|
|
302
314
|
private readonly _name: string;
|
|
@@ -333,6 +345,49 @@ export class CustomObject implements ManifestScope {
|
|
|
333
345
|
}
|
|
334
346
|
}
|
|
335
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Loads this custom object from the active existing-manifest JSON context.
|
|
350
|
+
*/
|
|
351
|
+
static loadFromExisting(apiName: string, options: ExistingManifestContextOptions = {}): CustomObject {
|
|
352
|
+
return getExistingManifestContext(options).loadCustomObject(apiName);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** @internal Hydrates a custom object from existing manifest wire JSON. */
|
|
356
|
+
static _fromExistingComponent(
|
|
357
|
+
scope: ManifestScope,
|
|
358
|
+
component: Record<string, any>,
|
|
359
|
+
resolveCategory: (apiName: string) => Category | string,
|
|
360
|
+
): CustomObject {
|
|
361
|
+
const categoryApiName = component['category_api_name'];
|
|
362
|
+
const props: CustomObjectProps = {
|
|
363
|
+
apiName: component['api_name'],
|
|
364
|
+
name: component['name'] ?? component['api_name'],
|
|
365
|
+
category: typeof categoryApiName === 'string' ? resolveCategory(categoryApiName) : categoryApiName,
|
|
366
|
+
};
|
|
367
|
+
if (component['description'] !== undefined) props.description = component['description'];
|
|
368
|
+
if (component['plural_label'] !== undefined) props.pluralLabel = component['plural_label'];
|
|
369
|
+
if (component['name_field_details'] !== undefined) {
|
|
370
|
+
props.nameFieldDetails = component['name_field_details'];
|
|
371
|
+
}
|
|
372
|
+
if (component['default_field_section_name'] !== undefined) {
|
|
373
|
+
props.defaultFieldSectionName = component['default_field_section_name'];
|
|
374
|
+
}
|
|
375
|
+
const icon = CustomObject.iconFromExistingComponent(component['icon']);
|
|
376
|
+
if (icon != null) props.icon = icon;
|
|
377
|
+
return new CustomObject(scope, props);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private static iconFromExistingComponent(value: unknown): IconConfig | undefined {
|
|
381
|
+
if (value == null || typeof value !== 'object') return undefined;
|
|
382
|
+
const wire = value as Record<string, any>;
|
|
383
|
+
const icon: IconConfig = {};
|
|
384
|
+
if (wire['emoji'] !== undefined) icon.emoji = wire['emoji'];
|
|
385
|
+
if (wire['rippling_icon'] !== undefined) icon.ripplingIcon = wire['rippling_icon'];
|
|
386
|
+
if (wire['s3_bucket'] !== undefined) icon.s3Bucket = wire['s3_bucket'];
|
|
387
|
+
if (wire['s3_key'] !== undefined) icon.s3Key = wire['s3_key'];
|
|
388
|
+
return Object.keys(icon).length > 0 ? icon : undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
336
391
|
/** @internal Scope hook — forwards child registration up to the root builder. */
|
|
337
392
|
_register(component: ManifestComponent): void {
|
|
338
393
|
this._scope._register(component);
|
|
@@ -362,7 +417,7 @@ export class CustomObject implements ManifestScope {
|
|
|
362
417
|
*/
|
|
363
418
|
toDict(): Record<string, any> {
|
|
364
419
|
const component: Record<string, any> = {
|
|
365
|
-
type:
|
|
420
|
+
type: CustomObject.componentType,
|
|
366
421
|
api_name: this._apiName,
|
|
367
422
|
name: this._name,
|
|
368
423
|
description: this._description ?? null,
|