@rippling/rippling-sdk 0.2.0-alpha.32 → 0.2.0-alpha.34
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/client.d.mts +8 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +8 -2
- package/client.d.ts.map +1 -1
- package/client.js +17 -0
- package/client.js.map +1 -1
- package/client.mjs +17 -0
- package/client.mjs.map +1 -1
- package/internal/types.d.mts +6 -6
- package/internal/types.d.mts.map +1 -1
- package/internal/types.d.ts +6 -6
- package/internal/types.d.ts.map +1 -1
- package/lib/manifest/_helpers.d.mts +91 -0
- package/lib/manifest/_helpers.d.mts.map +1 -0
- package/lib/manifest/_helpers.d.ts +91 -0
- package/lib/manifest/_helpers.d.ts.map +1 -0
- package/lib/manifest/_helpers.js +65 -0
- package/lib/manifest/_helpers.js.map +1 -0
- package/lib/manifest/_helpers.mjs +61 -0
- package/lib/manifest/_helpers.mjs.map +1 -0
- package/lib/manifest/app.d.mts +45 -0
- package/lib/manifest/app.d.mts.map +1 -0
- package/lib/manifest/app.d.ts +45 -0
- package/lib/manifest/app.d.ts.map +1 -0
- package/lib/manifest/app.js +74 -0
- package/lib/manifest/app.js.map +1 -0
- package/lib/manifest/app.mjs +70 -0
- package/lib/manifest/app.mjs.map +1 -0
- package/lib/manifest/category.d.mts +23 -0
- package/lib/manifest/category.d.mts.map +1 -0
- package/lib/manifest/category.d.ts +23 -0
- package/lib/manifest/category.d.ts.map +1 -0
- package/lib/manifest/category.js +37 -0
- package/lib/manifest/category.js.map +1 -0
- package/lib/manifest/category.mjs +33 -0
- package/lib/manifest/category.mjs.map +1 -0
- package/lib/manifest/custom-object-field-section.d.mts +21 -0
- package/lib/manifest/custom-object-field-section.d.mts.map +1 -0
- package/lib/manifest/custom-object-field-section.d.ts +21 -0
- package/lib/manifest/custom-object-field-section.d.ts.map +1 -0
- package/lib/manifest/custom-object-field-section.js +42 -0
- package/lib/manifest/custom-object-field-section.js.map +1 -0
- package/lib/manifest/custom-object-field-section.mjs +38 -0
- package/lib/manifest/custom-object-field-section.mjs.map +1 -0
- package/lib/manifest/custom-object-page-layout.d.mts +158 -0
- package/lib/manifest/custom-object-page-layout.d.mts.map +1 -0
- package/lib/manifest/custom-object-page-layout.d.ts +158 -0
- package/lib/manifest/custom-object-page-layout.d.ts.map +1 -0
- package/lib/manifest/custom-object-page-layout.js +112 -0
- package/lib/manifest/custom-object-page-layout.js.map +1 -0
- package/lib/manifest/custom-object-page-layout.mjs +108 -0
- package/lib/manifest/custom-object-page-layout.mjs.map +1 -0
- package/lib/manifest/custom-object.d.mts +52 -0
- package/lib/manifest/custom-object.d.mts.map +1 -0
- package/lib/manifest/custom-object.d.ts +52 -0
- package/lib/manifest/custom-object.d.ts.map +1 -0
- package/lib/manifest/custom-object.js +219 -0
- package/lib/manifest/custom-object.js.map +1 -0
- package/lib/manifest/custom-object.mjs +215 -0
- package/lib/manifest/custom-object.mjs.map +1 -0
- package/lib/manifest/field.d.mts +276 -0
- package/lib/manifest/field.d.mts.map +1 -0
- package/lib/manifest/field.d.ts +276 -0
- package/lib/manifest/field.d.ts.map +1 -0
- package/lib/manifest/field.js +418 -0
- package/lib/manifest/field.js.map +1 -0
- package/lib/manifest/field.mjs +395 -0
- package/lib/manifest/field.mjs.map +1 -0
- package/lib/manifest/index.d.mts +15 -0
- package/lib/manifest/index.d.mts.map +1 -0
- package/lib/manifest/index.d.ts +15 -0
- package/lib/manifest/index.d.ts.map +1 -0
- package/lib/manifest/index.js +53 -0
- package/lib/manifest/index.js.map +1 -0
- package/lib/manifest/index.mjs +18 -0
- package/lib/manifest/index.mjs.map +1 -0
- package/lib/manifest/list-view.d.mts +47 -0
- package/lib/manifest/list-view.d.mts.map +1 -0
- package/lib/manifest/list-view.d.ts +47 -0
- package/lib/manifest/list-view.d.ts.map +1 -0
- package/lib/manifest/list-view.js +73 -0
- package/lib/manifest/list-view.js.map +1 -0
- package/lib/manifest/list-view.mjs +69 -0
- package/lib/manifest/list-view.mjs.map +1 -0
- package/lib/manifest/manifest-builder.d.mts +44 -0
- package/lib/manifest/manifest-builder.d.mts.map +1 -0
- package/lib/manifest/manifest-builder.d.ts +44 -0
- package/lib/manifest/manifest-builder.d.ts.map +1 -0
- package/lib/manifest/manifest-builder.js +69 -0
- package/lib/manifest/manifest-builder.js.map +1 -0
- package/lib/manifest/manifest-builder.mjs +65 -0
- package/lib/manifest/manifest-builder.mjs.map +1 -0
- package/lib/manifest/manifest-function.d.mts +39 -0
- package/lib/manifest/manifest-function.d.mts.map +1 -0
- package/lib/manifest/manifest-function.d.ts +39 -0
- package/lib/manifest/manifest-function.d.ts.map +1 -0
- package/lib/manifest/manifest-function.js +56 -0
- package/lib/manifest/manifest-function.js.map +1 -0
- package/lib/manifest/manifest-function.mjs +52 -0
- package/lib/manifest/manifest-function.mjs.map +1 -0
- package/lib/manifest/rule.d.mts +50 -0
- package/lib/manifest/rule.d.mts.map +1 -0
- package/lib/manifest/rule.d.ts +50 -0
- package/lib/manifest/rule.d.ts.map +1 -0
- package/lib/manifest/rule.js +84 -0
- package/lib/manifest/rule.js.map +1 -0
- package/lib/manifest/rule.mjs +80 -0
- package/lib/manifest/rule.mjs.map +1 -0
- package/lib/manifest/sdui-page.d.mts +33 -0
- package/lib/manifest/sdui-page.d.mts.map +1 -0
- package/lib/manifest/sdui-page.d.ts +33 -0
- package/lib/manifest/sdui-page.d.ts.map +1 -0
- package/lib/manifest/sdui-page.js +52 -0
- package/lib/manifest/sdui-page.js.map +1 -0
- package/lib/manifest/sdui-page.mjs +48 -0
- package/lib/manifest/sdui-page.mjs.map +1 -0
- package/lib/manifest/validation.d.mts +41 -0
- package/lib/manifest/validation.d.mts.map +1 -0
- package/lib/manifest/validation.d.ts +41 -0
- package/lib/manifest/validation.d.ts.map +1 -0
- package/lib/manifest/validation.js +57 -0
- package/lib/manifest/validation.js.map +1 -0
- package/lib/manifest/validation.mjs +53 -0
- package/lib/manifest/validation.mjs.map +1 -0
- package/package.json +11 -1
- package/resources/draft-hires.d.mts +22 -0
- package/resources/draft-hires.d.mts.map +1 -1
- package/resources/draft-hires.d.ts +22 -0
- package/resources/draft-hires.d.ts.map +1 -1
- package/resources/earnings-inputs.d.mts +104 -1
- package/resources/earnings-inputs.d.mts.map +1 -1
- package/resources/earnings-inputs.d.ts +104 -1
- package/resources/earnings-inputs.d.ts.map +1 -1
- package/resources/earnings-inputs.js +17 -0
- package/resources/earnings-inputs.js.map +1 -1
- package/resources/earnings-inputs.mjs +17 -0
- package/resources/earnings-inputs.mjs.map +1 -1
- package/resources/files.d.mts +149 -0
- package/resources/files.d.mts.map +1 -0
- package/resources/files.d.ts +149 -0
- package/resources/files.d.ts.map +1 -0
- package/resources/files.js +25 -0
- package/resources/files.js.map +1 -0
- package/resources/files.mjs +21 -0
- package/resources/files.mjs.map +1 -0
- package/resources/index.d.mts +2 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +2 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +4 -2
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +1 -0
- package/resources/index.mjs.map +1 -1
- package/resources/object-categories.d.mts +1 -1
- package/resources/object-categories.d.ts +1 -1
- package/resources/object-categories.js +1 -1
- package/resources/object-categories.mjs +1 -1
- package/resources/report-runs.d.mts +11 -11
- package/resources/report-runs.d.ts +11 -11
- package/resources/workflow-action-executions.d.mts +17 -2
- package/resources/workflow-action-executions.d.mts.map +1 -1
- package/resources/workflow-action-executions.d.ts +17 -2
- package/resources/workflow-action-executions.d.ts.map +1 -1
- package/src/client.ts +29 -0
- package/src/internal/types.ts +6 -8
- package/src/lib/manifest/_helpers.ts +164 -0
- package/src/lib/manifest/app.ts +108 -0
- package/src/lib/manifest/category.ts +51 -0
- package/src/lib/manifest/custom-object-field-section.ts +54 -0
- package/src/lib/manifest/custom-object-page-layout.ts +292 -0
- package/src/lib/manifest/custom-object.ts +269 -0
- package/src/lib/manifest/field.ts +632 -0
- package/src/lib/manifest/index.ts +114 -0
- package/src/lib/manifest/list-view.ts +103 -0
- package/src/lib/manifest/manifest-builder.ts +97 -0
- package/src/lib/manifest/manifest-function.ts +81 -0
- package/src/lib/manifest/rule.ts +125 -0
- package/src/lib/manifest/sdui-page.ts +72 -0
- package/src/lib/manifest/validation.ts +87 -0
- package/src/resources/draft-hires.ts +26 -0
- package/src/resources/earnings-inputs.ts +140 -0
- package/src/resources/files.ts +186 -0
- package/src/resources/index.ts +3 -0
- package/src/resources/object-categories.ts +1 -1
- package/src/resources/report-runs.ts +32 -32
- package/src/resources/workflow-action-executions.ts +22 -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
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The contents of this file were inserted manually and are not generated by Stainless.
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers and enum types for the manifest builder.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
let _counter = 0;
|
|
8
|
+
|
|
9
|
+
/** Generate a short unique ID string (e.g. "id_a3f1b2"). */
|
|
10
|
+
export function generateId(prefix = 'id'): string {
|
|
11
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
12
|
+
return `${prefix}_${rand}${(_counter++).toString(36)}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Enum types for strongly-typed setters
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
/** Record-triggered flow trigger type. */
|
|
20
|
+
export type TriggerType = 'CREATE' | 'UPDATE' | 'CREATE_OR_UPDATE';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Update-trigger condition type. Mirrors the backend
|
|
24
|
+
* `FlowUpdateTriggerBehavior` enum (`constants.py`). Note the `OR_AFTER`
|
|
25
|
+
* spelling — `BEFORE_AND_AFTER` is a common typo that /validate will reject.
|
|
26
|
+
*/
|
|
27
|
+
export type UpdateTriggerType = 'MEETS_CONDITION_AFTER_ONLY' | 'MEETS_CONDITION_BEFORE_OR_AFTER';
|
|
28
|
+
|
|
29
|
+
/** Validation rule state. */
|
|
30
|
+
export type ValidationState = 'ACTIVE' | 'INACTIVE';
|
|
31
|
+
|
|
32
|
+
/** Validation rule level. */
|
|
33
|
+
export type ValidationLevel = 'RECORD' | 'FIELD';
|
|
34
|
+
|
|
35
|
+
/** Sort direction for list views. */
|
|
36
|
+
export type SortOrder = 'ASC' | 'DESC';
|
|
37
|
+
|
|
38
|
+
/** Scope for list views. */
|
|
39
|
+
export type ObjectScope = 'all' | 'my_records';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Supported `data_type.field_type` values for CUSTOM_OBJECT_FIELD and
|
|
43
|
+
* CUSTOM_FIELD_V2. Note: lookup and parent-child relationships both use
|
|
44
|
+
* `field_type: 'OG_REFERENCE_FIELD'` and are differentiated by `edge_type`
|
|
45
|
+
* (see `EdgeType`). `'LOOKUP'` and `'PARENT_CHILD'` are NOT valid
|
|
46
|
+
* `field_type` values — emitting them produces invalid manifests.
|
|
47
|
+
*/
|
|
48
|
+
export type FieldType =
|
|
49
|
+
| 'TEXT'
|
|
50
|
+
| 'LONG_TEXT'
|
|
51
|
+
| 'EMAIL'
|
|
52
|
+
| 'URL'
|
|
53
|
+
| 'PHONE_NUMBER'
|
|
54
|
+
| 'NUMBER'
|
|
55
|
+
| 'CURRENCY'
|
|
56
|
+
| 'PERCENTAGE'
|
|
57
|
+
| 'DATE'
|
|
58
|
+
| 'DATETIME'
|
|
59
|
+
| 'TIME'
|
|
60
|
+
| 'SELECT'
|
|
61
|
+
| 'RADIO'
|
|
62
|
+
| 'BOOLEAN'
|
|
63
|
+
| 'FILE'
|
|
64
|
+
| 'OG_REFERENCE_FIELD';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Discriminator for `OG_REFERENCE_FIELD` data types — distinguishes a plain
|
|
68
|
+
* lookup from a parent-child relationship.
|
|
69
|
+
*/
|
|
70
|
+
export type EdgeType = 'LOOKUP' | 'PARENT_CHILD';
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Allowed output `field_type` for Simple Formula Fields. Mirrors the UI
|
|
74
|
+
* "Data type" dropdown in the formula field editor — backend `field_type` is
|
|
75
|
+
* free-form `str`, but the product only validates these 7 variants end-to-end.
|
|
76
|
+
*/
|
|
77
|
+
export type FormulaFieldType = 'TEXT' | 'NUMBER' | 'BOOLEAN' | 'CURRENCY' | 'PERCENTAGE' | 'DATE' | 'URL';
|
|
78
|
+
|
|
79
|
+
/** Runtime for FUNCTION component. */
|
|
80
|
+
export type FunctionRuntime = 'cloudflare-js' | 'lambda-deno' | 'lambda-python';
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Page type inside CUSTOM_APP. Mirrors the backend `PageType` enum
|
|
84
|
+
* (`pages.py`). The SDK currently models the two surfaces it supports —
|
|
85
|
+
* object pages and SDUI pages. `function_page` is NOT a valid backend token;
|
|
86
|
+
* wrap a function in an SDUI page instead.
|
|
87
|
+
*/
|
|
88
|
+
export type PageType = 'object_page' | 'sdui_page';
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Summary-field constants (for Field.summary)
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
/** Backend supports exactly these four (`constants.py:1316`). */
|
|
95
|
+
export type SummaryAggregation = 'COUNT' | 'SUM' | 'MIN' | 'MAX';
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* RQL operator for summary filters. Scalar-only, matching the admin
|
|
99
|
+
* condition-builder dropdown.
|
|
100
|
+
*
|
|
101
|
+
* The backend's RQL engine accepts a wider set (WHERE_CLAUSE_OPERATORS
|
|
102
|
+
* includes `LIKE`, `ILIKE`, `IN`, `CONTAINS`, …), but summary filters
|
|
103
|
+
* authored by the UI are restricted to plain scalar comparisons. Emitting
|
|
104
|
+
* anything else from the SDK produces a manifest that /validate accepts
|
|
105
|
+
* but the admin UI cannot render or edit — a split-brain config.
|
|
106
|
+
*/
|
|
107
|
+
export type SummaryFilterOperator =
|
|
108
|
+
| '='
|
|
109
|
+
| '!=' // equality (all scalar types)
|
|
110
|
+
| '>'
|
|
111
|
+
| '>='
|
|
112
|
+
| '<'
|
|
113
|
+
| '<='; // ordered numeric / currency / date
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Mirrors `DERIVED_AGGREGATION_FUNCTIONS_AND_SUPPORTED_TYPES` (constants.py:1316).
|
|
117
|
+
* The output field_type of a summary must be in the aggregation function's
|
|
118
|
+
* supported set. For non-COUNT, backend further requires the output to equal
|
|
119
|
+
* the aggregated field's field_type (parent_child_util.py:217-220).
|
|
120
|
+
*/
|
|
121
|
+
export const ALLOWED_SUMMARY_OUTPUT: Record<SummaryAggregation, ReadonlySet<FieldType>> = {
|
|
122
|
+
COUNT: new Set(['NUMBER']),
|
|
123
|
+
SUM: new Set(['NUMBER', 'PERCENTAGE', 'CURRENCY']),
|
|
124
|
+
MIN: new Set(['NUMBER', 'PERCENTAGE', 'DATE', 'DATETIME', 'TIME', 'CURRENCY']),
|
|
125
|
+
MAX: new Set(['NUMBER', 'PERCENTAGE', 'DATE', 'DATETIME', 'TIME', 'CURRENCY']),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Per-field-type allow-list for summary filter operators, mirroring the
|
|
130
|
+
* admin condition-builder picker.
|
|
131
|
+
*
|
|
132
|
+
* This is also the single source of truth for "which field types can be
|
|
133
|
+
* used as a summary filter at all": field types **absent from this map**
|
|
134
|
+
* are rejected as filter fields entirely. The UI-hidden types are:
|
|
135
|
+
*
|
|
136
|
+
* SELECT / RADIO — array-valued at the RQL layer; the
|
|
137
|
+
* "is this option selected?" semantics are
|
|
138
|
+
* ambiguous for aggregations. Users are
|
|
139
|
+
* expected to model a plain BOOLEAN on the
|
|
140
|
+
* child CO (updated via Rule) and filter
|
|
141
|
+
* on that.
|
|
142
|
+
* LONG_TEXT — backend hard-rejects (parent_child_util.py).
|
|
143
|
+
* OG_REFERENCE_FIELD — lookup/parent-child: filter-on-what is
|
|
144
|
+
* ambiguous (id vs. name vs. edge metadata).
|
|
145
|
+
*
|
|
146
|
+
* The backend additionally rejects formula and summary fields as filter
|
|
147
|
+
* fields, and rejects the summary's own parent-child `lookup` field as
|
|
148
|
+
* its filter field. Those are enforced at construction-time in
|
|
149
|
+
* `SummaryField` (see `field.ts`) so the error surfaces before /validate.
|
|
150
|
+
*/
|
|
151
|
+
export const FILTER_OPERATORS_BY_TYPE: Partial<Record<FieldType, ReadonlySet<SummaryFilterOperator>>> = {
|
|
152
|
+
TEXT: new Set(['=', '!=']),
|
|
153
|
+
EMAIL: new Set(['=', '!=']),
|
|
154
|
+
URL: new Set(['=', '!=']),
|
|
155
|
+
PHONE_NUMBER: new Set(['=', '!=']),
|
|
156
|
+
BOOLEAN: new Set(['=', '!=']),
|
|
157
|
+
FILE: new Set(['=', '!=']),
|
|
158
|
+
NUMBER: new Set(['=', '!=', '>', '>=', '<', '<=']),
|
|
159
|
+
PERCENTAGE: new Set(['=', '!=', '>', '>=', '<', '<=']),
|
|
160
|
+
CURRENCY: new Set(['=', '!=', '>', '>=', '<', '<=']),
|
|
161
|
+
DATE: new Set(['=', '<', '>']),
|
|
162
|
+
DATETIME: new Set(['=', '<', '>']),
|
|
163
|
+
TIME: new Set(['=', '<', '>']),
|
|
164
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The contents of this file were inserted manually and are not generated by Stainless.
|
|
3
|
+
*
|
|
4
|
+
* Unity App definitions that group pages for navigation.
|
|
5
|
+
* Backend schema: CUSTOM_APP (v2)
|
|
6
|
+
*
|
|
7
|
+
* Pages are declared at construction as a flat array of live refs — pass a
|
|
8
|
+
* `CustomObject` for an object-page tab, or an `SduiPage` for a custom SDUI
|
|
9
|
+
* surface. The tab `api_name` is derived from the ref's own identifier.
|
|
10
|
+
* External refs (e.g. native-model `employee`, or an externally-authored
|
|
11
|
+
* SDUI page) are not supported yet; add when a real case appears.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { CustomObject } from './custom-object';
|
|
15
|
+
import type { ManifestScope } from './manifest-builder';
|
|
16
|
+
import { SduiPage } from './sdui-page';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A single page entry in an App:
|
|
20
|
+
* - `CustomObject` → object page, tab `api_name = co.getApiName()`
|
|
21
|
+
* - `SduiPage` → SDUI page, tab `api_name = page.getSduiPageId()`
|
|
22
|
+
*/
|
|
23
|
+
export type AppPage = CustomObject | SduiPage;
|
|
24
|
+
|
|
25
|
+
export interface AppIcon {
|
|
26
|
+
s3Bucket: string;
|
|
27
|
+
s3Key: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface AppProps {
|
|
31
|
+
/** Required. App api_name. */
|
|
32
|
+
apiName: string;
|
|
33
|
+
/** Required. Display name. */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Optional. App description. @default null */
|
|
36
|
+
description?: string;
|
|
37
|
+
/** Optional. App type. @default 'custom' */
|
|
38
|
+
appType?: string;
|
|
39
|
+
/** Optional. S3 icon reference. @default null */
|
|
40
|
+
icon?: AppIcon;
|
|
41
|
+
/** Optional. Pages shown as tabs in the App; order is preserved. @default [] */
|
|
42
|
+
pages?: AppPage[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolvePage(entry: AppPage): Record<string, any> {
|
|
46
|
+
if (entry instanceof CustomObject) {
|
|
47
|
+
const apiName = entry.getApiName();
|
|
48
|
+
return {
|
|
49
|
+
api_name: apiName,
|
|
50
|
+
page_type: 'object_page',
|
|
51
|
+
object_rql_name: apiName,
|
|
52
|
+
};
|
|
53
|
+
} else {
|
|
54
|
+
const sduiPageId = entry.getSduiPageId();
|
|
55
|
+
return {
|
|
56
|
+
api_name: sduiPageId,
|
|
57
|
+
page_type: 'sdui_page',
|
|
58
|
+
sdui_page_id: sduiPageId,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class App {
|
|
64
|
+
private readonly _apiName: string;
|
|
65
|
+
private readonly _name: string;
|
|
66
|
+
private readonly _description: string | undefined;
|
|
67
|
+
private readonly _appType: string | undefined;
|
|
68
|
+
private readonly _icon: AppIcon | undefined;
|
|
69
|
+
/** Wire-format pages, resolved eagerly at construction. */
|
|
70
|
+
private readonly _pages: Record<string, any>[];
|
|
71
|
+
|
|
72
|
+
/** Build a new app and auto-register with `scope`; resolves page refs eagerly. */
|
|
73
|
+
constructor(scope: ManifestScope, props: AppProps) {
|
|
74
|
+
this._apiName = props.apiName;
|
|
75
|
+
this._name = props.name;
|
|
76
|
+
this._description = props.description;
|
|
77
|
+
this._appType = props.appType;
|
|
78
|
+
this._icon = props.icon;
|
|
79
|
+
this._pages = (props.pages ?? []).map(resolvePage);
|
|
80
|
+
scope._register(this);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Backend api_name for this app. */
|
|
84
|
+
getApiName(): string {
|
|
85
|
+
return this._apiName;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Display name shown in the UI. */
|
|
89
|
+
getName(): string {
|
|
90
|
+
return this._name;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Serialize to the backend `CUSTOM_APP` wire shape; omits unset optional fields. */
|
|
94
|
+
toDict(): Record<string, any> {
|
|
95
|
+
const component: Record<string, any> = {
|
|
96
|
+
type: 'CUSTOM_APP',
|
|
97
|
+
api_name: this._apiName,
|
|
98
|
+
name: this._name,
|
|
99
|
+
};
|
|
100
|
+
if (this._description != null) component['description'] = this._description;
|
|
101
|
+
if (this._icon != null) {
|
|
102
|
+
component['icon'] = { s3_bucket: this._icon.s3Bucket, s3_key: this._icon.s3Key };
|
|
103
|
+
}
|
|
104
|
+
if (this._appType != null) component['app_type'] = this._appType;
|
|
105
|
+
if (this._pages.length > 0) component['pages'] = this._pages.map((p) => ({ ...p }));
|
|
106
|
+
return component;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The contents of this file were inserted manually and are not generated by Stainless.
|
|
3
|
+
*
|
|
4
|
+
* Rippling category definitions for grouping objects in navigation.
|
|
5
|
+
* Backend schema: CUSTOM_CATEGORY (v2)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ManifestScope } from './manifest-builder';
|
|
9
|
+
|
|
10
|
+
export interface CategoryProps {
|
|
11
|
+
/** Required. Unique API name (e.g. `'finance__c'`). */
|
|
12
|
+
apiName: string;
|
|
13
|
+
/** Required. Display name shown in the UI. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Optional. Description. Pass `null` explicitly for "no description". @default null */
|
|
16
|
+
description?: string | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class Category {
|
|
20
|
+
private readonly _apiName: string;
|
|
21
|
+
private readonly _name: string;
|
|
22
|
+
private readonly _description: string | null;
|
|
23
|
+
|
|
24
|
+
/** Build a new category and auto-register with `scope` (usually a `ManifestBuilder`). */
|
|
25
|
+
constructor(scope: ManifestScope, props: CategoryProps) {
|
|
26
|
+
this._apiName = props.apiName;
|
|
27
|
+
this._name = props.name;
|
|
28
|
+
this._description = props.description ?? null;
|
|
29
|
+
scope._register(this);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Backend api_name used as this category's identifier. */
|
|
33
|
+
getApiName(): string {
|
|
34
|
+
return this._apiName;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Display name shown in the UI. */
|
|
38
|
+
getName(): string {
|
|
39
|
+
return this._name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Serialize to the backend `CUSTOM_CATEGORY` wire shape. */
|
|
43
|
+
toDict(): Record<string, any> {
|
|
44
|
+
return {
|
|
45
|
+
type: 'CUSTOM_CATEGORY',
|
|
46
|
+
api_name: this._apiName,
|
|
47
|
+
name: this._name,
|
|
48
|
+
description: this._description ?? null,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The contents of this file were inserted manually and are not generated by Stainless.
|
|
3
|
+
*
|
|
4
|
+
* Custom object field sections (UI grouping of fields on detail pages).
|
|
5
|
+
* Backend schema: CUSTOM_OBJECT_FIELD_SECTION (v2)
|
|
6
|
+
*
|
|
7
|
+
* Construction is CDK-style: `new CustomObjectFieldSection(customObject, props)`
|
|
8
|
+
* — the CO is the first positional arg, and the section auto-registers with
|
|
9
|
+
* the manifest via the CO's scope chain.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { generateId } from './_helpers';
|
|
13
|
+
import type { CustomObject } from './custom-object';
|
|
14
|
+
|
|
15
|
+
export interface CustomObjectFieldSectionProps {
|
|
16
|
+
/** Required. Display name of the section. */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Identity override. Override the section identifier. @default generateId('sec') */
|
|
19
|
+
sectionId?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class CustomObjectFieldSection {
|
|
23
|
+
private readonly _sectionId: string;
|
|
24
|
+
private readonly _name: string;
|
|
25
|
+
private readonly _model: CustomObject;
|
|
26
|
+
|
|
27
|
+
/** Build a new section and auto-register with the CO's scope. */
|
|
28
|
+
constructor(customObject: CustomObject, props: CustomObjectFieldSectionProps) {
|
|
29
|
+
this._sectionId = props.sectionId ?? generateId('sec');
|
|
30
|
+
this._name = props.name;
|
|
31
|
+
this._model = customObject;
|
|
32
|
+
customObject._register(this);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Backend section_id used as this section's identifier. */
|
|
36
|
+
getSectionId(): string {
|
|
37
|
+
return this._sectionId;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** api_name of the parent custom object this section lives on. */
|
|
41
|
+
getModelApiName(): string {
|
|
42
|
+
return this._model.getApiName();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Serialize to the backend `CUSTOM_OBJECT_FIELD_SECTION` wire shape. */
|
|
46
|
+
toDict(): Record<string, any> {
|
|
47
|
+
return {
|
|
48
|
+
type: 'CUSTOM_OBJECT_FIELD_SECTION',
|
|
49
|
+
section_id: this._sectionId,
|
|
50
|
+
model_name: this._model.getApiName(),
|
|
51
|
+
name: this._name,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The contents of this file were inserted manually and are not generated by Stainless.
|
|
3
|
+
*
|
|
4
|
+
* Custom object page layouts (detail page structure).
|
|
5
|
+
* Backend schema: CUSTOM_OBJECT_PAGE_LAYOUT (v2)
|
|
6
|
+
*
|
|
7
|
+
* CDK-style: `new CustomObjectPageLayout(customObject, props)` auto-registers
|
|
8
|
+
* with the CO's scope. `blueprint_key` defaults to the CO's api_name.
|
|
9
|
+
* For the layout that drives **Add** and the default detail view, use
|
|
10
|
+
* `apiName: 'default'` (one per custom object). `CustomObjectPageLayout.basic`
|
|
11
|
+
* uses `default` automatically.
|
|
12
|
+
*
|
|
13
|
+
* TabEditsDTO / HeaderEditsDTO / VisibilityConditionsDTO are strict
|
|
14
|
+
* dataclasses on the backend. They expect camelCase keys on the wire
|
|
15
|
+
* (newTabs, systemTabEdits, fieldRqlName, newTitleField, ...). Snake_case
|
|
16
|
+
* keys are silently dropped and produce an empty layout on deploy. The
|
|
17
|
+
* interfaces below mirror the DTO field aliases exactly.
|
|
18
|
+
*
|
|
19
|
+
* TS catches misspellings on direct object literals but not on spreads,
|
|
20
|
+
* `as` casts, or loosely-typed variables — so be careful when constructing
|
|
21
|
+
* these objects dynamically.
|
|
22
|
+
*
|
|
23
|
+
* DTO references: types/edits.py, types/layout.py, types/sections.py.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { generateId } from './_helpers';
|
|
27
|
+
import type { CustomObject } from './custom-object';
|
|
28
|
+
import type { Field } from './field';
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// header_edits — HeaderEditsDTO
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/** Edit to a built-in (system) header field. */
|
|
35
|
+
export interface SystemHeaderFieldEdit {
|
|
36
|
+
newRqlField?: string;
|
|
37
|
+
deleted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Custom header field added via newFields. `key` is required + non-empty. */
|
|
41
|
+
export interface NewHeaderField {
|
|
42
|
+
rqlName: string;
|
|
43
|
+
key: string;
|
|
44
|
+
canBeDeleted?: boolean;
|
|
45
|
+
canBeChanged?: boolean;
|
|
46
|
+
canBeMoved?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Strict shape for header_edits. Only the keys listed here are accepted by
|
|
51
|
+
* HeaderEditsDTO — anything else is dropped on the wire. Pass `{}` for an
|
|
52
|
+
* empty header.
|
|
53
|
+
*/
|
|
54
|
+
export interface HeaderEdits {
|
|
55
|
+
newTitleField?: string | null;
|
|
56
|
+
titleFieldDeleted?: boolean;
|
|
57
|
+
newDescriptionField?: string | null;
|
|
58
|
+
descriptionFieldDeleted?: boolean;
|
|
59
|
+
/** Map of system field key → edit. */
|
|
60
|
+
systemFieldEdits?: Record<string, SystemHeaderFieldEdit>;
|
|
61
|
+
newFields?: NewHeaderField[];
|
|
62
|
+
/** Sort order of header field `key` values (custom + system). */
|
|
63
|
+
headerFieldsOrder?: string[];
|
|
64
|
+
buttons?: string[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// tab_edits — TabEditsDTO + section/tab DTOs
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
/** SectionFieldDTO — one field inside a fields_section. */
|
|
72
|
+
export interface SectionField {
|
|
73
|
+
fieldRqlName: string;
|
|
74
|
+
hidden?: boolean;
|
|
75
|
+
editable?: boolean;
|
|
76
|
+
movementOption?: 'tab' | 'free';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** FieldsSectionDTO — standard field grid section. */
|
|
80
|
+
export interface FieldsSection {
|
|
81
|
+
type: 'fields_section';
|
|
82
|
+
key: string;
|
|
83
|
+
name: string;
|
|
84
|
+
fields: SectionField[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Only `fields_section` is modeled today (most common). Add other section
|
|
88
|
+
* types (related_object_section, custom_section, …) explicitly as needed. */
|
|
89
|
+
export type PageLayoutSection = FieldsSection;
|
|
90
|
+
|
|
91
|
+
/** PageLayoutTabWithSectionsDTO. */
|
|
92
|
+
export interface TabWithSections {
|
|
93
|
+
type: 'tab_with_sections';
|
|
94
|
+
key: string;
|
|
95
|
+
name: string;
|
|
96
|
+
sections: PageLayoutSection[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** CustomTabDTO — host a custom component as a tab. */
|
|
100
|
+
export interface CustomTab {
|
|
101
|
+
type: 'custom_tab';
|
|
102
|
+
key: string;
|
|
103
|
+
name: string;
|
|
104
|
+
componentKey: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export type PageLayoutTab = TabWithSections | CustomTab;
|
|
108
|
+
|
|
109
|
+
/** Layout of fields inside a fields_section. */
|
|
110
|
+
export type SectionFieldsLayout = 'one_column' | 'two_column' | 'three_column' | 'responsive';
|
|
111
|
+
|
|
112
|
+
/** SystemSectionEditDTO — edits to a built-in section inside a system tab. */
|
|
113
|
+
export interface SystemSectionEdit {
|
|
114
|
+
newName?: string;
|
|
115
|
+
deleted?: boolean;
|
|
116
|
+
newLayout?: SectionFieldsLayout;
|
|
117
|
+
newFields?: SectionField[];
|
|
118
|
+
newHideName?: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** SystemTabEditDTO — edits to a built-in tab (rename, delete, add sections, …). */
|
|
122
|
+
export interface SystemTabEdit {
|
|
123
|
+
newName?: string;
|
|
124
|
+
deleted?: boolean;
|
|
125
|
+
newSections?: PageLayoutSection[];
|
|
126
|
+
systemSectionEdits?: Record<string, SystemSectionEdit>;
|
|
127
|
+
sectionsOrder?: string[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Strict shape for tab_edits. Only TabEditsDTO keys allowed.
|
|
132
|
+
*
|
|
133
|
+
* All fields are optional to match `TabEditsDTO`'s `default_factory` (empty
|
|
134
|
+
* list / empty dict). An omitted `tabEdits` defaults to `{}` in the
|
|
135
|
+
* constructor; partial objects rely on backend per-field defaults.
|
|
136
|
+
*
|
|
137
|
+
* - newTabs: tabs to create (each needs a `type` discriminator)
|
|
138
|
+
* - systemTabEdits: edits keyed by built-in tab key
|
|
139
|
+
* - tabsOrder: ordered list of tab `key` values (new + system)
|
|
140
|
+
* - newTabLayout: optional orientation
|
|
141
|
+
*/
|
|
142
|
+
export interface TabEdits {
|
|
143
|
+
newTabs?: PageLayoutTab[];
|
|
144
|
+
systemTabEdits?: Record<string, SystemTabEdit>;
|
|
145
|
+
tabsOrder?: string[];
|
|
146
|
+
newTabLayout?: 'vertical' | 'horizontal';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// visibility_conditions — VisibilityConditionsDTO
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* VisibilityConditionDTO. Both fields are required on the Python type — pass
|
|
155
|
+
* empty string / empty object if you genuinely have no formula or AST.
|
|
156
|
+
*/
|
|
157
|
+
export interface VisibilityCondition {
|
|
158
|
+
rqlFormula: string;
|
|
159
|
+
layeredConditionsTree: Record<string, any>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Pass `{}` for "no conditions" — both maps default empty. */
|
|
163
|
+
export interface VisibilityConditions {
|
|
164
|
+
sections?: Record<string, VisibilityCondition>;
|
|
165
|
+
tabs?: Record<string, VisibilityCondition>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Public props
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
export interface CustomObjectPageLayoutProps {
|
|
173
|
+
/**
|
|
174
|
+
* Required. Stable `api_name` for the layout. Use `'default'` for the layout
|
|
175
|
+
* that drives **Add** and the default object detail view (per Custom Object
|
|
176
|
+
* — one `default` per object).
|
|
177
|
+
*/
|
|
178
|
+
apiName: string;
|
|
179
|
+
/** Required. Display name of the layout. */
|
|
180
|
+
name: string;
|
|
181
|
+
/** Optional. Tab structure (TabEditsDTO). Defaults to empty. */
|
|
182
|
+
tabEdits?: TabEdits;
|
|
183
|
+
/** Optional. Header configuration (HeaderEditsDTO). Defaults to empty. */
|
|
184
|
+
headerEdits?: HeaderEdits;
|
|
185
|
+
/** Optional. Visibility conditions. Defaults to empty (no conditions). */
|
|
186
|
+
visibilityConditions?: VisibilityConditions;
|
|
187
|
+
/** Identity override. Override the layout identifier. @default generateId('layout') */
|
|
188
|
+
layoutId?: string;
|
|
189
|
+
/** Optional. Overwritten at install; defaults to object api_name. */
|
|
190
|
+
blueprintKey?: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
// Class
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
|
|
197
|
+
export class CustomObjectPageLayout {
|
|
198
|
+
private readonly _layoutId: string;
|
|
199
|
+
private readonly _apiName: string;
|
|
200
|
+
private readonly _customObjectApiName: string;
|
|
201
|
+
private readonly _name: string;
|
|
202
|
+
private readonly _tabEdits: TabEdits;
|
|
203
|
+
private readonly _headerEdits: HeaderEdits;
|
|
204
|
+
private readonly _visibilityConditions: VisibilityConditions;
|
|
205
|
+
private readonly _blueprintKey: string | undefined;
|
|
206
|
+
|
|
207
|
+
/** Build a new layout and auto-register with the CO's scope. */
|
|
208
|
+
constructor(customObject: CustomObject, props: CustomObjectPageLayoutProps) {
|
|
209
|
+
if (!props.apiName) throw new Error('CustomObjectPageLayout: apiName cannot be empty');
|
|
210
|
+
if (!props.name) throw new Error('CustomObjectPageLayout: name cannot be empty');
|
|
211
|
+
this._layoutId = props.layoutId ?? generateId('layout');
|
|
212
|
+
this._apiName = props.apiName;
|
|
213
|
+
this._customObjectApiName = customObject.getApiName();
|
|
214
|
+
this._name = props.name;
|
|
215
|
+
this._tabEdits = props.tabEdits ?? {};
|
|
216
|
+
this._headerEdits = props.headerEdits ?? {};
|
|
217
|
+
this._visibilityConditions = props.visibilityConditions ?? {};
|
|
218
|
+
this._blueprintKey = props.blueprintKey;
|
|
219
|
+
customObject._register(this);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Backend layout_id used as this layout's identifier. */
|
|
223
|
+
getLayoutId(): string {
|
|
224
|
+
return this._layoutId;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Stable api_name for this layout. */
|
|
228
|
+
getApiName(): string {
|
|
229
|
+
return this._apiName;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** api_name of the CustomObject this layout lives on. */
|
|
233
|
+
getCustomObjectApiName(): string {
|
|
234
|
+
return this._customObjectApiName;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Serialize to the backend `CUSTOM_OBJECT_PAGE_LAYOUT` wire shape. */
|
|
238
|
+
toDict(): Record<string, any> {
|
|
239
|
+
const d: Record<string, any> = {
|
|
240
|
+
type: 'CUSTOM_OBJECT_PAGE_LAYOUT',
|
|
241
|
+
layout_id: this._layoutId,
|
|
242
|
+
api_name: this._apiName,
|
|
243
|
+
object_rql_name: this._customObjectApiName,
|
|
244
|
+
name: this._name,
|
|
245
|
+
// Packaged layouts are never system-created (backend invariant).
|
|
246
|
+
system_created: false,
|
|
247
|
+
tab_edits: this._tabEdits,
|
|
248
|
+
header_edits: this._headerEdits,
|
|
249
|
+
visibility_conditions: this._visibilityConditions,
|
|
250
|
+
blueprint_key: this._blueprintKey ?? this._customObjectApiName,
|
|
251
|
+
};
|
|
252
|
+
return d;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** Factory for a single-tab "Details" page listing the given fields. */
|
|
256
|
+
static basic(
|
|
257
|
+
customObject: CustomObject,
|
|
258
|
+
props: {
|
|
259
|
+
fields?: Field[];
|
|
260
|
+
} = {},
|
|
261
|
+
): CustomObjectPageLayout {
|
|
262
|
+
const coApiName = customObject.getApiName();
|
|
263
|
+
const coName = customObject.getName();
|
|
264
|
+
return new CustomObjectPageLayout(customObject, {
|
|
265
|
+
apiName: 'default',
|
|
266
|
+
name: `${coName} Layout`,
|
|
267
|
+
tabEdits: {
|
|
268
|
+
newTabs: [
|
|
269
|
+
{
|
|
270
|
+
key: 'details',
|
|
271
|
+
name: 'Details',
|
|
272
|
+
type: 'tab_with_sections',
|
|
273
|
+
sections: [
|
|
274
|
+
{
|
|
275
|
+
key: 'general',
|
|
276
|
+
name: 'General',
|
|
277
|
+
type: 'fields_section',
|
|
278
|
+
fields: (props.fields ?? []).map((f: Field) => ({
|
|
279
|
+
fieldRqlName: f.getApiName(),
|
|
280
|
+
})),
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
systemTabEdits: {},
|
|
286
|
+
tabsOrder: ['details'],
|
|
287
|
+
},
|
|
288
|
+
headerEdits: {},
|
|
289
|
+
visibilityConditions: {},
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|