@stndrds/schema 1.0.0-alpha.264 → 1.0.0-alpha.266
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/dist/all--B2_3ksI.d.ts +465 -0
- package/dist/all-D5zeUllO.d.mts +465 -0
- package/dist/{attributes-DUuaECJI.d.ts → attributes-_b3Db8vT.d.ts} +1 -1
- package/dist/{attributes-DCgZhISp.d.mts → attributes-lBLiOIY3.d.mts} +1 -1
- package/dist/chunk-6ZDH3EJA.js +1261 -0
- package/dist/chunk-F6ATLCIR.mjs +1214 -0
- package/dist/{chunk-TS3PJOMZ.js → chunk-FDIAOFHS.js} +22 -235
- package/dist/{chunk-UXCJ3NI4.mjs → chunk-KDHDC7E6.mjs} +150 -9
- package/dist/{chunk-U36ZIBEM.mjs → chunk-O73ROMWQ.mjs} +15 -6
- package/dist/{chunk-54WDPQ6R.mjs → chunk-POULKEJM.mjs} +22 -224
- package/dist/{chunk-EBGRZUIH.js → chunk-Q4SZAMJT.js} +5 -0
- package/dist/chunk-QMLO7V5E.mjs +216 -0
- package/dist/{chunk-L4U5QEQL.js → chunk-QN2N3IJZ.js} +158 -8
- package/dist/{chunk-JUKLL5RJ.mjs → chunk-R5LAJCBU.mjs} +5 -2
- package/dist/chunk-V6Q7HCA7.js +229 -0
- package/dist/{chunk-QAF3HNKQ.js → chunk-ZPFOKBIN.js} +16 -5
- package/dist/exceptions.d.mts +471 -0
- package/dist/exceptions.d.ts +471 -0
- package/dist/exceptions.js +158 -0
- package/dist/exceptions.mjs +1 -0
- package/dist/helpers-C1VVEAOO.d.mts +76 -0
- package/dist/helpers-vQ6kp8ET.d.ts +76 -0
- package/dist/index-Bq1KrQkR.d.ts +2413 -0
- package/dist/index-DtxtOBYT.d.mts +2413 -0
- package/dist/index.d.mts +1580 -2652
- package/dist/index.d.ts +1580 -2652
- package/dist/index.js +1297 -1045
- package/dist/index.mjs +913 -907
- package/dist/migrations-BXd2ZGfM.d.mts +39 -0
- package/dist/migrations-DcuJZ8qO.d.ts +39 -0
- package/dist/{helpers-B4qBjTd0.d.ts → objects-A1ED9af-.d.ts} +33 -113
- package/dist/{helpers-B_NlMAm2.d.mts → objects-BCaBw2ef.d.mts} +33 -113
- package/dist/{types-15lGDPlN.d.mts → types-DNz3ITS-.d.mts} +1 -1
- package/dist/{types-CqZZxm_V.d.ts → types-DqLi1tx1.d.ts} +1 -1
- package/dist/validation/all.d.mts +7 -4
- package/dist/validation/all.d.ts +7 -4
- package/dist/validation/all.js +88 -15
- package/dist/validation/all.mjs +9 -8
- package/dist/validation/complex/currency.d.mts +2 -2
- package/dist/validation/complex/currency.d.ts +2 -2
- package/dist/validation/complex/location.d.mts +2 -2
- package/dist/validation/complex/location.d.ts +2 -2
- package/dist/validation/complex/phone.d.mts +2 -2
- package/dist/validation/complex/phone.d.ts +2 -2
- package/dist/validation/complex/phone.js +2 -2
- package/dist/validation/complex/phone.mjs +1 -1
- package/dist/validation/complex/relation.d.mts +2 -2
- package/dist/validation/complex/relation.d.ts +2 -2
- package/dist/validation/complex/richtext.d.mts +2 -2
- package/dist/validation/complex/richtext.d.ts +2 -2
- package/dist/validation/complex/select.d.mts +2 -2
- package/dist/validation/complex/select.d.ts +2 -2
- package/dist/validation/complex/user.d.mts +2 -2
- package/dist/validation/complex/user.d.ts +2 -2
- package/dist/validation/computed/formula.d.mts +2 -2
- package/dist/validation/computed/formula.d.ts +2 -2
- package/dist/validation/computed/rollup.d.mts +2 -2
- package/dist/validation/computed/rollup.d.ts +2 -2
- package/dist/validation/config/index.d.mts +5 -18
- package/dist/validation/config/index.d.ts +5 -18
- package/dist/validation/config/index.js +34 -4
- package/dist/validation/config/index.mjs +7 -1
- package/dist/validation/core/index.d.mts +3 -3
- package/dist/validation/core/index.d.ts +3 -3
- package/dist/validation/object/index.d.mts +5 -4
- package/dist/validation/object/index.d.ts +5 -4
- package/dist/validation/object/index.js +19 -18
- package/dist/validation/object/index.mjs +7 -6
- package/dist/validation/primitives/checkbox.d.mts +2 -2
- package/dist/validation/primitives/checkbox.d.ts +2 -2
- package/dist/validation/primitives/date.d.mts +2 -2
- package/dist/validation/primitives/date.d.ts +2 -2
- package/dist/validation/primitives/number.d.mts +2 -2
- package/dist/validation/primitives/number.d.ts +2 -2
- package/dist/validation/primitives/text.d.mts +2 -2
- package/dist/validation/primitives/text.d.ts +2 -2
- package/dist/validation/primitives/text.js +2 -2
- package/dist/validation/primitives/text.mjs +1 -1
- package/package.json +7 -2
- package/dist/chunk-PGERPYDR.js +0 -2
- package/dist/chunk-SP3PNHYF.mjs +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { generateId } from './chunk-QY6QFRRV.mjs';
|
|
2
2
|
export { asTenantId, asUserId, deepEqual, generateId, indexBy } from './chunk-QY6QFRRV.mjs';
|
|
3
|
-
import './chunk-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-U36ZIBEM.mjs';
|
|
3
|
+
import { SYSTEM_FILTER_ATTRIBUTE_TYPES, RESERVED_OBJECT_NAMES, listViewConfigSchema, detailViewConfigSchema, RESERVED_ATTRIBUTE_NAMES, isAttributeSortable, getAttributeCapabilities, resolveIsWithinBounds } from './chunk-F6ATLCIR.mjs';
|
|
4
|
+
export { ATTRIBUTE_FILTER_OPERATORS, LIST_VIEW_TAB_VISIBILITIES, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, REMOVED_OPERATOR_REPLACEMENTS, RESERVED_ATTRIBUTE_NAMES, RESERVED_OBJECT_NAMES, RESOURCE_VISIBILITIES, SYNONYM_ALIASES, SYSTEM_ATTRIBUTES, SYSTEM_ATTRIBUTE_I18N_KEYS, SYSTEM_FIELD_NAMES, SYSTEM_FILTER_ATTRIBUTE_TYPES, collectQualifiedRuleIssues, currentActor, detailTabSchema, detailViewConfigSchema, getAttributeCapabilities, getAttributeFilterOperators, getRollupFilterOperators, getSystemAttributeI18nKey, getSystemAttributeList, inverseSourceSchema, isAttributeFilterable, isAttributeGroupable, isAttributeKanbanGroupable, isAttributeSearchable, isDynamicValue, isManagedSystemAttribute, isNoValueOperator, isRelativeDateValue, listViewConfigSchema, listViewTabSchema, normalizeFilterRule, normalizeOperator, now, parseViewConfig, relationSourceSchema, resolveIsWithinBounds, tableSourceSchema, toUtcDayString, today, validateQualifiedRule, viewConfigByTypeSchema, viewTypeSchema } from './chunk-F6ATLCIR.mjs';
|
|
5
|
+
import { iconNameSchema, parseAttributeConfigForCreate, parseComputedFormula } from './chunk-KDHDC7E6.mjs';
|
|
6
|
+
export { ComputedFormulaParseError, SCHEMA_LIMITS, colorIdSchema, iconNameSchema, multiselectOptionWriteSchema, parseAttributeConfig, parseAttributeConfigForCreate, parseAttributeConfigForUpdate, parseComputedFormula, selectOptionWriteSchema, statusGroupSchema, statusOptionWriteSchema } from './chunk-KDHDC7E6.mjs';
|
|
7
|
+
import { createObjectValidator, createAttributeValidator } from './chunk-QMLO7V5E.mjs';
|
|
8
|
+
export { createFormAttributeValidator, rejectUnknownAttributesOrThrow, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from './chunk-QMLO7V5E.mjs';
|
|
9
|
+
import './chunk-QVLQPW3O.mjs';
|
|
11
10
|
import './chunk-ZDQ5AP26.mjs';
|
|
12
11
|
import './chunk-LV3FEUKU.mjs';
|
|
13
12
|
import './chunk-UXAHLSWC.mjs';
|
|
14
13
|
import './chunk-NS63SPNN.mjs';
|
|
15
|
-
|
|
14
|
+
export { createCheckboxValidator } from './chunk-OSSGN43B.mjs';
|
|
15
|
+
export { createDateValidator } from './chunk-Q44QKLN4.mjs';
|
|
16
|
+
export { createNumberValidator } from './chunk-UANQJ2GH.mjs';
|
|
17
|
+
export { TEXT_FORMAT_PATTERNS, createTextValidator, resolveTextPattern } from './chunk-O73ROMWQ.mjs';
|
|
18
|
+
import { SchemaError, SchemaErrorCode, ValidationError, NotFoundError, DuplicateError } from './chunk-POULKEJM.mjs';
|
|
19
|
+
export { AccessDeniedError, AttributeInUseError, AttributeNotFoundError, ChangeTypeNotSupportedError, ConcurrentModificationError, DestructiveSyncNotAllowedError, DuplicateError, ForbiddenError, MemoryNotFoundError, MigrationTimeoutError, NotFoundError, NotImplementedError, ObjectNotFoundError, ObjectReferencedError, OrphanSystemAttributeError, ProtectedResourceError, ProtectedRoleError, RecordNotFoundError, RecordReferencedError, RepositoryError, RoleNotFoundError, SchemaError, SchemaErrorCode, SchemaPlanNotFoundError, SearchBackendError, StorageError, SyncCascadeError, SyncConflictError, SyncError, SystemEntityImmutableError, ValidationError, isAttributeInUseError, isNotFoundError, isObjectReferencedError, isProtectedResourceError, isRecordReferencedError, isSchemaError, isValidationError } from './chunk-POULKEJM.mjs';
|
|
16
20
|
import './chunk-AYVHMVKQ.mjs';
|
|
17
21
|
import './chunk-YUFTHPOE.mjs';
|
|
18
|
-
import { formatPhoneForDisplay } from './chunk-
|
|
22
|
+
import { formatPhoneForDisplay, normalizeCountrylessPhoneNumber, normalizePhoneNumber } from './chunk-R5LAJCBU.mjs';
|
|
19
23
|
import './chunk-GO6LQADH.mjs';
|
|
20
|
-
import './chunk-QVLQPW3O.mjs';
|
|
21
24
|
export { DEFAULT_VALIDATION_MESSAGES, formatZodErrors } from './chunk-HRQEZUAA.mjs';
|
|
22
25
|
import { ICONS, SKILL_NAME_MAX_LENGTH, SKILL_DESCRIPTION_MAX_LENGTH, MEMORY_NAME_MAX_LENGTH, MEMORY_DESCRIPTION_MAX_LENGTH, getCountryDisplayNameByIso3 } from '@stndrds/constants';
|
|
23
|
-
import
|
|
26
|
+
import z2, { z } from 'zod';
|
|
24
27
|
|
|
25
28
|
// src/types/notifications.ts
|
|
26
29
|
var NOTIFICATION_KINDS = ["fyi", "task", "question", "handoff", "system"];
|
|
@@ -65,408 +68,6 @@ var BEHAVIOR_PROPERTIES = [
|
|
|
65
68
|
];
|
|
66
69
|
var PRESENTATION_PROPERTIES = ["label", "description", "placeholder", "icon"];
|
|
67
70
|
|
|
68
|
-
// src/types/system-attributes.ts
|
|
69
|
-
var SYSTEM_ATTRIBUTE_I18N_KEYS = {
|
|
70
|
-
createdAt: "createdAt",
|
|
71
|
-
updatedAt: "updatedAt",
|
|
72
|
-
createdBy: "createdBy",
|
|
73
|
-
lastUpdatedBy: "lastUpdatedBy",
|
|
74
|
-
attachments: "attachments"
|
|
75
|
-
};
|
|
76
|
-
function getSystemAttributeI18nKey(name) {
|
|
77
|
-
return SYSTEM_ATTRIBUTE_I18N_KEYS[name];
|
|
78
|
-
}
|
|
79
|
-
var SYSTEM_ATTRIBUTES = {
|
|
80
|
-
createdAt: {
|
|
81
|
-
id: "system:createdAt",
|
|
82
|
-
name: "createdAt",
|
|
83
|
-
label: "Created time",
|
|
84
|
-
type: "date",
|
|
85
|
-
required: false,
|
|
86
|
-
system: true,
|
|
87
|
-
icon: "clock-circle",
|
|
88
|
-
description: "When this record was created"
|
|
89
|
-
},
|
|
90
|
-
updatedAt: {
|
|
91
|
-
id: "system:updatedAt",
|
|
92
|
-
name: "updatedAt",
|
|
93
|
-
label: "Last edited time",
|
|
94
|
-
type: "date",
|
|
95
|
-
required: false,
|
|
96
|
-
system: true,
|
|
97
|
-
icon: "clock-circle",
|
|
98
|
-
description: "When this record was last modified"
|
|
99
|
-
},
|
|
100
|
-
createdBy: {
|
|
101
|
-
id: "system:createdBy",
|
|
102
|
-
name: "createdBy",
|
|
103
|
-
label: "Created by",
|
|
104
|
-
type: "user",
|
|
105
|
-
required: false,
|
|
106
|
-
system: true,
|
|
107
|
-
multiple: false,
|
|
108
|
-
icon: "user",
|
|
109
|
-
description: "Actor who created this record"
|
|
110
|
-
},
|
|
111
|
-
lastUpdatedBy: {
|
|
112
|
-
id: "system:lastUpdatedBy",
|
|
113
|
-
name: "lastUpdatedBy",
|
|
114
|
-
label: "Last edited by",
|
|
115
|
-
type: "user",
|
|
116
|
-
required: false,
|
|
117
|
-
system: true,
|
|
118
|
-
multiple: false,
|
|
119
|
-
icon: "user",
|
|
120
|
-
description: "Actor who last modified this record"
|
|
121
|
-
},
|
|
122
|
-
/**
|
|
123
|
-
* System attribute for free-form document attachments.
|
|
124
|
-
* Hidden from forms, visible in Documents tab.
|
|
125
|
-
* Users can attach any document without template constraints.
|
|
126
|
-
*/
|
|
127
|
-
attachments: {
|
|
128
|
-
id: "system:attachments",
|
|
129
|
-
name: "attachments",
|
|
130
|
-
label: "Attachments",
|
|
131
|
-
type: "document",
|
|
132
|
-
required: false,
|
|
133
|
-
system: true,
|
|
134
|
-
hidden: true,
|
|
135
|
-
// Hidden from regular form views
|
|
136
|
-
icon: "paperclip",
|
|
137
|
-
description: "Free-form document attachments"
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
function getSystemAttributeList() {
|
|
141
|
-
return Object.values(SYSTEM_ATTRIBUTES);
|
|
142
|
-
}
|
|
143
|
-
function isManagedSystemAttribute(attribute) {
|
|
144
|
-
return attribute.id?.startsWith("system:") ?? false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/types/attribute-capabilities.ts
|
|
148
|
-
var TEXT_OPERATORS = [
|
|
149
|
-
"is",
|
|
150
|
-
"is_not",
|
|
151
|
-
"contains",
|
|
152
|
-
"not_contains",
|
|
153
|
-
"starts_with",
|
|
154
|
-
"ends_with",
|
|
155
|
-
"is_empty",
|
|
156
|
-
"is_not_empty"
|
|
157
|
-
];
|
|
158
|
-
var NUMBER_OPERATORS = [
|
|
159
|
-
"eq",
|
|
160
|
-
"neq",
|
|
161
|
-
"lt",
|
|
162
|
-
"gt",
|
|
163
|
-
"lte",
|
|
164
|
-
"gte",
|
|
165
|
-
"is_empty",
|
|
166
|
-
"is_not_empty"
|
|
167
|
-
];
|
|
168
|
-
var CHECKBOX_OPERATORS = [
|
|
169
|
-
"is_checked",
|
|
170
|
-
"is_not_checked"
|
|
171
|
-
];
|
|
172
|
-
var DATE_OPERATORS = [
|
|
173
|
-
"is",
|
|
174
|
-
"is_not",
|
|
175
|
-
"before",
|
|
176
|
-
"after",
|
|
177
|
-
"on_or_before",
|
|
178
|
-
"on_or_after",
|
|
179
|
-
"is_within",
|
|
180
|
-
"day_month_eq",
|
|
181
|
-
"is_empty",
|
|
182
|
-
"is_not_empty"
|
|
183
|
-
];
|
|
184
|
-
var SELECT_OPERATORS = [
|
|
185
|
-
"is",
|
|
186
|
-
"is_not",
|
|
187
|
-
"any_of",
|
|
188
|
-
"none_of",
|
|
189
|
-
"is_empty",
|
|
190
|
-
"is_not_empty"
|
|
191
|
-
];
|
|
192
|
-
var MULTISELECT_OPERATORS = [
|
|
193
|
-
"contains",
|
|
194
|
-
"not_contains",
|
|
195
|
-
"is_empty",
|
|
196
|
-
"is_not_empty"
|
|
197
|
-
];
|
|
198
|
-
var REFERENCE_OPERATORS = [
|
|
199
|
-
"is",
|
|
200
|
-
"is_not",
|
|
201
|
-
"any_of",
|
|
202
|
-
"none_of",
|
|
203
|
-
"contains",
|
|
204
|
-
"not_contains",
|
|
205
|
-
"is_empty",
|
|
206
|
-
"is_not_empty"
|
|
207
|
-
];
|
|
208
|
-
var PRESENCE_OPERATORS = [
|
|
209
|
-
"is_empty",
|
|
210
|
-
"is_not_empty"
|
|
211
|
-
];
|
|
212
|
-
var FORMULA_OPERATORS = [
|
|
213
|
-
"is",
|
|
214
|
-
"is_not",
|
|
215
|
-
"eq",
|
|
216
|
-
"neq",
|
|
217
|
-
"lt",
|
|
218
|
-
"gt",
|
|
219
|
-
"lte",
|
|
220
|
-
"gte",
|
|
221
|
-
"contains",
|
|
222
|
-
"not_contains",
|
|
223
|
-
"is_empty",
|
|
224
|
-
"is_not_empty"
|
|
225
|
-
];
|
|
226
|
-
var ATTRIBUTE_FILTER_OPERATORS = {
|
|
227
|
-
text: TEXT_OPERATORS,
|
|
228
|
-
richtext: [],
|
|
229
|
-
number: NUMBER_OPERATORS,
|
|
230
|
-
checkbox: CHECKBOX_OPERATORS,
|
|
231
|
-
date: DATE_OPERATORS,
|
|
232
|
-
phone: ["is", "is_not", "contains", "not_contains", "is_empty", "is_not_empty"],
|
|
233
|
-
currency: NUMBER_OPERATORS,
|
|
234
|
-
status: SELECT_OPERATORS,
|
|
235
|
-
select: SELECT_OPERATORS,
|
|
236
|
-
multiselect: MULTISELECT_OPERATORS,
|
|
237
|
-
location: [],
|
|
238
|
-
user: REFERENCE_OPERATORS,
|
|
239
|
-
relation: REFERENCE_OPERATORS,
|
|
240
|
-
formula: FORMULA_OPERATORS,
|
|
241
|
-
document: PRESENCE_OPERATORS
|
|
242
|
-
};
|
|
243
|
-
var COMPUTED_TYPES = /* @__PURE__ */ new Set(["formula", "rollup"]);
|
|
244
|
-
var EDGE_BACKED_TYPES = /* @__PURE__ */ new Set(["user", "relation", "document"]);
|
|
245
|
-
var STATIC_DEFAULT_TYPES = /* @__PURE__ */ new Set([
|
|
246
|
-
"text",
|
|
247
|
-
"richtext",
|
|
248
|
-
"number",
|
|
249
|
-
"select",
|
|
250
|
-
"multiselect",
|
|
251
|
-
"status",
|
|
252
|
-
"date",
|
|
253
|
-
"phone",
|
|
254
|
-
"currency",
|
|
255
|
-
"location",
|
|
256
|
-
"user",
|
|
257
|
-
"relation",
|
|
258
|
-
"document"
|
|
259
|
-
]);
|
|
260
|
-
var PLACEHOLDER_TYPES = /* @__PURE__ */ new Set([
|
|
261
|
-
"text",
|
|
262
|
-
"number",
|
|
263
|
-
"date",
|
|
264
|
-
"phone",
|
|
265
|
-
"currency",
|
|
266
|
-
"select",
|
|
267
|
-
"multiselect"
|
|
268
|
-
]);
|
|
269
|
-
var SEARCHABLE_TYPES = /* @__PURE__ */ new Set([
|
|
270
|
-
"text",
|
|
271
|
-
"phone",
|
|
272
|
-
"status",
|
|
273
|
-
"select",
|
|
274
|
-
"multiselect"
|
|
275
|
-
]);
|
|
276
|
-
var SORTABLE_TYPES = /* @__PURE__ */ new Set([
|
|
277
|
-
"text",
|
|
278
|
-
"number",
|
|
279
|
-
"checkbox",
|
|
280
|
-
"date",
|
|
281
|
-
"phone",
|
|
282
|
-
"currency",
|
|
283
|
-
"status",
|
|
284
|
-
"select"
|
|
285
|
-
]);
|
|
286
|
-
function getAttributeCapabilities(attribute) {
|
|
287
|
-
const suppressed = Boolean(attribute.hidden || attribute.archived);
|
|
288
|
-
const active = !attribute.archived;
|
|
289
|
-
const computed = COMPUTED_TYPES.has(attribute.type);
|
|
290
|
-
const document2 = attribute.type === "document";
|
|
291
|
-
const edgeBacked = EDGE_BACKED_TYPES.has(attribute.type);
|
|
292
|
-
const cardinality = getAttributeCardinality(attribute);
|
|
293
|
-
const operators = suppressed ? [] : getRawFilterOperators(attribute);
|
|
294
|
-
const filterable = operators.length > 0 && !suppressed;
|
|
295
|
-
const searchable = !suppressed && SEARCHABLE_TYPES.has(attribute.type);
|
|
296
|
-
const sortable = !suppressed && SORTABLE_TYPES.has(attribute.type);
|
|
297
|
-
const groupable = !suppressed && isGroupableType(attribute.type);
|
|
298
|
-
const kanbanGroupable = !suppressed && attribute.type === "status";
|
|
299
|
-
const managed = isManagedSystemAttribute(attribute);
|
|
300
|
-
const readOnly = computed || document2 || managed;
|
|
301
|
-
const editable = !(suppressed || readOnly);
|
|
302
|
-
const required = isRequiredForbidden(attribute.type) ? "forbidden" : "allowed";
|
|
303
|
-
const defaultValue = getDefaultValueCapability(attribute.type);
|
|
304
|
-
const maxItems = supportsMaxItems(attribute);
|
|
305
|
-
const placeholder = PLACEHOLDER_TYPES.has(attribute.type);
|
|
306
|
-
const warningWhenDeprecated = Boolean(attribute.deprecated && !suppressed);
|
|
307
|
-
const editMode = resolveEditMode(attribute);
|
|
308
|
-
return {
|
|
309
|
-
lifecycle: {
|
|
310
|
-
active,
|
|
311
|
-
deprecated: Boolean(attribute.deprecated),
|
|
312
|
-
visibleInArchitect: true,
|
|
313
|
-
visibleInRuntime: !suppressed,
|
|
314
|
-
warningWhenDeprecated
|
|
315
|
-
},
|
|
316
|
-
storage: {
|
|
317
|
-
mode: computed ? "computed" : edgeBacked ? "edge" : "value",
|
|
318
|
-
cardinality,
|
|
319
|
-
edgeBacked,
|
|
320
|
-
preservesExistingValues: Boolean(attribute.archived),
|
|
321
|
-
qualifiedProperties: supportsQualifiedProperties(attribute.type),
|
|
322
|
-
polymorphic: getPolymorphicCapability(attribute),
|
|
323
|
-
maxItems
|
|
324
|
-
},
|
|
325
|
-
authoring: {
|
|
326
|
-
editable,
|
|
327
|
-
readOnly,
|
|
328
|
-
directEdit: editable && editMode === "inline",
|
|
329
|
-
required,
|
|
330
|
-
defaultValue,
|
|
331
|
-
placeholder,
|
|
332
|
-
maxItems
|
|
333
|
-
},
|
|
334
|
-
presentation: {
|
|
335
|
-
formField: !suppressed && isFormFieldType(attribute.type),
|
|
336
|
-
tableCell: !suppressed && isTableCellType(attribute.type),
|
|
337
|
-
defaultColumn: !suppressed && isDefaultColumnType(attribute.type),
|
|
338
|
-
compactDisplay: !suppressed,
|
|
339
|
-
popoverEditor: !suppressed && editMode === "popover",
|
|
340
|
-
placeholder,
|
|
341
|
-
warningWhenDeprecated
|
|
342
|
-
},
|
|
343
|
-
query: {
|
|
344
|
-
filterable,
|
|
345
|
-
searchable,
|
|
346
|
-
sortable,
|
|
347
|
-
groupable,
|
|
348
|
-
kanbanGroupable,
|
|
349
|
-
operators
|
|
350
|
-
},
|
|
351
|
-
agent: {
|
|
352
|
-
readable: !suppressed,
|
|
353
|
-
writable: editable && !document2,
|
|
354
|
-
compactReadable: !suppressed,
|
|
355
|
-
contentReadable: !suppressed && isContentReadableType(attribute.type),
|
|
356
|
-
requiresDedicatedTool: document2
|
|
357
|
-
},
|
|
358
|
-
exchange: {
|
|
359
|
-
importable: !suppressed,
|
|
360
|
-
exportable: !suppressed,
|
|
361
|
-
schemaExportable: true,
|
|
362
|
-
metadataExportable: false
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
function getAttributeFilterOperators(attribute) {
|
|
367
|
-
return getAttributeCapabilities(attribute).query.operators;
|
|
368
|
-
}
|
|
369
|
-
function isAttributeFilterable(attribute) {
|
|
370
|
-
return getAttributeCapabilities(attribute).query.filterable;
|
|
371
|
-
}
|
|
372
|
-
function isAttributeSearchable(attribute) {
|
|
373
|
-
return getAttributeCapabilities(attribute).query.searchable;
|
|
374
|
-
}
|
|
375
|
-
function isAttributeSortable(attribute) {
|
|
376
|
-
return getAttributeCapabilities(attribute).query.sortable;
|
|
377
|
-
}
|
|
378
|
-
function isAttributeGroupable(attribute) {
|
|
379
|
-
return getAttributeCapabilities(attribute).query.groupable;
|
|
380
|
-
}
|
|
381
|
-
function isAttributeKanbanGroupable(attribute) {
|
|
382
|
-
return getAttributeCapabilities(attribute).query.kanbanGroupable;
|
|
383
|
-
}
|
|
384
|
-
function getRollupFilterOperators(attr) {
|
|
385
|
-
const fn = attr.function;
|
|
386
|
-
if (fn === "earliest" || fn === "latest") {
|
|
387
|
-
return ATTRIBUTE_FILTER_OPERATORS.date;
|
|
388
|
-
}
|
|
389
|
-
if (fn === "original") {
|
|
390
|
-
const targetType = attr.targetAttributeType;
|
|
391
|
-
if (targetType && hasFilterOperatorEntry(targetType)) {
|
|
392
|
-
return ATTRIBUTE_FILTER_OPERATORS[targetType];
|
|
393
|
-
}
|
|
394
|
-
return ATTRIBUTE_FILTER_OPERATORS.number;
|
|
395
|
-
}
|
|
396
|
-
return ATTRIBUTE_FILTER_OPERATORS.number;
|
|
397
|
-
}
|
|
398
|
-
function getRawFilterOperators(attribute) {
|
|
399
|
-
if (attribute.type === "rollup") {
|
|
400
|
-
return getRollupFilterOperators(attribute);
|
|
401
|
-
}
|
|
402
|
-
return ATTRIBUTE_FILTER_OPERATORS[attribute.type] ?? [];
|
|
403
|
-
}
|
|
404
|
-
function getAttributeCardinality(attribute) {
|
|
405
|
-
if (attribute.type === "multiselect" || attribute.type === "document") return "many";
|
|
406
|
-
if (attribute.type === "user" && attribute.multiple === true) return "many";
|
|
407
|
-
if (attribute.type === "relation") return attribute.cardinality === "many" ? "many" : "one";
|
|
408
|
-
return "one";
|
|
409
|
-
}
|
|
410
|
-
function getPolymorphicCapability(attribute) {
|
|
411
|
-
if (attribute.type !== "relation") return "none";
|
|
412
|
-
const relation2 = attribute;
|
|
413
|
-
const targets = relation2.targets ?? [];
|
|
414
|
-
if (targets.length === 1 && targets[0]?.object === "*") return "internal";
|
|
415
|
-
return targets.length > 1 ? "code-only" : "none";
|
|
416
|
-
}
|
|
417
|
-
function supportsMaxItems(attribute) {
|
|
418
|
-
if (attribute.type === "multiselect") return true;
|
|
419
|
-
if (attribute.type === "relation") return attribute.cardinality === "many";
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
function supportsQualifiedProperties(type) {
|
|
423
|
-
return type === "relation" || type === "document";
|
|
424
|
-
}
|
|
425
|
-
function isRequiredForbidden(type) {
|
|
426
|
-
return type === "checkbox" || type === "formula" || type === "rollup";
|
|
427
|
-
}
|
|
428
|
-
function getDefaultValueCapability(type) {
|
|
429
|
-
if (type === "checkbox") return "automatic";
|
|
430
|
-
if (type === "formula" || type === "rollup") return "forbidden";
|
|
431
|
-
if (STATIC_DEFAULT_TYPES.has(type)) return "static";
|
|
432
|
-
return "forbidden";
|
|
433
|
-
}
|
|
434
|
-
function isDefaultColumnType(type) {
|
|
435
|
-
return isTableCellType(type);
|
|
436
|
-
}
|
|
437
|
-
function isTableCellType(type) {
|
|
438
|
-
return type !== "richtext" && type !== "document";
|
|
439
|
-
}
|
|
440
|
-
function isFormFieldType(type) {
|
|
441
|
-
return type !== "richtext";
|
|
442
|
-
}
|
|
443
|
-
function resolveEditMode(attribute) {
|
|
444
|
-
switch (attribute.type) {
|
|
445
|
-
case "checkbox":
|
|
446
|
-
return "inline";
|
|
447
|
-
case "number":
|
|
448
|
-
return attribute.renderAs === "rating" ? "inline" : "default";
|
|
449
|
-
case "select":
|
|
450
|
-
case "multiselect":
|
|
451
|
-
return attribute.renderAs === "badges" ? "inline" : "popover";
|
|
452
|
-
case "status":
|
|
453
|
-
case "relation":
|
|
454
|
-
case "user":
|
|
455
|
-
return "popover";
|
|
456
|
-
default:
|
|
457
|
-
return "default";
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
function isGroupableType(type) {
|
|
461
|
-
return type === "status" || type === "currency";
|
|
462
|
-
}
|
|
463
|
-
function isContentReadableType(type) {
|
|
464
|
-
return type === "richtext" || type === "document";
|
|
465
|
-
}
|
|
466
|
-
function hasFilterOperatorEntry(type) {
|
|
467
|
-
return Object.prototype.hasOwnProperty.call(ATTRIBUTE_FILTER_OPERATORS, type);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
71
|
// src/types/attributes.ts
|
|
471
72
|
var RELATION_TARGET_ANY = "*";
|
|
472
73
|
function isUniversalRelation(attr) {
|
|
@@ -487,10 +88,12 @@ var AUDIT_RESOURCE_TYPES = [
|
|
|
487
88
|
"record",
|
|
488
89
|
"object",
|
|
489
90
|
"attribute",
|
|
91
|
+
"view",
|
|
490
92
|
"user",
|
|
491
93
|
"role",
|
|
492
94
|
"settings",
|
|
493
|
-
"file"
|
|
95
|
+
"file",
|
|
96
|
+
"agent"
|
|
494
97
|
];
|
|
495
98
|
var AUDIT_ACTIONS = [
|
|
496
99
|
// Records
|
|
@@ -507,6 +110,10 @@ var AUDIT_ACTIONS = [
|
|
|
507
110
|
"attribute.created",
|
|
508
111
|
"attribute.updated",
|
|
509
112
|
"attribute.deleted",
|
|
113
|
+
// Schema - Views
|
|
114
|
+
"view.created",
|
|
115
|
+
"view.updated",
|
|
116
|
+
"view.deleted",
|
|
510
117
|
// Users
|
|
511
118
|
"user.created",
|
|
512
119
|
"user.invited",
|
|
@@ -528,6 +135,32 @@ var AUDIT_ACTIONS = [
|
|
|
528
135
|
"file.deleted"
|
|
529
136
|
];
|
|
530
137
|
|
|
138
|
+
// src/types/agent.ts
|
|
139
|
+
var SESSION_TERMINAL_STATUSES = [
|
|
140
|
+
"completed",
|
|
141
|
+
"failed",
|
|
142
|
+
"cancelled",
|
|
143
|
+
"timeout",
|
|
144
|
+
"expired"
|
|
145
|
+
];
|
|
146
|
+
function isTerminalSessionStatus(status2) {
|
|
147
|
+
return SESSION_TERMINAL_STATUSES.includes(status2);
|
|
148
|
+
}
|
|
149
|
+
var DEFAULT_APPROVAL_POLICY = Object.freeze({
|
|
150
|
+
mutation: "ask",
|
|
151
|
+
destructive: "ask",
|
|
152
|
+
outward: "ask"
|
|
153
|
+
});
|
|
154
|
+
var TODO_PLAN_STATUSES = ["active", "completed", "promoted", "abandoned"];
|
|
155
|
+
function agentDisplayName(agent2) {
|
|
156
|
+
return agent2.label?.trim() || agent2.name;
|
|
157
|
+
}
|
|
158
|
+
var TODO_STATUSES = ["pending", "in_progress", "completed", "blocked"];
|
|
159
|
+
var MAX_TODOS = 50;
|
|
160
|
+
var MAX_TODO_ID_CHARS = 80;
|
|
161
|
+
var MAX_TODO_DESCRIPTION_CHARS = 500;
|
|
162
|
+
var MAX_TODO_RESULT_CHARS = 2e3;
|
|
163
|
+
|
|
531
164
|
// src/types/document-layout.ts
|
|
532
165
|
var MAX_PRESET_DEPTH = 5;
|
|
533
166
|
|
|
@@ -543,21 +176,6 @@ function getErrorMessage(error) {
|
|
|
543
176
|
return String(error);
|
|
544
177
|
}
|
|
545
178
|
|
|
546
|
-
// src/types/filters.ts
|
|
547
|
-
var OPERATORS_BY_TYPE = ATTRIBUTE_FILTER_OPERATORS;
|
|
548
|
-
var NO_VALUE_OPERATORS = [
|
|
549
|
-
"is_empty",
|
|
550
|
-
"is_not_empty",
|
|
551
|
-
"is_checked",
|
|
552
|
-
"is_not_checked"
|
|
553
|
-
];
|
|
554
|
-
function isNoValueOperator(operator) {
|
|
555
|
-
return NO_VALUE_OPERATORS.includes(operator);
|
|
556
|
-
}
|
|
557
|
-
function getRollupFilterOperators2(attr) {
|
|
558
|
-
return getRollupFilterOperators(attr);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
179
|
// src/types/forms/definition.ts
|
|
562
180
|
function isFormDefinition(obj) {
|
|
563
181
|
return typeof obj === "object" && obj !== null && "slots" in obj && "steps" in obj && "name" in obj && typeof obj.name === "string" && Array.isArray(obj.slots) && Array.isArray(obj.steps);
|
|
@@ -610,29 +228,6 @@ var NoopGeocodingAdapter = class {
|
|
|
610
228
|
}
|
|
611
229
|
};
|
|
612
230
|
|
|
613
|
-
// src/types/objects.ts
|
|
614
|
-
var SYSTEM_FIELD_NAMES = [
|
|
615
|
-
"id",
|
|
616
|
-
"createdAt",
|
|
617
|
-
"updatedAt",
|
|
618
|
-
"createdBy",
|
|
619
|
-
"lastUpdatedBy"
|
|
620
|
-
];
|
|
621
|
-
var RESERVED_ATTRIBUTE_NAMES = [
|
|
622
|
-
// System fields (auto-managed)
|
|
623
|
-
...SYSTEM_FIELD_NAMES,
|
|
624
|
-
// Other ObjectRecord properties
|
|
625
|
-
"objectId",
|
|
626
|
-
"label",
|
|
627
|
-
"embeddingText",
|
|
628
|
-
"values",
|
|
629
|
-
"metadata",
|
|
630
|
-
"deletedAt",
|
|
631
|
-
"deletedBy",
|
|
632
|
-
"schemaVersion"
|
|
633
|
-
];
|
|
634
|
-
var RESERVED_OBJECT_NAMES = ["skill"];
|
|
635
|
-
|
|
636
231
|
// src/types/permissions.ts
|
|
637
232
|
var ALL_ACTIONS = ["read", "create", "update", "delete", "manage"];
|
|
638
233
|
function actionsToAccessLevel(actions) {
|
|
@@ -668,6 +263,11 @@ function hasOptions(attr) {
|
|
|
668
263
|
// src/types/user-profiles.ts
|
|
669
264
|
var USER_STATUSES = ["active", "suspended"];
|
|
670
265
|
|
|
266
|
+
// src/types/schema-state.ts
|
|
267
|
+
function viewStateKey(view) {
|
|
268
|
+
return `${view.object}:${view.name}:${view.type}`;
|
|
269
|
+
}
|
|
270
|
+
|
|
671
271
|
// src/types/views.ts
|
|
672
272
|
function isDetailView(view) {
|
|
673
273
|
return view.type === "detail";
|
|
@@ -676,12 +276,15 @@ function isListView(view) {
|
|
|
676
276
|
return view.type === "list";
|
|
677
277
|
}
|
|
678
278
|
function isFieldGroup(group2) {
|
|
679
|
-
return
|
|
279
|
+
return group2.type === "fields";
|
|
680
280
|
}
|
|
681
281
|
function isRelationGroup(group2) {
|
|
682
282
|
return group2.type === "relation";
|
|
683
283
|
}
|
|
684
284
|
|
|
285
|
+
// src/types/pagination.ts
|
|
286
|
+
var ESTIMATED_COUNT_CAP = 1e4;
|
|
287
|
+
|
|
685
288
|
// src/lib/object-helpers.ts
|
|
686
289
|
function isEmptyObject(obj) {
|
|
687
290
|
if (obj === null || obj === void 0) {
|
|
@@ -699,6 +302,21 @@ function toUndefinedIfEmpty(obj) {
|
|
|
699
302
|
return isNotEmpty(obj) ? obj : void 0;
|
|
700
303
|
}
|
|
701
304
|
|
|
305
|
+
// src/lib/byte-size.ts
|
|
306
|
+
var MAX_UNIT_INDEX = 4;
|
|
307
|
+
function computeByteMagnitude(bytes) {
|
|
308
|
+
if (bytes <= 0) return { value: 0, unitIndex: 0 };
|
|
309
|
+
const k = 1e3;
|
|
310
|
+
const unitIndex = Math.min(MAX_UNIT_INDEX, Math.floor(Math.log(bytes) / Math.log(k)));
|
|
311
|
+
const value = Number.parseFloat((bytes / k ** unitIndex).toFixed(1));
|
|
312
|
+
return { value, unitIndex };
|
|
313
|
+
}
|
|
314
|
+
var BYTE_UNIT_LABELS = ["B", "KB", "MB", "GB", "TB"];
|
|
315
|
+
function formatByteSize(bytes) {
|
|
316
|
+
const { value, unitIndex } = computeByteMagnitude(bytes);
|
|
317
|
+
return `${value} ${BYTE_UNIT_LABELS[unitIndex]}`;
|
|
318
|
+
}
|
|
319
|
+
|
|
702
320
|
// src/lib/document-attribute.ts
|
|
703
321
|
var DOCUMENT_SYSTEM_ATTRIBUTES = {
|
|
704
322
|
ATTACHMENTS: "attachments"
|
|
@@ -706,13 +324,13 @@ var DOCUMENT_SYSTEM_ATTRIBUTES = {
|
|
|
706
324
|
function isDocumentAttribute(attr) {
|
|
707
325
|
return attr.type === "document";
|
|
708
326
|
}
|
|
709
|
-
function
|
|
710
|
-
if (!
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
return
|
|
327
|
+
function matchesAccepts(file, accepts) {
|
|
328
|
+
if (!accepts || accepts.length === 0) return true;
|
|
329
|
+
const name = file.name.toLowerCase();
|
|
330
|
+
return accepts.some((pattern) => {
|
|
331
|
+
if (pattern.endsWith("/*")) return file.mimeType.startsWith(pattern.slice(0, -1));
|
|
332
|
+
if (pattern.startsWith(".")) return name.endsWith(pattern.toLowerCase());
|
|
333
|
+
return file.mimeType === pattern;
|
|
716
334
|
});
|
|
717
335
|
}
|
|
718
336
|
|
|
@@ -966,6 +584,19 @@ var labelExpressionSchema = z.string().min(1, "labelExpression cannot be empty")
|
|
|
966
584
|
message: `Invalid pipe name. Valid pipes: ${ALL_PIPES.join(", ")}`
|
|
967
585
|
}
|
|
968
586
|
);
|
|
587
|
+
function validateLabelExpression(expression) {
|
|
588
|
+
const result = labelExpressionSchema.safeParse(expression);
|
|
589
|
+
if (!result.success) {
|
|
590
|
+
return {
|
|
591
|
+
success: false,
|
|
592
|
+
error: result.error.issues[0]?.message ?? "Invalid labelExpression"
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
return {
|
|
596
|
+
success: true,
|
|
597
|
+
attributes: extractAttributeNames(expression)
|
|
598
|
+
};
|
|
599
|
+
}
|
|
969
600
|
var simplePipes = {
|
|
970
601
|
/** Convert to uppercase */
|
|
971
602
|
UPPER: (v) => String(v).toUpperCase(),
|
|
@@ -1124,6 +755,13 @@ function getUserDisplayName(user2) {
|
|
|
1124
755
|
return user2.email?.split("@")[0] ?? "";
|
|
1125
756
|
}
|
|
1126
757
|
|
|
758
|
+
// src/lib/record-creator.ts
|
|
759
|
+
var RECORD_CREATOR_ROOT_ACTOR_METADATA_KEY = "__creatorRootActorId";
|
|
760
|
+
function getRecordCreatorPrincipalId(record) {
|
|
761
|
+
const creatorRootActorId = record.metadata?.[RECORD_CREATOR_ROOT_ACTOR_METADATA_KEY];
|
|
762
|
+
return typeof creatorRootActorId === "string" && creatorRootActorId.length > 0 ? creatorRootActorId : record.createdBy;
|
|
763
|
+
}
|
|
764
|
+
|
|
1127
765
|
// src/constants/attribute-columns.ts
|
|
1128
766
|
var DB_COLUMN_FIELDS = /* @__PURE__ */ new Set([
|
|
1129
767
|
"id",
|
|
@@ -1201,17 +839,25 @@ var DEFAULT_ROLES = {
|
|
|
1201
839
|
/** Standard user - can work with business data and view people */
|
|
1202
840
|
MEMBER: "member",
|
|
1203
841
|
/** Default role for agent actors - CRUD on records + documents/files */
|
|
1204
|
-
AGENT_DEFAULT: "agent_default"
|
|
842
|
+
AGENT_DEFAULT: "agent_default",
|
|
843
|
+
/**
|
|
844
|
+
* Default role for reflex actors — deliberately NO record access (D22).
|
|
845
|
+
* An agent is interactive, watched, and acts once; a reflex is unattended and
|
|
846
|
+
* repeats. Real access is a per-reflex role derived from its first rehearsal.
|
|
847
|
+
*/
|
|
848
|
+
REFLEX_DEFAULT: "reflex_default"
|
|
1205
849
|
};
|
|
1206
850
|
var DEFAULT_ROLE_LABELS = {
|
|
1207
851
|
owner: "Owner",
|
|
1208
852
|
member: "Member",
|
|
1209
|
-
agent_default: "Agent Default"
|
|
853
|
+
agent_default: "Agent Default",
|
|
854
|
+
reflex_default: "Reflex Default"
|
|
1210
855
|
};
|
|
1211
856
|
var DEFAULT_ROLE_DESCRIPTIONS = {
|
|
1212
857
|
owner: "Full access to all platform features and data",
|
|
1213
858
|
member: "Can view, create, edit and delete business data",
|
|
1214
|
-
agent_default: "Default role for AI agents \u2014 CRUD on records plus documents and files"
|
|
859
|
+
agent_default: "Default role for AI agents \u2014 CRUD on records plus documents and files",
|
|
860
|
+
reflex_default: "Default role for reflexes \u2014 no data access; each reflex is granted exactly what its rehearsal showed it uses"
|
|
1215
861
|
};
|
|
1216
862
|
var ALL_ACTIONS2 = ["read", "create", "update", "delete", "manage"];
|
|
1217
863
|
var MEMBER_CONNECTOR_ACTIONS = ["read", "create", "delete"];
|
|
@@ -1241,6 +887,13 @@ var DEFAULT_ROLE_PERMISSIONS = {
|
|
|
1241
887
|
{ target: "session", actions: ["observe"] }
|
|
1242
888
|
],
|
|
1243
889
|
object: [{ target: "*", actions: ["read", "create", "update", "delete"] }]
|
|
890
|
+
},
|
|
891
|
+
reflex_default: {
|
|
892
|
+
// Intentionally empty (D22): a reflex starts with no access at all. Real
|
|
893
|
+
// access is a per-reflex role derived from its first rehearsal, not a
|
|
894
|
+
// shared default.
|
|
895
|
+
system: [],
|
|
896
|
+
object: []
|
|
1244
897
|
}
|
|
1245
898
|
};
|
|
1246
899
|
function isDefaultRole(roleName) {
|
|
@@ -1250,6 +903,19 @@ var VALID_ICONS = new Set(ICONS);
|
|
|
1250
903
|
var ATTRIBUTE_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
1251
904
|
var MAX_NAME_LENGTH = 63;
|
|
1252
905
|
var MAX_LABEL_LENGTH = 128;
|
|
906
|
+
var OBJECT_NAME_SCHEMA = z2.string().min(1, "Object name cannot be empty").max(63, "Object name is too long (max 63 characters)").regex(/^[a-z][a-z0-9-]*$/, {
|
|
907
|
+
message: "Invalid object name format.\nName must be in kebab-case (slug format):\n \u2705 Valid: 'products', 'user-profiles', 'order-items'\n \u274C Invalid: 'Products', 'userProfiles', 'user_profiles'"
|
|
908
|
+
});
|
|
909
|
+
function validateObjectName(name) {
|
|
910
|
+
try {
|
|
911
|
+
OBJECT_NAME_SCHEMA.parse(name);
|
|
912
|
+
} catch (error) {
|
|
913
|
+
if (error instanceof z2.ZodError) {
|
|
914
|
+
throw new SchemaError(error.issues[0].message, SchemaErrorCode.INVALID_OBJECT_NAME);
|
|
915
|
+
}
|
|
916
|
+
throw error;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
1253
919
|
function assertUniqueBy(items, getKey, buildError) {
|
|
1254
920
|
const seen = /* @__PURE__ */ new Set();
|
|
1255
921
|
for (const item of items) {
|
|
@@ -1346,12 +1012,28 @@ var AgentBuilder = class {
|
|
|
1346
1012
|
if (!config.name || config.name.trim().length === 0) {
|
|
1347
1013
|
throw new ValidationError("Agent name is required", []);
|
|
1348
1014
|
}
|
|
1349
|
-
this.bp = { name: config.name, system: true, triggers: [] };
|
|
1015
|
+
this.bp = { name: config.name, system: true, visibility: "workspace", triggers: [] };
|
|
1350
1016
|
}
|
|
1351
1017
|
description(value) {
|
|
1352
1018
|
this.bp.description = value;
|
|
1353
1019
|
return this;
|
|
1354
1020
|
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Display text shown wherever this agent's identity is rendered in the
|
|
1023
|
+
* UI — a separate concern from `name` (the stable identity the boot sync
|
|
1024
|
+
* matches rows on). Falls back to `name` when never called.
|
|
1025
|
+
*
|
|
1026
|
+
* @example
|
|
1027
|
+
* ```typescript
|
|
1028
|
+
* agent({ name: "architecte" })
|
|
1029
|
+
* .label("Architecte")
|
|
1030
|
+
* // ...
|
|
1031
|
+
* ```
|
|
1032
|
+
*/
|
|
1033
|
+
label(value) {
|
|
1034
|
+
this.bp.label = value;
|
|
1035
|
+
return this;
|
|
1036
|
+
}
|
|
1355
1037
|
icon(value) {
|
|
1356
1038
|
this.bp.icon = value;
|
|
1357
1039
|
return this;
|
|
@@ -1390,6 +1072,32 @@ var AgentBuilder = class {
|
|
|
1390
1072
|
Object.assign(this.bp, value);
|
|
1391
1073
|
return this;
|
|
1392
1074
|
}
|
|
1075
|
+
approval(value) {
|
|
1076
|
+
this.bp.approval = { ...DEFAULT_APPROVAL_POLICY, ...this.bp.approval, ...value };
|
|
1077
|
+
return this;
|
|
1078
|
+
}
|
|
1079
|
+
/** Runtime-agent visibility. Code-declared system agents must stay workspace-visible. */
|
|
1080
|
+
visibility(value) {
|
|
1081
|
+
this.bp.visibility = value;
|
|
1082
|
+
return this;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Gate this agent behind a system permission: an actor lacking `action` on
|
|
1086
|
+
* `resource` never sees it in the agent list and cannot open a session
|
|
1087
|
+
* against it. Reuses the same permission vocabulary that guards the
|
|
1088
|
+
* matching HTTP surface — do not invent a new resource/action pair.
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```typescript
|
|
1092
|
+
* agent({ name: "architecte" })
|
|
1093
|
+
* .requiresPermission("architect", "update")
|
|
1094
|
+
* // ...
|
|
1095
|
+
* ```
|
|
1096
|
+
*/
|
|
1097
|
+
requiresPermission(resource, action) {
|
|
1098
|
+
this.bp.requiredPermission = { resource, action };
|
|
1099
|
+
return this;
|
|
1100
|
+
}
|
|
1393
1101
|
/**
|
|
1394
1102
|
* Declare a trigger. `name` is the stable identity the boot sync uses to
|
|
1395
1103
|
* reconcile trigger rows; `enabled` defaults to true.
|
|
@@ -1422,6 +1130,12 @@ var AgentBuilder = class {
|
|
|
1422
1130
|
if (!this.bp.model) {
|
|
1423
1131
|
throw new ValidationError(`Agent "${this.bp.name}": model is required`, []);
|
|
1424
1132
|
}
|
|
1133
|
+
if (this.bp.system && this.bp.visibility === "private") {
|
|
1134
|
+
throw new ValidationError(
|
|
1135
|
+
`Agent "${this.bp.name}": system agents must use workspace visibility`,
|
|
1136
|
+
[]
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1425
1139
|
assertUniqueBy(
|
|
1426
1140
|
this.bp.triggers,
|
|
1427
1141
|
(t) => t.name,
|
|
@@ -1429,6 +1143,7 @@ var AgentBuilder = class {
|
|
|
1429
1143
|
);
|
|
1430
1144
|
return {
|
|
1431
1145
|
...this.bp,
|
|
1146
|
+
visibility: this.bp.visibility ?? "workspace",
|
|
1432
1147
|
config: this.bp.config ?? DEFAULT_AGENT_EXECUTION_CONFIG,
|
|
1433
1148
|
systemPrompt: this.bp.systemPrompt,
|
|
1434
1149
|
model: this.bp.model
|
|
@@ -1600,6 +1315,7 @@ var TextAttributeBuilder = class extends BaseAttributeBuilder {
|
|
|
1600
1315
|
}
|
|
1601
1316
|
pattern(value) {
|
|
1602
1317
|
this.attr.pattern = value;
|
|
1318
|
+
this.attr.format = void 0;
|
|
1603
1319
|
return this;
|
|
1604
1320
|
}
|
|
1605
1321
|
multiline(value = true) {
|
|
@@ -1618,21 +1334,24 @@ var TextAttributeBuilder = class extends BaseAttributeBuilder {
|
|
|
1618
1334
|
* Set email validation pattern
|
|
1619
1335
|
*/
|
|
1620
1336
|
email() {
|
|
1621
|
-
this.attr.
|
|
1337
|
+
this.attr.format = "email";
|
|
1338
|
+
this.attr.pattern = void 0;
|
|
1622
1339
|
return this;
|
|
1623
1340
|
}
|
|
1624
1341
|
/**
|
|
1625
1342
|
* Set URL validation pattern
|
|
1626
1343
|
*/
|
|
1627
1344
|
url() {
|
|
1628
|
-
this.attr.
|
|
1345
|
+
this.attr.format = "url";
|
|
1346
|
+
this.attr.pattern = void 0;
|
|
1629
1347
|
return this;
|
|
1630
1348
|
}
|
|
1631
1349
|
/**
|
|
1632
1350
|
* Set slug validation pattern
|
|
1633
1351
|
*/
|
|
1634
1352
|
slug() {
|
|
1635
|
-
this.attr.
|
|
1353
|
+
this.attr.format = "slug";
|
|
1354
|
+
this.attr.pattern = void 0;
|
|
1636
1355
|
return this;
|
|
1637
1356
|
}
|
|
1638
1357
|
};
|
|
@@ -3001,17 +2720,7 @@ var ObjectBuilder = class {
|
|
|
3001
2720
|
if (name === void 0) {
|
|
3002
2721
|
return;
|
|
3003
2722
|
}
|
|
3004
|
-
|
|
3005
|
-
message: "Invalid object name format.\nName must be in kebab-case (slug format):\n \u2705 Valid: 'products', 'user-profiles', 'order-items'\n \u274C Invalid: 'Products', 'userProfiles', 'user_profiles'"
|
|
3006
|
-
});
|
|
3007
|
-
try {
|
|
3008
|
-
objectNameSchema.parse(name);
|
|
3009
|
-
} catch (error) {
|
|
3010
|
-
if (error instanceof z3.ZodError) {
|
|
3011
|
-
throw new SchemaError(error.issues[0].message, SchemaErrorCode.INVALID_OBJECT_NAME);
|
|
3012
|
-
}
|
|
3013
|
-
throw error;
|
|
3014
|
-
}
|
|
2723
|
+
validateObjectName(name);
|
|
3015
2724
|
}
|
|
3016
2725
|
};
|
|
3017
2726
|
function object(config) {
|
|
@@ -3046,7 +2755,7 @@ function validatePresetStructure(presetId, nodes, depth) {
|
|
|
3046
2755
|
}
|
|
3047
2756
|
var GroupBuilder = class {
|
|
3048
2757
|
constructor(id, label) {
|
|
3049
|
-
this.data = { fields: [] };
|
|
2758
|
+
this.data = { type: "fields", fields: [] };
|
|
3050
2759
|
this.data.id = id;
|
|
3051
2760
|
this.data.label = label;
|
|
3052
2761
|
}
|
|
@@ -3168,17 +2877,6 @@ var RelationGroupBuilder = class {
|
|
|
3168
2877
|
this.data.allowCreate = value;
|
|
3169
2878
|
return this;
|
|
3170
2879
|
}
|
|
3171
|
-
/**
|
|
3172
|
-
* Enable two-level traversal (through mode).
|
|
3173
|
-
* Parent rows become grouping headers; sub-rows from `attribute` are the primary display.
|
|
3174
|
-
*
|
|
3175
|
-
* @param attribute - Relation attribute on the first-level target object
|
|
3176
|
-
* @example .through("companies") — display companies linked via each member
|
|
3177
|
-
*/
|
|
3178
|
-
through(attribute) {
|
|
3179
|
-
this.data.through = { attribute };
|
|
3180
|
-
return this;
|
|
3181
|
-
}
|
|
3182
2880
|
/**
|
|
3183
2881
|
* Build the relation group definition
|
|
3184
2882
|
*/
|
|
@@ -3299,29 +2997,6 @@ var TableTabConfig = class {
|
|
|
3299
2997
|
this.tabData.sorts.push({ attribute, direction });
|
|
3300
2998
|
return this;
|
|
3301
2999
|
}
|
|
3302
|
-
/**
|
|
3303
|
-
* Traverse a 2nd-level relation to display nested data.
|
|
3304
|
-
* When active, `tab.columns` stores the 2nd-level object's attribute names.
|
|
3305
|
-
*
|
|
3306
|
-
* @param attribute - Relation attribute on the first-level target object
|
|
3307
|
-
* @example .table("members").through("companies").columns(["name", "sector"])
|
|
3308
|
-
*/
|
|
3309
|
-
through(attribute) {
|
|
3310
|
-
this.tabData.through = { attribute };
|
|
3311
|
-
return this;
|
|
3312
|
-
}
|
|
3313
|
-
/**
|
|
3314
|
-
* Show _source and _target columns in flattened (through) view
|
|
3315
|
-
*/
|
|
3316
|
-
showSourceTarget(value = true) {
|
|
3317
|
-
if (!this.tabData.through) {
|
|
3318
|
-
throw new Error(
|
|
3319
|
-
`[TableTabConfig] showSourceTarget() requires through() to be called first for tab "${this.tabData.name}"`
|
|
3320
|
-
);
|
|
3321
|
-
}
|
|
3322
|
-
this.tabData.through.showSourceTarget = value;
|
|
3323
|
-
return this;
|
|
3324
|
-
}
|
|
3325
3000
|
/**
|
|
3326
3001
|
* Continue building with a new tab
|
|
3327
3002
|
*/
|
|
@@ -3779,6 +3454,17 @@ var DetailViewBuilder = class {
|
|
|
3779
3454
|
function detailView(name, label) {
|
|
3780
3455
|
return new DetailViewBuilder(name, label);
|
|
3781
3456
|
}
|
|
3457
|
+
function findProtectedTabFilterAttribute(node) {
|
|
3458
|
+
if (Array.isArray(node)) {
|
|
3459
|
+
return node.map(findProtectedTabFilterAttribute).find((attribute) => attribute !== void 0);
|
|
3460
|
+
}
|
|
3461
|
+
if (node === null || typeof node !== "object") return void 0;
|
|
3462
|
+
const candidate = node;
|
|
3463
|
+
if (candidate.attribute === "visibility" || candidate.attribute === "ownedBy") {
|
|
3464
|
+
return candidate.attribute;
|
|
3465
|
+
}
|
|
3466
|
+
return findProtectedTabFilterAttribute(candidate.rules) ?? findProtectedTabFilterAttribute(candidate.groups);
|
|
3467
|
+
}
|
|
3782
3468
|
var ListViewBuilder = class {
|
|
3783
3469
|
constructor(name, label) {
|
|
3784
3470
|
validateViewName(name, "ListViewBuilder", {
|
|
@@ -3888,28 +3574,39 @@ var ListViewBuilder = class {
|
|
|
3888
3574
|
combinator: this.data.defaultFilters.combinator,
|
|
3889
3575
|
rules: this.data.defaultFilters.rules
|
|
3890
3576
|
} : void 0,
|
|
3891
|
-
tabs: this.data.tabs.map((tab) =>
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3577
|
+
tabs: this.data.tabs.map((tab) => {
|
|
3578
|
+
const common = {
|
|
3579
|
+
id: tab.id,
|
|
3580
|
+
label: tab.label,
|
|
3581
|
+
icon: tab.icon,
|
|
3582
|
+
default: tab.default,
|
|
3583
|
+
// Which records the tab scopes to — a tab-level scope, never a
|
|
3584
|
+
// record's own column (see the visibility notes in CLAUDE.md).
|
|
3585
|
+
visibility: tab.visibility,
|
|
3586
|
+
columns: tab.columns,
|
|
3587
|
+
filters: tab.filters ? {
|
|
3588
|
+
id: generateId(),
|
|
3589
|
+
combinator: tab.filters.combinator,
|
|
3590
|
+
rules: tab.filters.rules
|
|
3591
|
+
} : void 0,
|
|
3592
|
+
sorts: tab.sorts,
|
|
3593
|
+
createMode: tab.createMode
|
|
3594
|
+
};
|
|
3595
|
+
return tab.layout === "kanban" ? {
|
|
3596
|
+
...common,
|
|
3597
|
+
layout: "kanban",
|
|
3598
|
+
groupByAttribute: tab.groupByAttribute,
|
|
3599
|
+
cardUserAttribute: tab.cardUserAttribute,
|
|
3600
|
+
cardDateAttribute: tab.cardDateAttribute,
|
|
3601
|
+
kanbanColumnOrder: tab.kanbanColumnOrder,
|
|
3602
|
+
kanbanColumnVisibility: tab.kanbanColumnVisibility,
|
|
3603
|
+
kanbanPinnedColumns: tab.kanbanPinnedColumns
|
|
3604
|
+
} : {
|
|
3605
|
+
...common,
|
|
3606
|
+
layout: "table",
|
|
3607
|
+
columnSizing: tab.columnSizing
|
|
3608
|
+
};
|
|
3609
|
+
})
|
|
3913
3610
|
};
|
|
3914
3611
|
return {
|
|
3915
3612
|
name: this.data.name,
|
|
@@ -3931,6 +3628,7 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
3931
3628
|
this.tabData = {
|
|
3932
3629
|
id,
|
|
3933
3630
|
label,
|
|
3631
|
+
visibility: "all",
|
|
3934
3632
|
layout: "table",
|
|
3935
3633
|
columns: []
|
|
3936
3634
|
};
|
|
@@ -3949,6 +3647,14 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
3949
3647
|
this.tabData.default = true;
|
|
3950
3648
|
return this;
|
|
3951
3649
|
}
|
|
3650
|
+
/**
|
|
3651
|
+
* Set the record scope this tab reads. Defaults to `"all"` (no scope: every
|
|
3652
|
+
* workspace record plus the viewer's own private ones).
|
|
3653
|
+
*/
|
|
3654
|
+
visibility(value) {
|
|
3655
|
+
this.tabData.visibility = value;
|
|
3656
|
+
return this;
|
|
3657
|
+
}
|
|
3952
3658
|
/**
|
|
3953
3659
|
* Set the layout to table (default)
|
|
3954
3660
|
*/
|
|
@@ -4042,6 +3748,11 @@ var ListViewTabConfigBuilder = class _ListViewTabConfigBuilder {
|
|
|
4042
3748
|
* @example .filter({ combinator: "and", rules: [{ attribute: "status", operator: "is", value: "active" }] })
|
|
4043
3749
|
*/
|
|
4044
3750
|
filter(filters) {
|
|
3751
|
+
const protectedAttribute = findProtectedTabFilterAttribute(filters);
|
|
3752
|
+
if (protectedAttribute) {
|
|
3753
|
+
const message = `Tab filters cannot target "${protectedAttribute}". Use .visibility("private")`;
|
|
3754
|
+
throw new ValidationError(message, [{ path: ["filters"], message }]);
|
|
3755
|
+
}
|
|
4045
3756
|
this.tabData.filters = filters;
|
|
4046
3757
|
return this;
|
|
4047
3758
|
}
|
|
@@ -4799,7 +4510,7 @@ var SKILL_OBJECT = object({ name: "skill", label: "Skill" }).sealed().icon("spar
|
|
|
4799
4510
|
)
|
|
4800
4511
|
).attribute(richtext({ name: "content", label: "Content" }).defaultValue(SKILL_CONTENT_TEMPLATE)).build();
|
|
4801
4512
|
var SKILL_VIEW = detailView("skill-detail", "Skill").for("skill").default().sidePanel({ attributes: ["name", "description"] }).tab("content", "Content").richtext("content").titleAttribute("name").done().tab("files", "Files").documents().done().build();
|
|
4802
|
-
var SKILL_LIST_VIEW = listView("skill-list", "Skills").for("skill").default().tab("
|
|
4513
|
+
var SKILL_LIST_VIEW = listView("skill-list", "Skills").for("skill").default().tab("workspace", "Skills").default().icon("table").visibility("workspace").table().columns("name", "description").sort("name", "asc").tab("mine", "Mes skills").icon("lock").visibility("private").table().columns("name", "description").sort("name", "asc").build();
|
|
4803
4514
|
var MEMORY_OBJECT = object({ name: "memory", label: "Memory" }).sealed().icon("database").order(Number.MAX_SAFE_INTEGER).pluralLabel("Memories").labelExpression("{{ name }}").embeddingExpression("{{ name }}\n{{ description }}\n{{ content }}").attribute(text({ name: "name", label: "Name" }).maxLength(MEMORY_NAME_MAX_LENGTH).required()).attribute(
|
|
4804
4515
|
text({ name: "description", label: "Description" }).multiline().maxLength(MEMORY_DESCRIPTION_MAX_LENGTH).required()
|
|
4805
4516
|
).attribute(text({ name: "content", label: "Content" }).multiline()).attribute(
|
|
@@ -4809,9 +4520,9 @@ var MEMORY_OBJECT = object({ name: "memory", label: "Memory" }).sealed().icon("d
|
|
|
4809
4520
|
{ value: "feedback", label: "Feedback" },
|
|
4810
4521
|
{ value: "reference", label: "Reference" }
|
|
4811
4522
|
])
|
|
4812
|
-
).attribute(
|
|
4813
|
-
var MEMORY_VIEW = detailView("memory-detail", "Memory").for("memory").default().sidePanel({ attributes: ["name", "description", "kind", "
|
|
4814
|
-
var MEMORY_LIST_VIEW = listView("memory-list", "Memories").for("memory").default().tab("
|
|
4523
|
+
).attribute(relation({ name: "subjects", label: "Subjects" }).toAny().many()).attribute(relation({ name: "links", label: "Links" }).to("memory").many()).build();
|
|
4524
|
+
var MEMORY_VIEW = detailView("memory-detail", "Memory").for("memory").default().sidePanel({ attributes: ["name", "description", "kind", "subjects", "links"] }).tab("content", "Content").form(group("content", "Content").field("content", { span: 12 })).build();
|
|
4525
|
+
var MEMORY_LIST_VIEW = listView("memory-list", "Memories").for("memory").default().tab("workspace", "Memories").default().icon("table").visibility("workspace").table().columns("name", "kind", "description", "createdAt").sort("name", "asc").tab("mine", "Mes m\xE9moires").icon("lock").visibility("private").table().columns("name", "kind", "description", "createdAt").sort("name", "asc").build();
|
|
4815
4526
|
|
|
4816
4527
|
// src/views/registry.ts
|
|
4817
4528
|
function cloneViewDefinition(view) {
|
|
@@ -5016,6 +4727,7 @@ function generateDefaultDetailView(object2, options = {}) {
|
|
|
5016
4727
|
{
|
|
5017
4728
|
id: "general",
|
|
5018
4729
|
label: "General",
|
|
4730
|
+
type: "fields",
|
|
5019
4731
|
fields: sortedAttrs.map(attributeToField),
|
|
5020
4732
|
order: 0
|
|
5021
4733
|
}
|
|
@@ -5070,6 +4782,7 @@ function generateDefaultListView(object2, options = {}) {
|
|
|
5070
4782
|
id: "all",
|
|
5071
4783
|
label: "All",
|
|
5072
4784
|
default: true,
|
|
4785
|
+
visibility: "workspace",
|
|
5073
4786
|
layout: "table",
|
|
5074
4787
|
columns
|
|
5075
4788
|
}
|
|
@@ -5329,6 +5042,8 @@ var BROWSER_PREVIEW_STATUSES = ["live", "paused", "ended", "disconnected"];
|
|
|
5329
5042
|
var LIVE_EVENT_TYPE_REGISTRY = {
|
|
5330
5043
|
"record.patch": true,
|
|
5331
5044
|
"record.deleted": true,
|
|
5045
|
+
"record.removed": true,
|
|
5046
|
+
"record.created": true,
|
|
5332
5047
|
"view.projection.stale": true,
|
|
5333
5048
|
"agent.session.patch": true,
|
|
5334
5049
|
"agent.unread.patch": true,
|
|
@@ -5375,6 +5090,33 @@ var BROWSER_PREVIEW_DESCRIPTOR_KEYS = [
|
|
|
5375
5090
|
"sequence",
|
|
5376
5091
|
"updatedAt"
|
|
5377
5092
|
];
|
|
5093
|
+
var RECORD_REMOVED_PAYLOAD_KEYS = [
|
|
5094
|
+
"type",
|
|
5095
|
+
"objectId",
|
|
5096
|
+
"recordId",
|
|
5097
|
+
"recordVersion"
|
|
5098
|
+
];
|
|
5099
|
+
var RECORD_CREATED_PAYLOAD_KEYS = [
|
|
5100
|
+
"type",
|
|
5101
|
+
"objectId",
|
|
5102
|
+
"recordId",
|
|
5103
|
+
"recordVersion",
|
|
5104
|
+
"record"
|
|
5105
|
+
];
|
|
5106
|
+
var RECORD_LIVE_SNAPSHOT_KEYS = [
|
|
5107
|
+
"id",
|
|
5108
|
+
"objectId",
|
|
5109
|
+
"visibility",
|
|
5110
|
+
"ownedBy",
|
|
5111
|
+
"label",
|
|
5112
|
+
"values",
|
|
5113
|
+
"metadata",
|
|
5114
|
+
"createdAt",
|
|
5115
|
+
"updatedAt",
|
|
5116
|
+
"createdBy",
|
|
5117
|
+
"lastUpdatedBy",
|
|
5118
|
+
"schemaVersion"
|
|
5119
|
+
];
|
|
5378
5120
|
function isLiveEventType(value) {
|
|
5379
5121
|
return typeof value === "string" && LIVE_EVENT_TYPES.includes(value);
|
|
5380
5122
|
}
|
|
@@ -5393,6 +5135,10 @@ function isLiveEventPayloadForType(type, payload) {
|
|
|
5393
5135
|
return isRecordPatchPayload(payload);
|
|
5394
5136
|
case "record.deleted":
|
|
5395
5137
|
return isRecordDeletedPayload(payload);
|
|
5138
|
+
case "record.removed":
|
|
5139
|
+
return isRecordRemovedPayload(payload);
|
|
5140
|
+
case "record.created":
|
|
5141
|
+
return isRecordCreatedPayload(payload);
|
|
5396
5142
|
case "view.projection.stale":
|
|
5397
5143
|
return isViewProjectionStalePayload(payload);
|
|
5398
5144
|
case "agent.session.patch":
|
|
@@ -5488,6 +5234,15 @@ function isRecordPatchPayload(payload) {
|
|
|
5488
5234
|
function isRecordDeletedPayload(payload) {
|
|
5489
5235
|
return payload.type === "record.deleted" && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion") && hasString(payload, "deletedAt");
|
|
5490
5236
|
}
|
|
5237
|
+
function isRecordRemovedPayload(payload) {
|
|
5238
|
+
return payload.type === "record.removed" && hasOnlyKeys(payload, RECORD_REMOVED_PAYLOAD_KEYS) && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion");
|
|
5239
|
+
}
|
|
5240
|
+
function isRecordLiveSnapshot(value) {
|
|
5241
|
+
return isRecord(value) && hasOnlyKeys(value, RECORD_LIVE_SNAPSHOT_KEYS) && hasString(value, "id") && hasString(value, "objectId") && isOneOf(value.visibility, ["workspace", "private"]) && isNullableString(value.ownedBy) && (value.visibility === "workspace" && value.ownedBy === null || value.visibility === "private" && isNonEmptyString(value.ownedBy)) && hasString(value, "label") && isRecord(value.values) && hasOptional(value, "metadata", isRecord) && hasIsoDateString(value, "createdAt") && hasIsoDateString(value, "updatedAt") && hasOptional(value, "createdBy", isString) && hasOptional(value, "lastUpdatedBy", isString) && hasVersion(value, "schemaVersion");
|
|
5242
|
+
}
|
|
5243
|
+
function isRecordCreatedPayload(payload) {
|
|
5244
|
+
return payload.type === "record.created" && hasOnlyKeys(payload, RECORD_CREATED_PAYLOAD_KEYS) && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion") && isRecordLiveSnapshot(payload.record) && payload.record.id === payload.recordId && payload.record.objectId === payload.objectId;
|
|
5245
|
+
}
|
|
5491
5246
|
function isViewProjectionStalePayload(payload) {
|
|
5492
5247
|
return payload.type === "view.projection.stale" && hasString(payload, "viewId") && isOneOf(payload.reason, VIEW_PROJECTION_STALE_REASONS);
|
|
5493
5248
|
}
|
|
@@ -6779,46 +6534,79 @@ var toDate2 = (v) => {
|
|
|
6779
6534
|
return Number.isNaN(d.getTime()) ? null : d;
|
|
6780
6535
|
};
|
|
6781
6536
|
var toArr = (v) => Array.isArray(v) ? v : v == null ? [] : [v];
|
|
6782
|
-
|
|
6783
|
-
const
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
const
|
|
6790
|
-
return
|
|
6537
|
+
var compareNumbers = (v, rv, cmp) => {
|
|
6538
|
+
const a = toNum(v);
|
|
6539
|
+
const b = toNum(rv);
|
|
6540
|
+
return a !== null && b !== null && cmp(a, b);
|
|
6541
|
+
};
|
|
6542
|
+
var compareDates = (v, rv, cmp) => {
|
|
6543
|
+
const a = toDate2(v);
|
|
6544
|
+
const b = toDate2(rv);
|
|
6545
|
+
return a !== null && b !== null && cmp(a.getTime(), b.getTime());
|
|
6546
|
+
};
|
|
6547
|
+
var equalsForAttr = (v, rv, attr) => {
|
|
6548
|
+
if (attr.type === "number" || attr.type === "currency") {
|
|
6549
|
+
const a = toNum(v);
|
|
6550
|
+
const b = toNum(rv);
|
|
6551
|
+
if (a !== null && b !== null) return a === b;
|
|
6552
|
+
}
|
|
6553
|
+
return toStr(v) === toStr(rv);
|
|
6554
|
+
};
|
|
6555
|
+
function isCheckboxEquality(attributeType, value) {
|
|
6556
|
+
return attributeType ? attributeType === "checkbox" : typeof value === "boolean";
|
|
6791
6557
|
}
|
|
6558
|
+
var orderingSpec = (cmp) => ({
|
|
6559
|
+
appliesTo: ["number", "currency", "date", "formula"],
|
|
6560
|
+
evaluateInMemory: (v, rv, attr) => attr.type === "date" ? compareDates(v, rv, cmp) : compareNumbers(v, rv, cmp)
|
|
6561
|
+
});
|
|
6792
6562
|
var OPERATOR_SPECS = {
|
|
6793
|
-
// ----
|
|
6563
|
+
// ---- equality ----
|
|
6794
6564
|
is: {
|
|
6795
|
-
appliesTo: [
|
|
6796
|
-
|
|
6565
|
+
appliesTo: [
|
|
6566
|
+
"text",
|
|
6567
|
+
"phone",
|
|
6568
|
+
"number",
|
|
6569
|
+
"currency",
|
|
6570
|
+
"checkbox",
|
|
6571
|
+
"status",
|
|
6572
|
+
"select",
|
|
6573
|
+
"date",
|
|
6574
|
+
"user",
|
|
6575
|
+
"relation",
|
|
6576
|
+
"formula"
|
|
6577
|
+
],
|
|
6578
|
+
evaluateInMemory: (v, rv, attr) => attr.type === "checkbox" ? v === true === (rv === true) : equalsForAttr(v, rv, attr)
|
|
6797
6579
|
},
|
|
6798
6580
|
is_not: {
|
|
6799
|
-
appliesTo: [
|
|
6800
|
-
|
|
6581
|
+
appliesTo: [
|
|
6582
|
+
"text",
|
|
6583
|
+
"phone",
|
|
6584
|
+
"number",
|
|
6585
|
+
"currency",
|
|
6586
|
+
"status",
|
|
6587
|
+
"select",
|
|
6588
|
+
"date",
|
|
6589
|
+
"user",
|
|
6590
|
+
"relation",
|
|
6591
|
+
"formula"
|
|
6592
|
+
],
|
|
6593
|
+
evaluateInMemory: (v, rv, attr) => !equalsForAttr(v, rv, attr)
|
|
6801
6594
|
},
|
|
6595
|
+
// ---- text substring ----
|
|
6802
6596
|
contains: {
|
|
6803
|
-
appliesTo: ["text", "phone", "
|
|
6804
|
-
evaluateInMemory: (v, rv) =>
|
|
6805
|
-
if (Array.isArray(v)) return v.map(toStr).includes(toStr(rv));
|
|
6806
|
-
return toStr(v).toLowerCase().includes(toStr(rv).toLowerCase());
|
|
6807
|
-
}
|
|
6597
|
+
appliesTo: ["text", "phone", "formula"],
|
|
6598
|
+
evaluateInMemory: (v, rv) => toStr(v).toLowerCase().includes(toStr(rv).toLowerCase())
|
|
6808
6599
|
},
|
|
6809
6600
|
not_contains: {
|
|
6810
|
-
appliesTo: ["text", "phone", "
|
|
6811
|
-
evaluateInMemory: (v, rv) =>
|
|
6812
|
-
if (Array.isArray(v)) return !v.map(toStr).includes(toStr(rv));
|
|
6813
|
-
return !toStr(v).toLowerCase().includes(toStr(rv).toLowerCase());
|
|
6814
|
-
}
|
|
6601
|
+
appliesTo: ["text", "phone", "formula"],
|
|
6602
|
+
evaluateInMemory: (v, rv) => !toStr(v).toLowerCase().includes(toStr(rv).toLowerCase())
|
|
6815
6603
|
},
|
|
6816
6604
|
starts_with: {
|
|
6817
|
-
appliesTo: ["text", "
|
|
6605
|
+
appliesTo: ["text", "phone"],
|
|
6818
6606
|
evaluateInMemory: (v, rv) => toStr(v).toLowerCase().startsWith(toStr(rv).toLowerCase())
|
|
6819
6607
|
},
|
|
6820
6608
|
ends_with: {
|
|
6821
|
-
appliesTo: ["text"
|
|
6609
|
+
appliesTo: ["text"],
|
|
6822
6610
|
evaluateInMemory: (v, rv) => toStr(v).toLowerCase().endsWith(toStr(rv).toLowerCase())
|
|
6823
6611
|
},
|
|
6824
6612
|
is_empty: {
|
|
@@ -6859,100 +6647,22 @@ var OPERATOR_SPECS = {
|
|
|
6859
6647
|
],
|
|
6860
6648
|
evaluateInMemory: (v) => !isEmpty(v)
|
|
6861
6649
|
},
|
|
6862
|
-
// ---- numeric ----
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
appliesTo: ["number", "currency", "formula"],
|
|
6869
|
-
evaluateInMemory: (v, rv) => toNum(v) !== toNum(rv)
|
|
6870
|
-
},
|
|
6871
|
-
lt: {
|
|
6872
|
-
appliesTo: ["number", "currency", "formula"],
|
|
6873
|
-
evaluateInMemory: (v, rv) => {
|
|
6874
|
-
const a = toNum(v);
|
|
6875
|
-
const b = toNum(rv);
|
|
6876
|
-
return a !== null && b !== null && a < b;
|
|
6877
|
-
}
|
|
6878
|
-
},
|
|
6879
|
-
gt: {
|
|
6880
|
-
appliesTo: ["number", "currency", "formula"],
|
|
6881
|
-
evaluateInMemory: (v, rv) => {
|
|
6882
|
-
const a = toNum(v);
|
|
6883
|
-
const b = toNum(rv);
|
|
6884
|
-
return a !== null && b !== null && a > b;
|
|
6885
|
-
}
|
|
6886
|
-
},
|
|
6887
|
-
lte: {
|
|
6888
|
-
appliesTo: ["number", "currency", "formula"],
|
|
6889
|
-
evaluateInMemory: (v, rv) => {
|
|
6890
|
-
const a = toNum(v);
|
|
6891
|
-
const b = toNum(rv);
|
|
6892
|
-
return a !== null && b !== null && a <= b;
|
|
6893
|
-
}
|
|
6894
|
-
},
|
|
6895
|
-
gte: {
|
|
6896
|
-
appliesTo: ["number", "currency", "formula"],
|
|
6897
|
-
evaluateInMemory: (v, rv) => {
|
|
6898
|
-
const a = toNum(v);
|
|
6899
|
-
const b = toNum(rv);
|
|
6900
|
-
return a !== null && b !== null && a >= b;
|
|
6901
|
-
}
|
|
6902
|
-
},
|
|
6903
|
-
// ---- checkbox ----
|
|
6904
|
-
is_checked: {
|
|
6905
|
-
appliesTo: ["checkbox"],
|
|
6906
|
-
evaluateInMemory: (v) => v === true
|
|
6907
|
-
},
|
|
6908
|
-
is_not_checked: {
|
|
6909
|
-
appliesTo: ["checkbox"],
|
|
6910
|
-
evaluateInMemory: (v) => v !== true
|
|
6911
|
-
},
|
|
6912
|
-
// ---- date ----
|
|
6913
|
-
before: {
|
|
6914
|
-
appliesTo: ["date"],
|
|
6915
|
-
evaluateInMemory: (v, rv) => {
|
|
6916
|
-
const a = toDate2(v);
|
|
6917
|
-
const b = toDate2(rv);
|
|
6918
|
-
return a !== null && b !== null && a < b;
|
|
6919
|
-
}
|
|
6920
|
-
},
|
|
6921
|
-
after: {
|
|
6922
|
-
appliesTo: ["date"],
|
|
6923
|
-
evaluateInMemory: (v, rv) => {
|
|
6924
|
-
const a = toDate2(v);
|
|
6925
|
-
const b = toDate2(rv);
|
|
6926
|
-
return a !== null && b !== null && a > b;
|
|
6927
|
-
}
|
|
6928
|
-
},
|
|
6929
|
-
on_or_before: {
|
|
6930
|
-
appliesTo: ["date"],
|
|
6931
|
-
evaluateInMemory: (v, rv) => {
|
|
6932
|
-
const a = toDate2(v);
|
|
6933
|
-
const b = toDate2(rv);
|
|
6934
|
-
return a !== null && b !== null && a <= b;
|
|
6935
|
-
}
|
|
6936
|
-
},
|
|
6937
|
-
on_or_after: {
|
|
6938
|
-
appliesTo: ["date"],
|
|
6939
|
-
evaluateInMemory: (v, rv) => {
|
|
6940
|
-
const a = toDate2(v);
|
|
6941
|
-
const b = toDate2(rv);
|
|
6942
|
-
return a !== null && b !== null && a >= b;
|
|
6943
|
-
}
|
|
6944
|
-
},
|
|
6650
|
+
// ---- ordering (numeric on number/currency/formula, chronological on date) ----
|
|
6651
|
+
less_than: orderingSpec((a, b) => a < b),
|
|
6652
|
+
greater_than: orderingSpec((a, b) => a > b),
|
|
6653
|
+
less_or_equal: orderingSpec((a, b) => a <= b),
|
|
6654
|
+
greater_or_equal: orderingSpec((a, b) => a >= b),
|
|
6655
|
+
// ---- date-only ----
|
|
6945
6656
|
is_within: {
|
|
6946
6657
|
appliesTo: ["date"],
|
|
6947
6658
|
evaluateInMemory: (v, rv) => {
|
|
6948
6659
|
const d = toDate2(v);
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
return rel.direction === "future" ? d >= /* @__PURE__ */ new Date() && d <= boundary : d >= boundary && d <= /* @__PURE__ */ new Date();
|
|
6660
|
+
const bounds = resolveIsWithinBounds(rv);
|
|
6661
|
+
if (!(d && bounds)) return false;
|
|
6662
|
+
return d.getTime() >= bounds.startMs && d.getTime() < bounds.endMs;
|
|
6953
6663
|
}
|
|
6954
6664
|
},
|
|
6955
|
-
|
|
6665
|
+
on_day_month: {
|
|
6956
6666
|
appliesTo: ["date"],
|
|
6957
6667
|
evaluateInMemory: (v, rv) => {
|
|
6958
6668
|
const d = toDate2(v);
|
|
@@ -6961,9 +6671,9 @@ var OPERATOR_SPECS = {
|
|
|
6961
6671
|
return d.getMonth() + 1 === rule.month && d.getDate() === rule.day;
|
|
6962
6672
|
}
|
|
6963
6673
|
},
|
|
6964
|
-
// ----
|
|
6674
|
+
// ---- set membership ----
|
|
6965
6675
|
any_of: {
|
|
6966
|
-
appliesTo: ["status", "select", "relation"],
|
|
6676
|
+
appliesTo: ["status", "select", "multiselect", "user", "relation"],
|
|
6967
6677
|
evaluateInMemory: (v, rv) => {
|
|
6968
6678
|
const ruleArr = toArr(rv).map(toStr);
|
|
6969
6679
|
const valArr = toArr(v).map(toStr);
|
|
@@ -6971,7 +6681,7 @@ var OPERATOR_SPECS = {
|
|
|
6971
6681
|
}
|
|
6972
6682
|
},
|
|
6973
6683
|
none_of: {
|
|
6974
|
-
appliesTo: ["status", "select", "relation"],
|
|
6684
|
+
appliesTo: ["status", "select", "multiselect", "user", "relation"],
|
|
6975
6685
|
evaluateInMemory: (v, rv) => {
|
|
6976
6686
|
const ruleArr = toArr(rv).map(toStr);
|
|
6977
6687
|
const valArr = toArr(v).map(toStr);
|
|
@@ -6980,37 +6690,34 @@ var OPERATOR_SPECS = {
|
|
|
6980
6690
|
}
|
|
6981
6691
|
};
|
|
6982
6692
|
|
|
6983
|
-
// src/filters/
|
|
6984
|
-
function
|
|
6985
|
-
if (
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6693
|
+
// src/filters/extract-filter-value.ts
|
|
6694
|
+
function extractCurrencyFilterValue(value) {
|
|
6695
|
+
if (typeof value === "number") return value;
|
|
6696
|
+
if (value !== null && typeof value === "object" && "value" in value) {
|
|
6697
|
+
const inner = value.value;
|
|
6698
|
+
return typeof inner === "number" ? inner : null;
|
|
6699
|
+
}
|
|
6700
|
+
return null;
|
|
6989
6701
|
}
|
|
6990
|
-
function
|
|
6991
|
-
|
|
6992
|
-
if (
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
return spec.evaluateInMemory(values[rule.attribute], rule.value, attr);
|
|
6702
|
+
function extractFilterValue(value) {
|
|
6703
|
+
if (value === null || value === void 0) return null;
|
|
6704
|
+
if (typeof value === "object" && "value" in value) {
|
|
6705
|
+
return value.value ?? null;
|
|
6706
|
+
}
|
|
6707
|
+
return value;
|
|
6997
6708
|
}
|
|
6998
6709
|
|
|
6999
6710
|
// src/filters/polarity.ts
|
|
7000
6711
|
var NEGATIVE_OPERATORS = /* @__PURE__ */ new Set([
|
|
7001
6712
|
"is_not",
|
|
7002
6713
|
"not_contains",
|
|
7003
|
-
"neq",
|
|
7004
6714
|
"none_of",
|
|
7005
|
-
"is_not_checked",
|
|
7006
6715
|
"is_empty"
|
|
7007
6716
|
]);
|
|
7008
6717
|
var NEGATIVE_TO_POSITIVE = {
|
|
7009
6718
|
is_not: "is",
|
|
7010
6719
|
not_contains: "contains",
|
|
7011
|
-
neq: "eq",
|
|
7012
6720
|
none_of: "any_of",
|
|
7013
|
-
is_not_checked: "is_checked",
|
|
7014
6721
|
is_empty: "is_not_empty"
|
|
7015
6722
|
};
|
|
7016
6723
|
function getOperatorPolarity(op) {
|
|
@@ -7021,251 +6728,136 @@ function normalizeForEdgeRpc(op) {
|
|
|
7021
6728
|
}
|
|
7022
6729
|
var SINGLE_TO_MULTI = {
|
|
7023
6730
|
is: "any_of",
|
|
7024
|
-
|
|
7025
|
-
contains: "any_of",
|
|
7026
|
-
is_not: "none_of",
|
|
7027
|
-
neq: "none_of",
|
|
7028
|
-
not_contains: "none_of"
|
|
6731
|
+
is_not: "none_of"
|
|
7029
6732
|
};
|
|
7030
6733
|
function toMultiValueOperator(op) {
|
|
7031
6734
|
return SINGLE_TO_MULTI[op] ?? op;
|
|
7032
6735
|
}
|
|
7033
6736
|
|
|
7034
|
-
// src/filters/
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
function
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
6737
|
+
// src/filters/evaluate.ts
|
|
6738
|
+
var systemAttribute = (name, type) => ({ id: `system:${name}`, name, label: name, type, system: true });
|
|
6739
|
+
var RECORD_SYSTEM_ATTRIBUTES = [
|
|
6740
|
+
...Object.entries(SYSTEM_FILTER_ATTRIBUTE_TYPES).map(
|
|
6741
|
+
([name, type]) => systemAttribute(name, type)
|
|
6742
|
+
)
|
|
6743
|
+
];
|
|
6744
|
+
function evaluateRecordFilterState(state, record, attributes) {
|
|
6745
|
+
const physical = record;
|
|
6746
|
+
return evaluateFilterState(
|
|
6747
|
+
state,
|
|
6748
|
+
{
|
|
6749
|
+
...record.values,
|
|
6750
|
+
id: record.id,
|
|
6751
|
+
objectId: record.objectId,
|
|
6752
|
+
objectName: physical.objectName,
|
|
6753
|
+
tenantId: physical.tenantId,
|
|
6754
|
+
label: record.label,
|
|
6755
|
+
createdAt: record.createdAt,
|
|
6756
|
+
updatedAt: record.updatedAt,
|
|
6757
|
+
createdBy: record.createdBy,
|
|
6758
|
+
lastUpdatedBy: record.lastUpdatedBy,
|
|
6759
|
+
deletedAt: record.deletedAt,
|
|
6760
|
+
deletedBy: record.deletedBy,
|
|
6761
|
+
visibility: record.visibility,
|
|
6762
|
+
ownedBy: record.ownedBy
|
|
6763
|
+
},
|
|
6764
|
+
[...attributes, ...RECORD_SYSTEM_ATTRIBUTES]
|
|
6765
|
+
);
|
|
7046
6766
|
}
|
|
7047
|
-
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
equal: "is",
|
|
7053
|
-
"==": "is",
|
|
7054
|
-
"=": "is",
|
|
7055
|
-
notEqual: "is_not",
|
|
7056
|
-
isNot: "is_not",
|
|
7057
|
-
"!=": "is_not",
|
|
7058
|
-
"<>": "is_not",
|
|
7059
|
-
// set
|
|
7060
|
-
in: "any_of",
|
|
7061
|
-
isAnyOf: "any_of",
|
|
7062
|
-
oneOf: "any_of",
|
|
7063
|
-
notIn: "none_of",
|
|
7064
|
-
not_in: "none_of",
|
|
7065
|
-
isNoneOf: "none_of",
|
|
7066
|
-
notOneOf: "none_of",
|
|
7067
|
-
// text
|
|
7068
|
-
startsWith: "starts_with",
|
|
7069
|
-
beginsWith: "starts_with",
|
|
7070
|
-
endsWith: "ends_with",
|
|
7071
|
-
doesNotContain: "not_contains",
|
|
7072
|
-
notContain: "not_contains",
|
|
7073
|
-
// nullity
|
|
7074
|
-
isEmpty: "is_empty",
|
|
7075
|
-
isNotEmpty: "is_not_empty",
|
|
7076
|
-
// checkbox
|
|
7077
|
-
isChecked: "is_checked",
|
|
7078
|
-
isUnchecked: "is_not_checked"
|
|
7079
|
-
};
|
|
7080
|
-
var CROSS_TYPE_CONVERSIONS = {
|
|
7081
|
-
date: {
|
|
7082
|
-
gte: "on_or_after",
|
|
7083
|
-
lte: "on_or_before",
|
|
7084
|
-
gt: "after",
|
|
7085
|
-
lt: "before",
|
|
7086
|
-
eq: "is",
|
|
7087
|
-
neq: "is_not"
|
|
7088
|
-
},
|
|
7089
|
-
number: { is: "eq", is_not: "neq" },
|
|
7090
|
-
currency: { is: "eq", is_not: "neq" },
|
|
7091
|
-
text: { eq: "is", neq: "is_not" },
|
|
7092
|
-
phone: { eq: "is", neq: "is_not" },
|
|
7093
|
-
select: { eq: "is", neq: "is_not" },
|
|
7094
|
-
status: { eq: "is", neq: "is_not" },
|
|
7095
|
-
multiselect: { eq: "contains", neq: "not_contains" },
|
|
7096
|
-
relation: { eq: "is", neq: "is_not" },
|
|
7097
|
-
user: { eq: "is", neq: "is_not" },
|
|
7098
|
-
document: { eq: "is", neq: "is_not" },
|
|
7099
|
-
file: { eq: "is", neq: "is_not" },
|
|
7100
|
-
checkbox: { eq: "is_checked", neq: "is_not_checked", is: "is_checked", is_not: "is_not_checked" }
|
|
7101
|
-
};
|
|
7102
|
-
function normalizeOperator(rawOp, effectiveType) {
|
|
7103
|
-
const synonymed = SYNONYM_ALIASES[rawOp] ?? rawOp;
|
|
7104
|
-
const typeMap = CROSS_TYPE_CONVERSIONS[effectiveType];
|
|
7105
|
-
return typeMap?.[synonymed] ?? synonymed;
|
|
6767
|
+
function evaluateFilterState(state, values, attributes) {
|
|
6768
|
+
if (state.rules.length === 0) return true;
|
|
6769
|
+
const attrByName = new Map(attributes.map((a) => [a.name, a]));
|
|
6770
|
+
const reducer = state.combinator === "or" ? "some" : "every";
|
|
6771
|
+
return state.rules[reducer]((rule) => evaluateRule(rule, values, attrByName));
|
|
7106
6772
|
}
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
"is",
|
|
7114
|
-
"is_not",
|
|
7115
|
-
"any_of",
|
|
7116
|
-
"none_of",
|
|
7117
|
-
"is_empty",
|
|
7118
|
-
"is_not_empty"
|
|
7119
|
-
];
|
|
7120
|
-
var SYSTEM_FILTER_OPERATORS = {
|
|
7121
|
-
// Identifier columns (uuid)
|
|
7122
|
-
id: ID_LIKE_OPERATORS,
|
|
7123
|
-
objectId: ID_LIKE_OPERATORS,
|
|
7124
|
-
tenantId: ID_LIKE_OPERATORS,
|
|
7125
|
-
// Free-form text columns share their counterpart's operator set
|
|
7126
|
-
label: OPERATORS_BY_TYPE.text,
|
|
7127
|
-
// Date columns
|
|
7128
|
-
createdAt: OPERATORS_BY_TYPE.date,
|
|
7129
|
-
updatedAt: OPERATORS_BY_TYPE.date,
|
|
7130
|
-
deletedAt: OPERATORS_BY_TYPE.date,
|
|
7131
|
-
// User columns (uuid → actor identity)
|
|
7132
|
-
createdBy: OPERATORS_BY_TYPE.user,
|
|
7133
|
-
lastUpdatedBy: OPERATORS_BY_TYPE.user
|
|
7134
|
-
};
|
|
7135
|
-
var SYSTEM_ATTRIBUTE_TYPES = {
|
|
7136
|
-
id: "id",
|
|
7137
|
-
objectId: "id",
|
|
7138
|
-
tenantId: "id",
|
|
7139
|
-
label: "text",
|
|
7140
|
-
createdAt: "date",
|
|
7141
|
-
updatedAt: "date",
|
|
7142
|
-
deletedAt: "date",
|
|
7143
|
-
createdBy: "user",
|
|
7144
|
-
lastUpdatedBy: "user"
|
|
7145
|
-
};
|
|
7146
|
-
function assertOperatorForType(operator, type, context) {
|
|
7147
|
-
const normalized = normalizeOperator(operator, type);
|
|
7148
|
-
const ops = OPERATORS_BY_TYPE[type];
|
|
7149
|
-
if (!ops?.includes(normalized)) {
|
|
7150
|
-
const validList = ops?.length ? ops.join(", ") : "(no operators registered for this type)";
|
|
7151
|
-
const summary = `Operator "${operator}" is not valid for ${context} type "${type}". Valid operators: ${validList}.`;
|
|
7152
|
-
throw new ValidationError(summary, [
|
|
7153
|
-
{
|
|
7154
|
-
path: ["operator"],
|
|
7155
|
-
message: summary
|
|
7156
|
-
}
|
|
7157
|
-
]);
|
|
7158
|
-
}
|
|
7159
|
-
return normalized;
|
|
7160
|
-
}
|
|
7161
|
-
var RELATIVE_DATE_UNITS = /* @__PURE__ */ new Set(["days", "weeks", "months", "years"]);
|
|
7162
|
-
var RELATIVE_DATE_DIRECTIONS = /* @__PURE__ */ new Set(["past", "future"]);
|
|
7163
|
-
function assertRelativeDateValue(rule) {
|
|
7164
|
-
if (rule.operator !== "is_within") return;
|
|
7165
|
-
const v = rule.value;
|
|
7166
|
-
const valid = typeof v === "object" && v !== null && typeof v.amount === "number" && Number.isFinite(v.amount) && v.amount > 0 && typeof v.unit === "string" && RELATIVE_DATE_UNITS.has(v.unit) && typeof v.direction === "string" && RELATIVE_DATE_DIRECTIONS.has(v.direction);
|
|
7167
|
-
if (!valid) {
|
|
7168
|
-
const m = `Operator "is_within" requires a relative-date value { amount: positive number, unit: days|weeks|months|years, direction: past|future }`;
|
|
7169
|
-
throw new ValidationError(m, [{ path: ["value"], message: m }]);
|
|
7170
|
-
}
|
|
7171
|
-
}
|
|
7172
|
-
function assertDynamicValueForAttribute(rule, attrType) {
|
|
7173
|
-
if (!isDynamicValue(rule.value)) return;
|
|
7174
|
-
const v = rule.value;
|
|
7175
|
-
if (v.dynamic === "actor" && attrType !== "user") {
|
|
7176
|
-
const m = `actor token (@me) is only valid on user attributes, not "${attrType}"`;
|
|
7177
|
-
throw new ValidationError(m, [{ path: ["value"], message: m }]);
|
|
7178
|
-
}
|
|
7179
|
-
if (v.dynamic === "date" && attrType !== "date") {
|
|
7180
|
-
const m = `date token (@today/@now) is only valid on date attributes, not "${attrType}"`;
|
|
7181
|
-
throw new ValidationError(m, [{ path: ["value"], message: m }]);
|
|
7182
|
-
}
|
|
7183
|
-
}
|
|
7184
|
-
function validateQualifiedRule(rule, context) {
|
|
7185
|
-
const rootAttr = context.attributes.find((a) => a.name === rule.attribute);
|
|
7186
|
-
const systemOps = SYSTEM_FILTER_OPERATORS[rule.attribute];
|
|
7187
|
-
if (!(rootAttr || systemOps)) {
|
|
7188
|
-
throw new ValidationError(`Unknown attribute: ${rule.attribute}`, [
|
|
7189
|
-
{ path: ["attribute"], message: `Unknown attribute: ${rule.attribute}` }
|
|
7190
|
-
]);
|
|
7191
|
-
}
|
|
7192
|
-
if (rule.quantifier !== void 0 && !rule.property) {
|
|
7193
|
-
const m = `quantifier is only valid on qualified edge rules (set "property")`;
|
|
7194
|
-
throw new ValidationError(m, [{ path: ["quantifier"], message: m }]);
|
|
7195
|
-
}
|
|
7196
|
-
if (!rootAttr) {
|
|
7197
|
-
if (rule.property) {
|
|
7198
|
-
throw new ValidationError(`Cannot qualify system attribute "${rule.attribute}"`, [
|
|
7199
|
-
{ path: ["property"], message: `"${rule.attribute}" is a system column, not a reference` }
|
|
7200
|
-
]);
|
|
7201
|
-
}
|
|
7202
|
-
const effectiveType = SYSTEM_ATTRIBUTE_TYPES[rule.attribute] ?? "id";
|
|
7203
|
-
const normalizedOperator = normalizeOperator(
|
|
7204
|
-
rule.operator,
|
|
7205
|
-
effectiveType
|
|
7206
|
-
);
|
|
7207
|
-
if (!systemOps.includes(normalizedOperator)) {
|
|
7208
|
-
const summary = `Operator "${rule.operator}" is not valid for system attribute "${rule.attribute}". Valid operators: ${systemOps.join(", ")}.`;
|
|
7209
|
-
throw new ValidationError(summary, [{ path: ["operator"], message: summary }]);
|
|
7210
|
-
}
|
|
7211
|
-
rule.operator = normalizedOperator;
|
|
7212
|
-
assertRelativeDateValue(rule);
|
|
7213
|
-
return;
|
|
7214
|
-
}
|
|
7215
|
-
if (!rule.property) {
|
|
7216
|
-
assertDynamicValueForAttribute(rule, rootAttr.type);
|
|
7217
|
-
const ops = getAttributeFilterOperators(rootAttr);
|
|
7218
|
-
const normalizedOperator = normalizeOperator(
|
|
7219
|
-
rule.operator,
|
|
7220
|
-
rootAttr.type
|
|
7221
|
-
);
|
|
7222
|
-
if (!ops.includes(normalizedOperator)) {
|
|
7223
|
-
const validList = ops.length ? ops.join(", ") : "(not filterable)";
|
|
7224
|
-
const summary = `Operator "${rule.operator}" is not valid for attribute "${rootAttr.name}". Valid operators: ${validList}.`;
|
|
7225
|
-
throw new ValidationError(summary, [{ path: ["operator"], message: summary }]);
|
|
7226
|
-
}
|
|
7227
|
-
rule.operator = normalizedOperator;
|
|
7228
|
-
assertRelativeDateValue(rule);
|
|
7229
|
-
return;
|
|
7230
|
-
}
|
|
7231
|
-
if (!REFERENCE_TYPES.has(rootAttr.type)) {
|
|
7232
|
-
throw new ValidationError(`Cannot qualify ${rootAttr.type} attribute "${rule.attribute}"`, [
|
|
7233
|
-
{ path: ["property"], message: `Attribute "${rule.attribute}" is not a reference type` }
|
|
7234
|
-
]);
|
|
7235
|
-
}
|
|
7236
|
-
const propSchema = rootAttr.properties;
|
|
7237
|
-
if (!propSchema) {
|
|
7238
|
-
throw new ValidationError(`Attribute "${rule.attribute}" has no qualifyWith schema`, [
|
|
7239
|
-
{ path: ["property"], message: `"${rule.attribute}" has no qualifyWith` }
|
|
7240
|
-
]);
|
|
7241
|
-
}
|
|
7242
|
-
const propDef = propSchema.definitions.find((p) => p.name === rule.property);
|
|
7243
|
-
if (!propDef) {
|
|
7244
|
-
throw new ValidationError(
|
|
7245
|
-
`Property "${rule.property}" not defined on "${rule.attribute}".qualifyWith()`,
|
|
7246
|
-
[{ path: ["property"], message: `Unknown property: ${rule.property}` }]
|
|
6773
|
+
function evaluateRule(rule, values, attrByName) {
|
|
6774
|
+
const attr = attrByName.get(rule.attribute);
|
|
6775
|
+
if (!attr) return false;
|
|
6776
|
+
if (rule.property) {
|
|
6777
|
+
const property = resolvePropertyDefinitions(attr).find(
|
|
6778
|
+
(definition) => definition.name === rule.property
|
|
7247
6779
|
);
|
|
6780
|
+
if (!property) return false;
|
|
6781
|
+
const positiveOperator = normalizeForEdgeRpc(rule.operator);
|
|
6782
|
+
const propertySpec = OPERATOR_SPECS[positiveOperator];
|
|
6783
|
+
if (!propertySpec?.appliesTo.includes(property.type)) return false;
|
|
6784
|
+
const rootValue = values[rule.attribute];
|
|
6785
|
+
const references = Array.isArray(rootValue) ? rootValue : rootValue == null ? [] : [rootValue];
|
|
6786
|
+
const matches = references.some((reference) => {
|
|
6787
|
+
if (typeof reference !== "object" || reference === null) return false;
|
|
6788
|
+
const props = reference.props;
|
|
6789
|
+
if (typeof props !== "object" || props === null) return false;
|
|
6790
|
+
return evaluateNormalizedComparands(
|
|
6791
|
+
propertySpec,
|
|
6792
|
+
property.type,
|
|
6793
|
+
positiveOperator,
|
|
6794
|
+
props[rule.property],
|
|
6795
|
+
rule.value,
|
|
6796
|
+
property
|
|
6797
|
+
);
|
|
6798
|
+
});
|
|
6799
|
+
return (rule.quantifier ?? getOperatorPolarity(rule.operator)) === "none" ? !matches : matches;
|
|
7248
6800
|
}
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
6801
|
+
const spec = OPERATOR_SPECS[rule.operator];
|
|
6802
|
+
if (!spec) return false;
|
|
6803
|
+
if (!spec.appliesTo.includes(attr.type)) return false;
|
|
6804
|
+
const rawValue = values[rule.attribute];
|
|
6805
|
+
const value = attr.type === "relation" || attr.type === "document" || attr.type === "user" ? normalizeReferenceIds(rawValue) : rawValue;
|
|
6806
|
+
return evaluateNormalizedComparands(spec, attr.type, rule.operator, value, rule.value, attr);
|
|
6807
|
+
}
|
|
6808
|
+
function evaluateNormalizedComparands(spec, type, operator, storedValue, ruleValue, attribute) {
|
|
6809
|
+
const [normalizedStored, normalizedRule] = normalizeOperatorComparands(
|
|
6810
|
+
type,
|
|
6811
|
+
operator,
|
|
6812
|
+
storedValue,
|
|
6813
|
+
ruleValue
|
|
6814
|
+
);
|
|
6815
|
+
if (type === "phone" && normalizedRule === "" && operator === "contains") return false;
|
|
6816
|
+
if (type === "phone" && normalizedRule === "" && operator === "not_contains") return true;
|
|
6817
|
+
return spec.evaluateInMemory(normalizedStored, normalizedRule, attribute);
|
|
6818
|
+
}
|
|
6819
|
+
function normalizeOperatorComparands(type, operator, storedValue, ruleValue) {
|
|
6820
|
+
if (type === "date" && (operator === "is" || operator === "is_not")) {
|
|
6821
|
+
return [normalizeUtcCalendarDay(storedValue), normalizeUtcCalendarDay(ruleValue)];
|
|
6822
|
+
}
|
|
6823
|
+
if (type === "phone") return normalizePhoneComparands(storedValue, ruleValue);
|
|
6824
|
+
return [normalizeComparableValue(type, storedValue), normalizeComparableValue(type, ruleValue)];
|
|
6825
|
+
}
|
|
6826
|
+
function normalizeUtcCalendarDay(value) {
|
|
6827
|
+
if (value instanceof Date)
|
|
6828
|
+
return Number.isNaN(value.getTime()) ? null : value.toISOString().slice(0, 10);
|
|
6829
|
+
if (typeof value !== "string" || value === "") return null;
|
|
6830
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;
|
|
6831
|
+
const date2 = new Date(value);
|
|
6832
|
+
return Number.isNaN(date2.getTime()) ? null : date2.toISOString().slice(0, 10);
|
|
6833
|
+
}
|
|
6834
|
+
function normalizePhoneComparands(stored, rule) {
|
|
6835
|
+
const rulePhone = typeof rule === "object" && rule !== null ? rule : { };
|
|
6836
|
+
const ruleCountry = typeof rulePhone.countryCode === "string" ? rulePhone.countryCode : void 0;
|
|
6837
|
+
const normalizeOne = (value) => {
|
|
6838
|
+
const phone2 = typeof value === "object" && value !== null ? value : { phoneNumber: value };
|
|
6839
|
+
if (typeof phone2.phoneNumber !== "string") return null;
|
|
6840
|
+
if (!ruleCountry) return normalizeCountrylessPhoneNumber(phone2.phoneNumber);
|
|
6841
|
+
const country = typeof phone2.countryCode === "string" ? phone2.countryCode : ruleCountry;
|
|
6842
|
+
return `${country}:${normalizePhoneNumber(phone2.phoneNumber, country)}`;
|
|
6843
|
+
};
|
|
6844
|
+
return [normalizeOne(stored), normalizeOne(rule)];
|
|
7261
6845
|
}
|
|
7262
|
-
function
|
|
7263
|
-
if (
|
|
7264
|
-
if (
|
|
7265
|
-
return value.
|
|
6846
|
+
function normalizeComparableValue(type, value) {
|
|
6847
|
+
if (type === "currency") return extractCurrencyFilterValue(value);
|
|
6848
|
+
if (type === "date") {
|
|
6849
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
|
6850
|
+
return value;
|
|
7266
6851
|
}
|
|
7267
6852
|
return value;
|
|
7268
6853
|
}
|
|
6854
|
+
function normalizeReferenceIds(value) {
|
|
6855
|
+
const normalizeOne = (candidate) => {
|
|
6856
|
+
if (typeof candidate !== "object" || candidate === null) return candidate;
|
|
6857
|
+
return candidate.id;
|
|
6858
|
+
};
|
|
6859
|
+
return Array.isArray(value) ? value.map(normalizeOne) : normalizeOne(value);
|
|
6860
|
+
}
|
|
7269
6861
|
|
|
7270
6862
|
// src/connectors/types.ts
|
|
7271
6863
|
var CONNECTOR_CALLBACK_PARAM = {
|
|
@@ -7317,4 +6909,418 @@ function viewSyncPayload(view) {
|
|
|
7317
6909
|
};
|
|
7318
6910
|
}
|
|
7319
6911
|
|
|
7320
|
-
|
|
6912
|
+
// src/types/schema-plan.ts
|
|
6913
|
+
function hasDestructiveEntries(plan) {
|
|
6914
|
+
const { attributeRemovals, objectRemovals, renames } = plan.destructive;
|
|
6915
|
+
return attributeRemovals.length > 0 || objectRemovals.length > 0 || renames.length > 0;
|
|
6916
|
+
}
|
|
6917
|
+
var SCHEMA_PLAN_LIMITS = {
|
|
6918
|
+
objectAdditions: 20,
|
|
6919
|
+
totalMutations: 500,
|
|
6920
|
+
serializedBytes: 512 * 1024
|
|
6921
|
+
};
|
|
6922
|
+
function errorMessage(error) {
|
|
6923
|
+
return error instanceof Error ? error.message : String(error);
|
|
6924
|
+
}
|
|
6925
|
+
var attributeTypeSchema = z.enum([
|
|
6926
|
+
"text",
|
|
6927
|
+
"richtext",
|
|
6928
|
+
"number",
|
|
6929
|
+
"checkbox",
|
|
6930
|
+
"date",
|
|
6931
|
+
"phone",
|
|
6932
|
+
"currency",
|
|
6933
|
+
"status",
|
|
6934
|
+
"location",
|
|
6935
|
+
"select",
|
|
6936
|
+
"multiselect",
|
|
6937
|
+
"user",
|
|
6938
|
+
"relation",
|
|
6939
|
+
"formula",
|
|
6940
|
+
"rollup",
|
|
6941
|
+
"document"
|
|
6942
|
+
]).describe(
|
|
6943
|
+
'The attribute\'s data type. Determines which keys `config` accepts and requires: `status`/`select`/`multiselect` need a non-empty `options` array (each `status` option carrying its own `group`); `relation` needs `targets` (non-empty) and `cardinality` ("one" or "many"); `formula` needs `expression` and `returnType`; `rollup` needs `targetAttribute` and `function`. Every other type accepts only the shared presentation keys (`placeholder`, `defaultValue`, `icon`, ...) plus a few type-specific optionals (e.g. `number.decimals`, `date.dateFormat`). An attribute\'s type can never be changed later through this tool \u2014 only through a code migration \u2014 so pick it correctly now.'
|
|
6944
|
+
);
|
|
6945
|
+
var attributeNameSchema = z.string().min(1).superRefine((name, ctx) => {
|
|
6946
|
+
try {
|
|
6947
|
+
validateAttributeName(name);
|
|
6948
|
+
} catch (error) {
|
|
6949
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: errorMessage(error) });
|
|
6950
|
+
}
|
|
6951
|
+
}).describe(
|
|
6952
|
+
'The attribute\'s machine name \u2014 the record\'s field key, and what `{{ name }}` refers to in a labelExpression. Must be a valid identifier: starts with a letter or underscore, then only letters/digits/underscores ("montantHt", "first_name", "FIRST_NAME" are valid; "first-name", "first name", "123name" are not). Max 63 characters. Cannot be a name reserved by the record shape itself (id, createdAt, updatedAt, createdBy, lastUpdatedBy, objectId, label, embeddingText, values, metadata, deletedAt, deletedBy, schemaVersion).'
|
|
6953
|
+
);
|
|
6954
|
+
var objectNameSchema = z.string().min(1).superRefine((name, ctx) => {
|
|
6955
|
+
if (RESERVED_OBJECT_NAMES.includes(name)) {
|
|
6956
|
+
ctx.addIssue({
|
|
6957
|
+
code: z.ZodIssueCode.custom,
|
|
6958
|
+
message: `"${name}" is a reserved object name (${RESERVED_OBJECT_NAMES.join(", ")}) and cannot be used for a new object.`
|
|
6959
|
+
});
|
|
6960
|
+
}
|
|
6961
|
+
try {
|
|
6962
|
+
validateObjectName(name);
|
|
6963
|
+
} catch (error) {
|
|
6964
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: errorMessage(error) });
|
|
6965
|
+
}
|
|
6966
|
+
}).describe(
|
|
6967
|
+
`The new object's machine name: kebab-case slug, lowercase letters/digits/hyphens only, starting with a letter ("products", "user-profiles", "order-items" are valid; "Products", "userProfiles", "user_profiles" are not). Max 63 characters. Cannot be a name the platform reserves for its own system objects, and cannot already exist.`
|
|
6968
|
+
);
|
|
6969
|
+
function withConfigCheck(schema) {
|
|
6970
|
+
return schema.superRefine((attribute, ctx) => {
|
|
6971
|
+
try {
|
|
6972
|
+
const parsedConfig = parseAttributeConfigForCreate(attribute.type, {
|
|
6973
|
+
...attribute.config ?? {},
|
|
6974
|
+
description: attribute.description
|
|
6975
|
+
});
|
|
6976
|
+
const unknownKeys = Object.keys(attribute.config ?? {}).filter(
|
|
6977
|
+
(key) => !Object.hasOwn(parsedConfig, key)
|
|
6978
|
+
);
|
|
6979
|
+
if (unknownKeys.length > 0) {
|
|
6980
|
+
ctx.addIssue({
|
|
6981
|
+
code: "unrecognized_keys",
|
|
6982
|
+
keys: unknownKeys,
|
|
6983
|
+
path: ["config"],
|
|
6984
|
+
message: `Unrecognized attribute config key${unknownKeys.length === 1 ? "" : "s"}: ${unknownKeys.join(", ")}`
|
|
6985
|
+
});
|
|
6986
|
+
}
|
|
6987
|
+
} catch (error) {
|
|
6988
|
+
if (error instanceof ValidationError) {
|
|
6989
|
+
for (const issue of error.errors) {
|
|
6990
|
+
ctx.addIssue({
|
|
6991
|
+
code: z.ZodIssueCode.custom,
|
|
6992
|
+
path: [
|
|
6993
|
+
"config",
|
|
6994
|
+
...issue.path.map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment)
|
|
6995
|
+
],
|
|
6996
|
+
message: `Config for type "${attribute.type}" is invalid or incomplete: ${issue.message}`
|
|
6997
|
+
});
|
|
6998
|
+
}
|
|
6999
|
+
return;
|
|
7000
|
+
}
|
|
7001
|
+
ctx.addIssue({
|
|
7002
|
+
code: z.ZodIssueCode.custom,
|
|
7003
|
+
path: ["config"],
|
|
7004
|
+
message: `Config for type "${attribute.type}" is invalid or incomplete: ${errorMessage(error)}`
|
|
7005
|
+
});
|
|
7006
|
+
}
|
|
7007
|
+
});
|
|
7008
|
+
}
|
|
7009
|
+
var plannedAttributeBaseSchema = z.object({
|
|
7010
|
+
objectName: z.string().min(1).describe(
|
|
7011
|
+
"Name of the existing (or, elsewhere in the same plan, newly created) object this attribute is added to. Ignored for an attribute declared inline in `additive.objects[].attributes` \u2014 there the parent object's own `name` is used instead."
|
|
7012
|
+
),
|
|
7013
|
+
name: attributeNameSchema,
|
|
7014
|
+
label: z.string().min(1).max(128).describe("Human-readable display label shown in the UI. 1-128 characters, cannot be empty."),
|
|
7015
|
+
type: attributeTypeSchema,
|
|
7016
|
+
config: z.record(z.string(), z.unknown()).optional().describe(
|
|
7017
|
+
'Type-specific configuration; required keys depend on `type` (see `type`\'s description). Shared optional keys on every type: `placeholder`, `defaultValue`, `icon`, `order`, `hidden`, `archived`, `deprecated`, `metadata`. Per-type keys: `text` \u2014 `multiline`, `minLength`, `maxLength`, `pattern`, `format` ("email"|"url"|"slug"); `number` \u2014 `renderAs` ("number"|"rating"), `min`, `max`, `unit`, `decimals`; `date` \u2014 `dateFormat`, `minDate`, `maxDate`, `includeTime`, `endDate`, `timeFormat` ("12h"|"24h"); `phone` \u2014 `defaultCountryCode` (3-letter); `currency` \u2014 `defaultCurrency`, `allowedCurrencies`, `allowNegative`; `status`/`select`/`multiselect` \u2014 `options` (REQUIRED, non-empty array of `{ value, label, color }`, unique `value`s; for `status` every OPTION also carries `group` as idle|in_progress|finished \u2014 `group` belongs on each option, never on `config` itself; select/multiselect accept `renderAs: "badges"`); `location` \u2014 `granularity`, `defaultCountry`, `allowedCountries`; `user` \u2014 `types` ("user"|"agent"), `multiple`; `relation` \u2014 `targets` (REQUIRED, non-empty array of `{ object }`) and `cardinality` (REQUIRED, "one"|"many"); `formula` \u2014 `expression` (REQUIRED formula string) and `returnType` (REQUIRED); `rollup` \u2014 `targetAttribute` (REQUIRED) and `function` (REQUIRED, e.g. "sum"|"avg"|"count"); `document` \u2014 `properties`, `accepts`, `maxFileSize`. Omit entirely for `richtext`/`checkbox`, which take no type-specific keys.'
|
|
7018
|
+
),
|
|
7019
|
+
required: z.boolean().optional().describe(
|
|
7020
|
+
"Whether the attribute must have a value on every record. Defaults to false (optional)."
|
|
7021
|
+
),
|
|
7022
|
+
description: z.string().optional().describe("Help text shown under the field in the UI. Not the same as the plan's `summary`.")
|
|
7023
|
+
}).strict();
|
|
7024
|
+
var plannedAttributeSchema = withConfigCheck(plannedAttributeBaseSchema);
|
|
7025
|
+
var plannedInlineAttributeSchema = withConfigCheck(
|
|
7026
|
+
plannedAttributeBaseSchema.omit({ objectName: true })
|
|
7027
|
+
);
|
|
7028
|
+
var plannedObjectSchema = z.object({
|
|
7029
|
+
name: objectNameSchema,
|
|
7030
|
+
label: z.string().min(1).describe('Human-readable singular display label (e.g. "Devis").'),
|
|
7031
|
+
pluralLabel: z.string().optional().describe(
|
|
7032
|
+
'Human-readable plural display label (e.g. "Devis"/"Invoices"). Defaults from `label` if omitted.'
|
|
7033
|
+
),
|
|
7034
|
+
description: z.string().optional().describe("Help text describing what this object represents."),
|
|
7035
|
+
icon: iconNameSchema.describe(
|
|
7036
|
+
"Required icon name for the object. Must be a catalogue value \u2014 call `search_icons` and use a name it returns verbatim. A name that is not in the catalogue is rejected without any hint as to what would have worked, so never guess one."
|
|
7037
|
+
),
|
|
7038
|
+
labelExpression: labelExpressionSchema.describe(
|
|
7039
|
+
'Template used to render a human-readable label for every record of this object \u2014 e.g. shown in relations, search results, and breadcrumbs. MUST contain at least one `{{ attributeName }}` interpolation referencing an attribute this object will actually have (either declared in this same `attributes` array, or an existing attribute if this is an update) \u2014 a plain string with no `{{ }}` at all (e.g. "Devis") is rejected. Interpolations cannot be empty (`{{ }}` is rejected) and only these pipes are allowed: UPPER, LOWER, capitalize, trim, prefix:"...", suffix:"...", wrap:"..." "...", default:"...". `{{ a || b }}` falls back to `b` when `a` is empty. Examples: "{{ firstName }} {{ lastName }}", "{{ numero | UPPER }}", "{{ name || reference }}".'
|
|
7040
|
+
),
|
|
7041
|
+
// Inline attributes get the SAME validation as attributes added to an
|
|
7042
|
+
// existing object, minus `objectName` which the parent supplies. Anything
|
|
7043
|
+
// weaker would let an agent slip a typeless attribute into a new object
|
|
7044
|
+
// while the strict path above rejects the identical mistake.
|
|
7045
|
+
attributes: z.array(plannedInlineAttributeSchema).default([]).describe(
|
|
7046
|
+
"Attributes to create on this new object, inline. Same rules as a standalone entry in `additive.attributes`, minus `objectName` (implied by this object). At least one attribute referenced by `labelExpression` should be included here."
|
|
7047
|
+
)
|
|
7048
|
+
}).strict();
|
|
7049
|
+
var destructiveSchema = z.object({
|
|
7050
|
+
attributeRemovals: z.array(
|
|
7051
|
+
z.object({
|
|
7052
|
+
objectName: z.string().min(1).describe("Object the attribute is removed from."),
|
|
7053
|
+
attributeName: z.string().min(1).describe(
|
|
7054
|
+
"Attribute to delete, together with every record's stored value for it. Must not be a system (code-declared) attribute, and must not be referenced by the object's own `labelExpression` or `embeddingExpression` \u2014 update those first."
|
|
7055
|
+
)
|
|
7056
|
+
}).strict()
|
|
7057
|
+
).default([]).describe(
|
|
7058
|
+
"Attributes to permanently delete. Irreversible: record values for the attribute are purged."
|
|
7059
|
+
),
|
|
7060
|
+
objectRemovals: z.array(
|
|
7061
|
+
z.object({
|
|
7062
|
+
objectName: z.string().min(1).describe(
|
|
7063
|
+
"Object to delete entirely, together with all its records. Must not be a system (code-declared) object, and must not still be targeted by a `relation` attribute on another object \u2014 retarget or remove that relation first."
|
|
7064
|
+
)
|
|
7065
|
+
}).strict()
|
|
7066
|
+
).default([]).describe("Objects to permanently delete, records included. Irreversible."),
|
|
7067
|
+
renames: z.array(
|
|
7068
|
+
z.object({
|
|
7069
|
+
objectName: z.string().min(1).describe("Object the renamed attribute belongs to."),
|
|
7070
|
+
from: z.string().min(1).describe(
|
|
7071
|
+
"Current attribute name. Must already exist and not be a system attribute."
|
|
7072
|
+
),
|
|
7073
|
+
to: attributeNameSchema.describe(
|
|
7074
|
+
"New attribute name \u2014 same identifier rules as any attribute `name` (see `name` on a planned attribute), and must not collide with another name already on the object, including one added elsewhere in this same plan."
|
|
7075
|
+
)
|
|
7076
|
+
}).strict()
|
|
7077
|
+
).default([]).describe(
|
|
7078
|
+
"Attribute renames. Every reference to the old name (labelExpression, views, formulas) must be updated separately \u2014 a rename does not follow references automatically."
|
|
7079
|
+
)
|
|
7080
|
+
}).strict().default({ attributeRemovals: [], objectRemovals: [], renames: [] });
|
|
7081
|
+
var planSummarySchema = z.string().min(1).describe(
|
|
7082
|
+
"One or two plain-language sentences describing the change and why, shown to the human who approves or rejects the plan \u2014 this is the only free-text context they see before deciding. If `destructive` is non-empty, say plainly what will be lost (e.g. 'deletes the \"ancienMontant\" column and its data on every devis'). Do not restate the raw plan \u2014 explain intent."
|
|
7083
|
+
);
|
|
7084
|
+
var CANONICAL_CONFIG_DESCRIPTION = "The COMPLETE config this view should end up with \u2014 not a patch. Copy the baseline returned by get_default_view and edit it, preserving every tab and setting you are not changing: anything you omit is dropped. To change the columns shown, set `tabs[].columns` (an array of attribute names) \u2014 there is no top-level `columns` on either view type. For a detail view's side panel, set `sidePanel.attributes`. Every attribute name listed must already exist on the object, or be created earlier in this same plan. ONE EXCEPTION to omit-is-dropped: a tab with `type: \"custom\"` renders a component belonging to the application, which you cannot describe or recreate. Copy every such tab through from the baseline exactly as it came, `name`, `component` and `props` untouched \u2014 dropping one, inventing one, or altering any of those three is rejected rather than applied (`name` is the tab's address in links, not its wording). Its `label` and `icon` you may change.";
|
|
7085
|
+
var BASELINE_TOKEN_DESCRIPTION = "Opaque token returned by get_default_view alongside the baseline you edited. REQUIRED when the object already exists \u2014 it proves you authored against the baseline that is still current. Must be OMITTED when this plan creates the object, which has no baseline yet.";
|
|
7086
|
+
var viewTargetObjectNameSchema = z.string().min(1).describe(
|
|
7087
|
+
"Name of the object whose default view of this type is replaced. Not a view name \u2014 a plan can only replace an object's deterministic default view, never create a view or target a non-default one."
|
|
7088
|
+
);
|
|
7089
|
+
var proposedDefaultViewTargetSchema = z.discriminatedUnion("viewType", [
|
|
7090
|
+
z.object({
|
|
7091
|
+
objectName: viewTargetObjectNameSchema,
|
|
7092
|
+
viewType: z.literal("list").describe("Targets the object's default list view (the grid)."),
|
|
7093
|
+
canonicalConfig: listViewConfigSchema.describe(CANONICAL_CONFIG_DESCRIPTION),
|
|
7094
|
+
baselineToken: z.string().min(1).optional().describe(BASELINE_TOKEN_DESCRIPTION)
|
|
7095
|
+
}).strict(),
|
|
7096
|
+
z.object({
|
|
7097
|
+
objectName: viewTargetObjectNameSchema,
|
|
7098
|
+
viewType: z.literal("detail").describe("Targets the object's default detail view (the single-record view)."),
|
|
7099
|
+
canonicalConfig: detailViewConfigSchema.describe(CANONICAL_CONFIG_DESCRIPTION),
|
|
7100
|
+
baselineToken: z.string().min(1).optional().describe(BASELINE_TOKEN_DESCRIPTION)
|
|
7101
|
+
}).strict()
|
|
7102
|
+
]);
|
|
7103
|
+
var canonicalHashSchema = z.string().regex(/^[0-9a-f]{64}$/, "Expected a lowercase SHA-256 hash");
|
|
7104
|
+
var persistedBaselineFields = {
|
|
7105
|
+
baseConfigHash: canonicalHashSchema.nullable(),
|
|
7106
|
+
targetConfigHash: canonicalHashSchema,
|
|
7107
|
+
baselineOrigin: z.enum(["persisted", "generated", "absent"])
|
|
7108
|
+
};
|
|
7109
|
+
var persistedDefaultViewTargetSchema = z.discriminatedUnion("viewType", [
|
|
7110
|
+
z.object({
|
|
7111
|
+
objectName: z.string().min(1),
|
|
7112
|
+
viewType: z.literal("list"),
|
|
7113
|
+
canonicalConfig: listViewConfigSchema,
|
|
7114
|
+
...persistedBaselineFields
|
|
7115
|
+
}).strict(),
|
|
7116
|
+
z.object({
|
|
7117
|
+
objectName: z.string().min(1),
|
|
7118
|
+
viewType: z.literal("detail"),
|
|
7119
|
+
canonicalConfig: detailViewConfigSchema,
|
|
7120
|
+
...persistedBaselineFields
|
|
7121
|
+
}).strict()
|
|
7122
|
+
]).superRefine((target, ctx) => {
|
|
7123
|
+
const requiresHash = target.baselineOrigin !== "absent";
|
|
7124
|
+
if (requiresHash === (target.baseConfigHash !== null)) return;
|
|
7125
|
+
ctx.addIssue({
|
|
7126
|
+
code: "custom",
|
|
7127
|
+
path: ["baseConfigHash"],
|
|
7128
|
+
message: requiresHash ? `A ${target.baselineOrigin} baseline requires baseConfigHash` : "An absent baseline requires baseConfigHash to be null"
|
|
7129
|
+
});
|
|
7130
|
+
});
|
|
7131
|
+
function buildAdditiveSchema(viewTargetSchema) {
|
|
7132
|
+
return z.object({
|
|
7133
|
+
objects: z.array(plannedObjectSchema).default([]).describe("New objects to create, with their attributes inline."),
|
|
7134
|
+
attributes: z.array(plannedAttributeSchema).default([]).describe("Attributes to add to existing or same-plan objects."),
|
|
7135
|
+
viewUpdates: z.array(viewTargetSchema).default([]).describe("Complete target configs for deterministic default views; never view names.")
|
|
7136
|
+
}).strict().default({ objects: [], attributes: [], viewUpdates: [] });
|
|
7137
|
+
}
|
|
7138
|
+
function findJsonSafetyIssue(value, path = [], activeObjects = /* @__PURE__ */ new WeakSet()) {
|
|
7139
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return null;
|
|
7140
|
+
if (typeof value === "number") {
|
|
7141
|
+
if (!Number.isFinite(value)) {
|
|
7142
|
+
return { path, message: "Plan input contains a non-finite number" };
|
|
7143
|
+
}
|
|
7144
|
+
return null;
|
|
7145
|
+
}
|
|
7146
|
+
if (typeof value !== "object") {
|
|
7147
|
+
return { path, message: "Plan input must contain only JSON-safe values" };
|
|
7148
|
+
}
|
|
7149
|
+
if (activeObjects.has(value)) {
|
|
7150
|
+
return { path, message: "Plan input cannot contain circular references" };
|
|
7151
|
+
}
|
|
7152
|
+
if (Array.isArray(value)) {
|
|
7153
|
+
activeObjects.add(value);
|
|
7154
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
7155
|
+
if (key === "length") continue;
|
|
7156
|
+
if (typeof key === "symbol" || !/^(0|[1-9]\d*)$/.test(key)) {
|
|
7157
|
+
activeObjects.delete(value);
|
|
7158
|
+
return {
|
|
7159
|
+
path: [...path, key],
|
|
7160
|
+
message: "Plan input arrays cannot contain non-index JSON properties"
|
|
7161
|
+
};
|
|
7162
|
+
}
|
|
7163
|
+
}
|
|
7164
|
+
for (let index = 0; index < value.length; index++) {
|
|
7165
|
+
if (!Object.hasOwn(value, index)) {
|
|
7166
|
+
activeObjects.delete(value);
|
|
7167
|
+
return {
|
|
7168
|
+
path: [...path, index],
|
|
7169
|
+
message: "Plan input cannot contain sparse arrays"
|
|
7170
|
+
};
|
|
7171
|
+
}
|
|
7172
|
+
const issue = findJsonSafetyIssue(value[index], [...path, index], activeObjects);
|
|
7173
|
+
if (issue) {
|
|
7174
|
+
activeObjects.delete(value);
|
|
7175
|
+
return issue;
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
activeObjects.delete(value);
|
|
7179
|
+
return null;
|
|
7180
|
+
}
|
|
7181
|
+
const prototype = Object.getPrototypeOf(value);
|
|
7182
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
7183
|
+
return { path, message: "Plan input must contain only plain JSON objects" };
|
|
7184
|
+
}
|
|
7185
|
+
activeObjects.add(value);
|
|
7186
|
+
const record = value;
|
|
7187
|
+
const keys = Reflect.ownKeys(record);
|
|
7188
|
+
for (const key of keys) {
|
|
7189
|
+
const descriptor = Object.getOwnPropertyDescriptor(record, key);
|
|
7190
|
+
if (typeof key === "symbol" || !(descriptor?.enumerable && "value" in descriptor)) {
|
|
7191
|
+
activeObjects.delete(value);
|
|
7192
|
+
return {
|
|
7193
|
+
path: [...path, key],
|
|
7194
|
+
message: "Plan input objects must contain enumerable JSON data properties only"
|
|
7195
|
+
};
|
|
7196
|
+
}
|
|
7197
|
+
}
|
|
7198
|
+
for (const key of keys.sort()) {
|
|
7199
|
+
const issue = findJsonSafetyIssue(record[key], [...path, key], activeObjects);
|
|
7200
|
+
if (issue) {
|
|
7201
|
+
activeObjects.delete(value);
|
|
7202
|
+
return issue;
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
activeObjects.delete(value);
|
|
7206
|
+
return null;
|
|
7207
|
+
}
|
|
7208
|
+
function mutationPaths(plan) {
|
|
7209
|
+
const paths = [];
|
|
7210
|
+
plan.additive.objects.forEach((object2, objectIndex) => {
|
|
7211
|
+
paths.push(["additive", "objects", objectIndex]);
|
|
7212
|
+
object2.attributes.forEach((_attribute, attributeIndex) => {
|
|
7213
|
+
paths.push(["additive", "objects", objectIndex, "attributes", attributeIndex]);
|
|
7214
|
+
});
|
|
7215
|
+
});
|
|
7216
|
+
plan.additive.attributes.forEach((_attribute, index) => {
|
|
7217
|
+
paths.push(["additive", "attributes", index]);
|
|
7218
|
+
});
|
|
7219
|
+
plan.additive.viewUpdates.forEach((_target, index) => {
|
|
7220
|
+
paths.push(["additive", "viewUpdates", index]);
|
|
7221
|
+
});
|
|
7222
|
+
plan.destructive.attributeRemovals.forEach((_removal, index) => {
|
|
7223
|
+
paths.push(["destructive", "attributeRemovals", index]);
|
|
7224
|
+
});
|
|
7225
|
+
plan.destructive.objectRemovals.forEach((_removal, index) => {
|
|
7226
|
+
paths.push(["destructive", "objectRemovals", index]);
|
|
7227
|
+
});
|
|
7228
|
+
plan.destructive.renames.forEach((_rename, index) => {
|
|
7229
|
+
paths.push(["destructive", "renames", index]);
|
|
7230
|
+
});
|
|
7231
|
+
return paths;
|
|
7232
|
+
}
|
|
7233
|
+
function addPlanLimitIssues(plan, ctx) {
|
|
7234
|
+
if (plan.additive.objects.length > SCHEMA_PLAN_LIMITS.objectAdditions) {
|
|
7235
|
+
ctx.addIssue({
|
|
7236
|
+
code: "too_big",
|
|
7237
|
+
origin: "array",
|
|
7238
|
+
maximum: SCHEMA_PLAN_LIMITS.objectAdditions,
|
|
7239
|
+
inclusive: true,
|
|
7240
|
+
path: ["additive", "objects", SCHEMA_PLAN_LIMITS.objectAdditions],
|
|
7241
|
+
message: `A schema plan can add at most ${SCHEMA_PLAN_LIMITS.objectAdditions} objects`
|
|
7242
|
+
});
|
|
7243
|
+
}
|
|
7244
|
+
const paths = mutationPaths(plan);
|
|
7245
|
+
if (paths.length > SCHEMA_PLAN_LIMITS.totalMutations) {
|
|
7246
|
+
ctx.addIssue({
|
|
7247
|
+
code: "too_big",
|
|
7248
|
+
origin: "array",
|
|
7249
|
+
maximum: SCHEMA_PLAN_LIMITS.totalMutations,
|
|
7250
|
+
inclusive: true,
|
|
7251
|
+
path: paths[SCHEMA_PLAN_LIMITS.totalMutations],
|
|
7252
|
+
message: `A schema plan can contain at most ${SCHEMA_PLAN_LIMITS.totalMutations} mutations; received ${paths.length}`
|
|
7253
|
+
});
|
|
7254
|
+
}
|
|
7255
|
+
}
|
|
7256
|
+
function boundSerializedPlanInput(input, ctx) {
|
|
7257
|
+
const jsonSafetyIssue = findJsonSafetyIssue(input);
|
|
7258
|
+
if (jsonSafetyIssue) {
|
|
7259
|
+
ctx.addIssue({
|
|
7260
|
+
code: "custom",
|
|
7261
|
+
path: jsonSafetyIssue.path,
|
|
7262
|
+
message: jsonSafetyIssue.message
|
|
7263
|
+
});
|
|
7264
|
+
return z.NEVER;
|
|
7265
|
+
}
|
|
7266
|
+
const serializedBytes = new TextEncoder().encode(canonicalStringify(input)).byteLength;
|
|
7267
|
+
if (serializedBytes > SCHEMA_PLAN_LIMITS.serializedBytes) {
|
|
7268
|
+
ctx.addIssue({
|
|
7269
|
+
code: "too_big",
|
|
7270
|
+
origin: "string",
|
|
7271
|
+
maximum: SCHEMA_PLAN_LIMITS.serializedBytes,
|
|
7272
|
+
inclusive: true,
|
|
7273
|
+
path: [],
|
|
7274
|
+
message: `A schema plan can serialize to at most ${SCHEMA_PLAN_LIMITS.serializedBytes} UTF-8 bytes; received ${serializedBytes}`
|
|
7275
|
+
});
|
|
7276
|
+
return z.NEVER;
|
|
7277
|
+
}
|
|
7278
|
+
return input;
|
|
7279
|
+
}
|
|
7280
|
+
var proposedAdditiveSchema = buildAdditiveSchema(proposedDefaultViewTargetSchema);
|
|
7281
|
+
var persistedAdditiveSchema = buildAdditiveSchema(persistedDefaultViewTargetSchema);
|
|
7282
|
+
var structuralSchemaPlanSchema = z.object({
|
|
7283
|
+
schemaPlanVersion: z.literal(2).describe("Required proposal contract version."),
|
|
7284
|
+
summary: planSummarySchema,
|
|
7285
|
+
additive: proposedAdditiveSchema,
|
|
7286
|
+
destructive: destructiveSchema
|
|
7287
|
+
}).strict().superRefine((plan, ctx) => {
|
|
7288
|
+
const newObjectNames = new Set(plan.additive.objects.map((object2) => object2.name));
|
|
7289
|
+
plan.additive.viewUpdates.forEach((target, index) => {
|
|
7290
|
+
const path = ["additive", "viewUpdates", index, "baselineToken"];
|
|
7291
|
+
if (newObjectNames.has(target.objectName)) {
|
|
7292
|
+
if (target.baselineToken !== void 0) {
|
|
7293
|
+
ctx.addIssue({
|
|
7294
|
+
code: "custom",
|
|
7295
|
+
path,
|
|
7296
|
+
message: "A view target for an object added by this plan must not include baselineToken"
|
|
7297
|
+
});
|
|
7298
|
+
}
|
|
7299
|
+
return;
|
|
7300
|
+
}
|
|
7301
|
+
if (target.baselineToken === void 0) {
|
|
7302
|
+
ctx.addIssue({
|
|
7303
|
+
code: "custom",
|
|
7304
|
+
path,
|
|
7305
|
+
message: "A view target for an existing object requires baselineToken"
|
|
7306
|
+
});
|
|
7307
|
+
}
|
|
7308
|
+
});
|
|
7309
|
+
addPlanLimitIssues(plan, ctx);
|
|
7310
|
+
});
|
|
7311
|
+
var schemaPlanSchema = Object.assign(
|
|
7312
|
+
z.preprocess(boundSerializedPlanInput, structuralSchemaPlanSchema),
|
|
7313
|
+
{ shape: structuralSchemaPlanSchema.shape }
|
|
7314
|
+
);
|
|
7315
|
+
var structuralPersistedSchemaPlanSchema = z.object({
|
|
7316
|
+
schemaPlanVersion: z.literal(2),
|
|
7317
|
+
summary: planSummarySchema,
|
|
7318
|
+
additive: persistedAdditiveSchema,
|
|
7319
|
+
destructive: destructiveSchema
|
|
7320
|
+
}).strict().superRefine(addPlanLimitIssues);
|
|
7321
|
+
var persistedSchemaPlanSchema = z.preprocess(
|
|
7322
|
+
boundSerializedPlanInput,
|
|
7323
|
+
structuralPersistedSchemaPlanSchema
|
|
7324
|
+
);
|
|
7325
|
+
|
|
7326
|
+
export { ALLOWED_PROPERTY_TYPES, ALL_ACTIONS, ALL_SYSTEM_RESOURCES, AUDIT_ACTIONS, AUDIT_RESOURCE_TYPES, ActivityTabConfig, AgentBuilder, BEHAVIOR_PROPERTIES, BROWSER_PREVIEW_STATUSES, BYTE_UNIT_LABELS, COMPUTED_FUNCTIONS, COMPUTED_FUNCTION_METADATA, COMPUTED_FUNCTION_NAMES, CONNECTOR_CALLBACK_PARAM, ComputedFormulaCompileError, CustomTabConfig, DB_COLUMN_FIELDS, DEFAULT_AGENT_EXECUTION_CONFIG, DEFAULT_APPROVAL_POLICY, DEFAULT_ROLES, DEFAULT_ROLE_DESCRIPTIONS, DEFAULT_ROLE_LABELS, DEFAULT_ROLE_PERMISSIONS, DOCUMENT_SYSTEM_ATTRIBUTES, DetailViewBuilder, DocumentsTabConfig, EMPTY_VALUE_PLACEHOLDER, ESTIMATED_COUNT_CAP, EmailsTabConfig, FORM_FORBIDDEN_ATTRIBUTE_TYPES, FlagRegistry, FlagService, FormBuilder, FormRegistry, FormRowBuilder, FormStepBuilder, GroupBuilder, IDENTITY_PROPERTIES, LIVE_EVENT_TYPES, LIVE_STREAM_START_CURSOR, ListViewBuilder, ListViewTabConfigBuilder, MAX_PRESET_DEPTH, MAX_TODOS, MAX_TODO_DESCRIPTION_CHARS, MAX_TODO_ID_CHARS, MAX_TODO_RESULT_CHARS, MEMORY_LIST_VIEW, MEMORY_OBJECT, MEMORY_VIEW, NOTIFICATION_INBOX_STATES, NOTIFICATION_KINDS, NOTIFICATION_PRIORITIES, NOTIFICATION_SENSITIVITIES, NOTIFICATION_TYPES_V1, NOTIFICATION_TYPE_AGENT_QUESTION_REQUESTED, NOTIFICATION_TYPE_AGENT_SESSION_COMPLETED, NOTIFICATION_TYPE_AGENT_SESSION_FAILED, NOTIFICATION_TYPE_AGENT_SESSION_TIMEOUT, NOTIFICATION_TYPE_AGENT_SESSION_WAITING_HUMAN, NOTIFICATION_TYPE_AGENT_TASK_ASSIGNED, NOTIFICATION_WORK_STATES, NoopGeocodingAdapter, OPERATOR_SPECS, ObjectBuilder, PRESENTATION_PROPERTIES, QUALIFIED_SEPARATOR, RECORD_CREATOR_ROOT_ACTOR_METADATA_KEY, RELATION_TARGET_ANY, RelationGroupBuilder, RichtextTabConfig, SCHEMA_PLAN_LIMITS, SESSION_TERMINAL_STATUSES, SKILL_LIST_VIEW, SKILL_OBJECT, SKILL_VIEW, STANDARD_SCHEMA_VENDOR, SYSTEM_RESOURCES, SYSTEM_RESOURCE_LABELS, TODO_PLAN_STATUSES, TODO_STATUSES, TabBuilder, TableTabConfig, USER_STATUSES, accessLevelToActions, actionsToAccessLevel, agent, agentDisplayName, applyPipes, applyRelationProps, assertAcyclicComputedDependencies, assertLiveStreamCursor, booleanFlag, buildPropertySchema, buildQualifiedAttribute, canonicalStringify, checkbox, compareLiveStreamCursors, compileComputedFormula, compileRollupAttribute, computeByteMagnitude, createFlagRegistry, createFlagService, createStandardSchemaProps, currency, date, dateValueStart, destructiveSchema, detailView, document, evaluateComputedAst, evaluateComputedFormula, evaluateComputedFormulaWithResult, evaluateFilterState, evaluateRecordFilterState, extractAttributeNames, extractCurrencyFilterValue, extractFilterValue, extractValueRefs, flagRegistry, form, formRegistry, formatAttributeValue, formatByteSize, formatComputedResult, formatLocationValue, formula, generateDefaultDetailView, generateDefaultListView, getActiveTab, getErrorMessage, getLiveProtocolPayloadChannel, getOperatorPolarity, getRecordCreatorPrincipalId, getSlotFieldTargets, getUserDisplayName, group, hasDestructiveEntries, hasOptions, inferInverseCardinality, inferRollupReturnType, isAttributeSortable2 as isAttributeSortable, isBilateralRelation, isCheckboxEquality, isComputedFunctionName, isDateRangeValue, isDefaultRole, isDetailView, isDocumentAttribute, isEmptyObject, isFieldGroup, isFormDefinition, isFormFieldsRow, isFormFreeFieldRef, isFormHeadingRow, isFormSeparatorRow, isFormSlotFieldRef, isFormTextRow, isLabelExpression, isListView, isLiveErrorPayload, isLiveEventEnvelope, isLiveEventPayload, isLiveEventPayloadForType, isLiveEventType, isLiveGapPayload, isLiveReplayCompletePayload, isLiveStreamCursor, isNotEmpty, isPlainRecord, isRelationGroup, isStandardSchema, isTerminalSessionStatus, isUniversalRelation, jsonFlag, listView, liveChannelKey, location, matchesAccepts, multiselect, normalizeDateValue, normalizeForEdgeRpc, number, numberFlag, object, parseLiveChannelKey, parseLiveSubscribePayload, parseLiveUnsubscribePayload, parseQualifiedAttribute, persistedDefaultViewTargetSchema, persistedSchemaPlanSchema, phone, plannedAttributeSchema, plannedInlineAttributeSchema, plannedObjectSchema, proposedDefaultViewTargetSchema, registry, relation, relationGroup, renderLabelExpression, resetViewToDefault, resolvePropertyDefinitions, richtext, rollup, rollupToFormulaExpression, schemaPlanSchema, select, status, stringFlag, text, toMultiValueOperator, toUndefinedIfEmpty, user, validateAttributeName, validateLabelExpression, validateObjectName, viewRegistry, viewStateKey, viewSyncPayload };
|