@stndrds/schema 0.1.0-alpha.33 → 0.1.0-alpha.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-E2CTZTQX.mjs → chunk-EIRY4I7Q.mjs} +210 -114
- package/dist/{chunk-5WYGAQYH.js → chunk-UCUFSIOX.js} +211 -115
- package/dist/index.d.mts +50 -9
- package/dist/index.d.ts +50 -9
- package/dist/index.js +10 -6
- package/dist/index.mjs +5 -1
- package/dist/{runtime-DyTAIaum.d.mts → runtime-BWBRGKY1.d.mts} +352 -282
- package/dist/{runtime-DyTAIaum.d.ts → runtime-BWBRGKY1.d.ts} +352 -282
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +2 -2
- package/dist/runtime.mjs +1 -1
- package/package.json +2 -2
|
@@ -4559,14 +4559,6 @@ var RollupAttributeBuilder = class extends BaseAttributeBuilder {
|
|
|
4559
4559
|
this.attr.decimals = value;
|
|
4560
4560
|
return this;
|
|
4561
4561
|
}
|
|
4562
|
-
/**
|
|
4563
|
-
* Display the rollup value using the target attribute's type formatter
|
|
4564
|
-
* instead of the default rollup-specific formatting
|
|
4565
|
-
*/
|
|
4566
|
-
showAsOriginal() {
|
|
4567
|
-
this.attr.showAsOriginal = true;
|
|
4568
|
-
return this;
|
|
4569
|
-
}
|
|
4570
4562
|
/**
|
|
4571
4563
|
* Set multi-level path for traversing nested relations (Phase 4+)
|
|
4572
4564
|
* @param path - Dot notation path (e.g., "orders.items")
|
|
@@ -4575,6 +4567,24 @@ var RollupAttributeBuilder = class extends BaseAttributeBuilder {
|
|
|
4575
4567
|
this.attr.relationPath = relationPath;
|
|
4576
4568
|
return this;
|
|
4577
4569
|
}
|
|
4570
|
+
/**
|
|
4571
|
+
* Set the target attribute type for display purposes
|
|
4572
|
+
* Required when using function="original" to render values correctly
|
|
4573
|
+
* @param type - The type of the target attribute (e.g., "select", "status", "text")
|
|
4574
|
+
*/
|
|
4575
|
+
targetType(type) {
|
|
4576
|
+
this.attr.targetAttributeType = type;
|
|
4577
|
+
return this;
|
|
4578
|
+
}
|
|
4579
|
+
/**
|
|
4580
|
+
* Set the target attribute options for select-like types
|
|
4581
|
+
* Required when function="original" and target is select/status/multiselect
|
|
4582
|
+
* @param options - The options array from the target attribute
|
|
4583
|
+
*/
|
|
4584
|
+
targetOptions(options) {
|
|
4585
|
+
this.attr.targetAttributeOptions = options;
|
|
4586
|
+
return this;
|
|
4587
|
+
}
|
|
4578
4588
|
// Override to prevent making rollups required
|
|
4579
4589
|
// biome-ignore lint/suspicious/noExplicitAny: intentional override
|
|
4580
4590
|
required() {
|
|
@@ -5529,7 +5539,7 @@ var ViewBuilder = class {
|
|
|
5529
5539
|
return this;
|
|
5530
5540
|
}
|
|
5531
5541
|
/**
|
|
5532
|
-
* Mark as default view for the object
|
|
5542
|
+
* Mark as default view for the object (within its layout)
|
|
5533
5543
|
*/
|
|
5534
5544
|
default() {
|
|
5535
5545
|
this.data.default = true;
|
|
@@ -5542,6 +5552,23 @@ var ViewBuilder = class {
|
|
|
5542
5552
|
this.data.system = true;
|
|
5543
5553
|
return this;
|
|
5544
5554
|
}
|
|
5555
|
+
/**
|
|
5556
|
+
* Set the layout mode for the view
|
|
5557
|
+
* @param value - "page" for full tabs, "modal" for single form
|
|
5558
|
+
* @default "page"
|
|
5559
|
+
*/
|
|
5560
|
+
layout(value) {
|
|
5561
|
+
this.data.layout = value;
|
|
5562
|
+
return this;
|
|
5563
|
+
}
|
|
5564
|
+
/**
|
|
5565
|
+
* Shorthand for .layout("modal")
|
|
5566
|
+
* Modal views have a single form tab without tabs UI
|
|
5567
|
+
*/
|
|
5568
|
+
modal() {
|
|
5569
|
+
this.data.layout = "modal";
|
|
5570
|
+
return this;
|
|
5571
|
+
}
|
|
5545
5572
|
/**
|
|
5546
5573
|
* Set metadata
|
|
5547
5574
|
*/
|
|
@@ -5586,6 +5613,14 @@ var ViewBuilder = class {
|
|
|
5586
5613
|
}
|
|
5587
5614
|
tabNames.add(tab.name);
|
|
5588
5615
|
}
|
|
5616
|
+
if (this.data.layout === "modal") {
|
|
5617
|
+
if (this.data.tabs.length !== 1) {
|
|
5618
|
+
throw new Error("[ViewBuilder] Modal views must have exactly one tab");
|
|
5619
|
+
}
|
|
5620
|
+
if (this.data.tabs[0].type !== "form") {
|
|
5621
|
+
throw new Error("[ViewBuilder] Modal views must have a form tab");
|
|
5622
|
+
}
|
|
5623
|
+
}
|
|
5589
5624
|
this.validated = true;
|
|
5590
5625
|
return this.data;
|
|
5591
5626
|
}
|
|
@@ -5706,6 +5741,25 @@ function isSystemAttributeObject(attr) {
|
|
|
5706
5741
|
|
|
5707
5742
|
// src/validation/validators.ts
|
|
5708
5743
|
import { z as z4 } from "zod";
|
|
5744
|
+
var DEFAULT_VALIDATION_MESSAGES = {
|
|
5745
|
+
required: (attr) => `${attr.label} is required`,
|
|
5746
|
+
invalidType: (attr, expected) => `${attr.label} must be a ${expected}`,
|
|
5747
|
+
minLength: (attr, min) => `${attr.label} must be at least ${min} characters`,
|
|
5748
|
+
maxLength: (attr, max) => `${attr.label} must be at most ${max} characters`,
|
|
5749
|
+
invalidPattern: (attr) => `${attr.label} format is invalid`,
|
|
5750
|
+
minValue: (attr, min) => `${attr.label} must be at least ${min}`,
|
|
5751
|
+
maxValue: (attr, max) => `${attr.label} must be at most ${max}`,
|
|
5752
|
+
mustBeInteger: (attr) => `${attr.label} must be an integer`,
|
|
5753
|
+
invalidDate: (attr) => `${attr.label} must be a valid date`,
|
|
5754
|
+
invalidOption: (attr, options) => `${attr.label} must be one of: ${options.join(", ")}`,
|
|
5755
|
+
invalidId: (attr) => `${attr.label} must be a valid ID`,
|
|
5756
|
+
minItems: (attr, min) => `${attr.label} must have at least ${min} item${min > 1 ? "s" : ""}`,
|
|
5757
|
+
maxItems: (attr, max) => `${attr.label} must have at most ${max} item${max > 1 ? "s" : ""}`,
|
|
5758
|
+
invalidRichtext: (attr) => `${attr.label} must be valid rich text content`,
|
|
5759
|
+
invalidPhone: (attr) => `${attr.label} must be a valid phone number`,
|
|
5760
|
+
invalidCurrency: (attr) => `${attr.label} must be a valid currency value`,
|
|
5761
|
+
invalidLocation: (attr) => `${attr.label} must be a valid location`
|
|
5762
|
+
};
|
|
5709
5763
|
var baseConfigSchema = z4.object({
|
|
5710
5764
|
disabled: z4.boolean().optional(),
|
|
5711
5765
|
placeholder: z4.string().optional(),
|
|
@@ -5830,10 +5884,11 @@ var rollupConfigSchema = baseConfigSchema.extend({
|
|
|
5830
5884
|
"countEmpty",
|
|
5831
5885
|
// Percent (universal)
|
|
5832
5886
|
"percentEmpty",
|
|
5833
|
-
"percentNotEmpty"
|
|
5887
|
+
"percentNotEmpty",
|
|
5888
|
+
// Lookup (universal)
|
|
5889
|
+
"original"
|
|
5834
5890
|
]),
|
|
5835
5891
|
decimals: z4.number().int().min(0).max(10).optional(),
|
|
5836
|
-
showAsOriginal: z4.boolean().optional(),
|
|
5837
5892
|
targetAttributeType: z4.string().optional(),
|
|
5838
5893
|
targetAttributeOptions: z4.array(
|
|
5839
5894
|
z4.object({
|
|
@@ -5890,158 +5945,152 @@ function safeParseAttributeConfig(type, config) {
|
|
|
5890
5945
|
const result = schema.strip().safeParse(config);
|
|
5891
5946
|
return result.success ? result.data : void 0;
|
|
5892
5947
|
}
|
|
5893
|
-
function createTextValidator(attr) {
|
|
5948
|
+
function createTextValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5894
5949
|
let schema = z4.string();
|
|
5895
5950
|
if (attr.minLength !== void 0) {
|
|
5896
|
-
schema = schema.min(
|
|
5897
|
-
attr.minLength,
|
|
5898
|
-
`${attr.label} must be at least ${attr.minLength} characters`
|
|
5899
|
-
);
|
|
5951
|
+
schema = schema.min(attr.minLength, messages.minLength(attr, attr.minLength));
|
|
5900
5952
|
}
|
|
5901
5953
|
if (attr.maxLength !== void 0) {
|
|
5902
|
-
schema = schema.max(
|
|
5903
|
-
attr.maxLength,
|
|
5904
|
-
`${attr.label} must be at most ${attr.maxLength} characters`
|
|
5905
|
-
);
|
|
5954
|
+
schema = schema.max(attr.maxLength, messages.maxLength(attr, attr.maxLength));
|
|
5906
5955
|
}
|
|
5907
5956
|
if (attr.pattern) {
|
|
5908
|
-
schema = schema.regex(new RegExp(attr.pattern),
|
|
5957
|
+
schema = schema.regex(new RegExp(attr.pattern), messages.invalidPattern(attr));
|
|
5909
5958
|
}
|
|
5910
5959
|
return schema;
|
|
5911
5960
|
}
|
|
5912
|
-
function createNumberValidator(attr) {
|
|
5961
|
+
function createNumberValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5913
5962
|
let schema = z4.number();
|
|
5914
5963
|
if (attr.min !== void 0) {
|
|
5915
|
-
schema = schema.min(attr.min,
|
|
5964
|
+
schema = schema.min(attr.min, messages.minValue(attr, attr.min));
|
|
5916
5965
|
}
|
|
5917
5966
|
if (attr.max !== void 0) {
|
|
5918
|
-
schema = schema.max(attr.max,
|
|
5967
|
+
schema = schema.max(attr.max, messages.maxValue(attr, attr.max));
|
|
5919
5968
|
}
|
|
5920
5969
|
if (attr.unit === "integer") {
|
|
5921
|
-
schema = schema.int(
|
|
5970
|
+
schema = schema.int(messages.mustBeInteger(attr));
|
|
5922
5971
|
}
|
|
5923
5972
|
return schema;
|
|
5924
5973
|
}
|
|
5925
|
-
function createCheckboxValidator(_attr) {
|
|
5974
|
+
function createCheckboxValidator(_attr, _messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5926
5975
|
return z4.boolean();
|
|
5927
5976
|
}
|
|
5928
|
-
function createDateValidator(attr) {
|
|
5929
|
-
return z4.coerce.date({ message:
|
|
5977
|
+
function createDateValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5978
|
+
return z4.coerce.date({ message: messages.invalidDate(attr) });
|
|
5930
5979
|
}
|
|
5931
|
-
function createPhoneValidator(
|
|
5932
|
-
return z4.object(
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5980
|
+
function createPhoneValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5981
|
+
return z4.object(
|
|
5982
|
+
{
|
|
5983
|
+
countryCode: z4.string().length(3),
|
|
5984
|
+
phoneNumber: z4.string().min(1)
|
|
5985
|
+
},
|
|
5986
|
+
{ message: messages.invalidPhone(attr) }
|
|
5987
|
+
);
|
|
5936
5988
|
}
|
|
5937
|
-
function createCurrencyValidator(
|
|
5938
|
-
return z4.object(
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5989
|
+
function createCurrencyValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5990
|
+
return z4.object(
|
|
5991
|
+
{
|
|
5992
|
+
code: z4.string().length(3),
|
|
5993
|
+
value: z4.number().min(0)
|
|
5994
|
+
},
|
|
5995
|
+
{ message: messages.invalidCurrency(attr) }
|
|
5996
|
+
);
|
|
5942
5997
|
}
|
|
5943
|
-
function createStatusValidator(attr) {
|
|
5998
|
+
function createStatusValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5944
5999
|
const validValues = attr.options.map((opt) => opt.value);
|
|
5945
6000
|
return z4.enum(validValues, {
|
|
5946
|
-
|
|
6001
|
+
message: messages.invalidOption(attr, validValues)
|
|
5947
6002
|
});
|
|
5948
6003
|
}
|
|
5949
|
-
function createSelectValidator(attr) {
|
|
6004
|
+
function createSelectValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5950
6005
|
const validValues = attr.options.map((opt) => opt.value);
|
|
5951
6006
|
return z4.enum(validValues, {
|
|
5952
|
-
|
|
6007
|
+
message: messages.invalidOption(attr, validValues)
|
|
5953
6008
|
});
|
|
5954
6009
|
}
|
|
5955
|
-
function createMultiselectValidator(attr) {
|
|
6010
|
+
function createMultiselectValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5956
6011
|
const validValues = attr.options.map((opt) => opt.value);
|
|
5957
6012
|
return z4.array(
|
|
5958
6013
|
z4.enum(validValues, {
|
|
5959
|
-
|
|
6014
|
+
message: messages.invalidOption(attr, validValues)
|
|
5960
6015
|
})
|
|
5961
6016
|
);
|
|
5962
6017
|
}
|
|
5963
|
-
function createLocationValidator(
|
|
5964
|
-
return z4.object(
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
6018
|
+
function createLocationValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6019
|
+
return z4.object(
|
|
6020
|
+
{
|
|
6021
|
+
address: z4.string().optional(),
|
|
6022
|
+
address2: z4.string().optional(),
|
|
6023
|
+
city: z4.string().optional(),
|
|
6024
|
+
state: z4.string().optional(),
|
|
6025
|
+
postalCode: z4.string().optional(),
|
|
6026
|
+
country: z4.string().length(3).optional(),
|
|
6027
|
+
latitude: z4.number().optional(),
|
|
6028
|
+
longitude: z4.number().optional()
|
|
6029
|
+
},
|
|
6030
|
+
{ message: messages.invalidLocation(attr) }
|
|
6031
|
+
);
|
|
5974
6032
|
}
|
|
5975
|
-
function createFileValidator(attr) {
|
|
6033
|
+
function createFileValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5976
6034
|
const uuidSchema = z4.uuid({
|
|
5977
|
-
message:
|
|
6035
|
+
message: messages.invalidId(attr)
|
|
5978
6036
|
});
|
|
5979
6037
|
if (attr.multiple) {
|
|
5980
6038
|
let arraySchema = z4.array(uuidSchema);
|
|
5981
6039
|
if (attr.maxFiles) {
|
|
5982
|
-
arraySchema = arraySchema.max(
|
|
5983
|
-
attr.maxFiles,
|
|
5984
|
-
`${attr.label} cannot have more than ${attr.maxFiles} file${attr.maxFiles > 1 ? "s" : ""}`
|
|
5985
|
-
);
|
|
6040
|
+
arraySchema = arraySchema.max(attr.maxFiles, messages.maxItems(attr, attr.maxFiles));
|
|
5986
6041
|
}
|
|
5987
6042
|
return arraySchema;
|
|
5988
6043
|
}
|
|
5989
6044
|
return uuidSchema;
|
|
5990
6045
|
}
|
|
5991
|
-
function createUserValidator(attr) {
|
|
6046
|
+
function createUserValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
5992
6047
|
const uuidSchema = z4.uuid({
|
|
5993
|
-
message:
|
|
6048
|
+
message: messages.invalidId(attr)
|
|
5994
6049
|
});
|
|
5995
6050
|
if (attr.multiple) {
|
|
5996
6051
|
return z4.array(uuidSchema);
|
|
5997
6052
|
}
|
|
5998
6053
|
return uuidSchema;
|
|
5999
6054
|
}
|
|
6000
|
-
function createSingleRelationValidator(attr) {
|
|
6055
|
+
function createSingleRelationValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6001
6056
|
const uuidSchema = z4.uuid({
|
|
6002
|
-
message:
|
|
6057
|
+
message: messages.invalidId(attr)
|
|
6003
6058
|
});
|
|
6004
6059
|
return z4.union([uuidSchema, z4.null()]);
|
|
6005
6060
|
}
|
|
6006
|
-
function createMultiRelationValidator(attr) {
|
|
6061
|
+
function createMultiRelationValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6007
6062
|
const uuidSchema = z4.uuid({
|
|
6008
|
-
message:
|
|
6063
|
+
message: messages.invalidId(attr)
|
|
6009
6064
|
});
|
|
6010
6065
|
let arraySchema = z4.array(uuidSchema);
|
|
6011
6066
|
if (attr.minItems !== void 0) {
|
|
6012
|
-
arraySchema = arraySchema.min(
|
|
6013
|
-
attr.minItems,
|
|
6014
|
-
`${attr.label} must have at least ${attr.minItems} item${attr.minItems > 1 ? "s" : ""}`
|
|
6015
|
-
);
|
|
6067
|
+
arraySchema = arraySchema.min(attr.minItems, messages.minItems(attr, attr.minItems));
|
|
6016
6068
|
}
|
|
6017
6069
|
if (attr.maxItems !== void 0) {
|
|
6018
|
-
arraySchema = arraySchema.max(
|
|
6019
|
-
attr.maxItems,
|
|
6020
|
-
`${attr.label} must have at most ${attr.maxItems} item${attr.maxItems > 1 ? "s" : ""}`
|
|
6021
|
-
);
|
|
6070
|
+
arraySchema = arraySchema.max(attr.maxItems, messages.maxItems(attr, attr.maxItems));
|
|
6022
6071
|
}
|
|
6023
6072
|
return arraySchema;
|
|
6024
6073
|
}
|
|
6025
|
-
function createRelationValidator(attr) {
|
|
6074
|
+
function createRelationValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6026
6075
|
if (attr.cardinality === "many") {
|
|
6027
|
-
return createMultiRelationValidator(attr);
|
|
6076
|
+
return createMultiRelationValidator(attr, messages);
|
|
6028
6077
|
}
|
|
6029
|
-
return createSingleRelationValidator(attr);
|
|
6078
|
+
return createSingleRelationValidator(attr, messages);
|
|
6030
6079
|
}
|
|
6031
|
-
function createRatingValidator(attr) {
|
|
6080
|
+
function createRatingValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6032
6081
|
let schema = z4.number().min(0);
|
|
6033
6082
|
if (attr.max !== void 0) {
|
|
6034
|
-
schema = schema.max(attr.max,
|
|
6083
|
+
schema = schema.max(attr.max, messages.maxValue(attr, attr.max));
|
|
6035
6084
|
}
|
|
6036
6085
|
return schema;
|
|
6037
6086
|
}
|
|
6038
|
-
function createFormulaValidator(_attr) {
|
|
6087
|
+
function createFormulaValidator(_attr, _messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6039
6088
|
return z4.unknown();
|
|
6040
6089
|
}
|
|
6041
|
-
function createRollupValidator(_attr) {
|
|
6090
|
+
function createRollupValidator(_attr, _messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6042
6091
|
return z4.unknown();
|
|
6043
6092
|
}
|
|
6044
|
-
function createTextAreaValidator(_attr) {
|
|
6093
|
+
function createTextAreaValidator(_attr, _messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6045
6094
|
return z4.string();
|
|
6046
6095
|
}
|
|
6047
6096
|
var blockNoteBlockSchema = z4.lazy(
|
|
@@ -6053,53 +6102,60 @@ var blockNoteBlockSchema = z4.lazy(
|
|
|
6053
6102
|
children: z4.array(z4.any())
|
|
6054
6103
|
})
|
|
6055
6104
|
);
|
|
6056
|
-
function createRichtextValidator(attr) {
|
|
6105
|
+
function createRichtextValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6057
6106
|
return z4.array(blockNoteBlockSchema, {
|
|
6058
|
-
message:
|
|
6107
|
+
message: messages.invalidRichtext(attr)
|
|
6059
6108
|
});
|
|
6060
6109
|
}
|
|
6061
|
-
function createAttributeValidator(attr) {
|
|
6110
|
+
function createAttributeValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6062
6111
|
switch (attr.type) {
|
|
6063
6112
|
case "text":
|
|
6064
|
-
return createTextValidator(attr);
|
|
6113
|
+
return createTextValidator(attr, messages);
|
|
6065
6114
|
case "textarea":
|
|
6066
|
-
return createTextAreaValidator(attr);
|
|
6115
|
+
return createTextAreaValidator(attr, messages);
|
|
6067
6116
|
case "richtext":
|
|
6068
|
-
return createRichtextValidator(attr);
|
|
6117
|
+
return createRichtextValidator(attr, messages);
|
|
6069
6118
|
case "number":
|
|
6070
|
-
return createNumberValidator(attr);
|
|
6119
|
+
return createNumberValidator(attr, messages);
|
|
6071
6120
|
case "checkbox":
|
|
6072
|
-
return createCheckboxValidator(attr);
|
|
6121
|
+
return createCheckboxValidator(attr, messages);
|
|
6073
6122
|
case "date":
|
|
6074
|
-
return createDateValidator(attr);
|
|
6123
|
+
return createDateValidator(attr, messages);
|
|
6075
6124
|
case "phone":
|
|
6076
|
-
return createPhoneValidator(attr);
|
|
6125
|
+
return createPhoneValidator(attr, messages);
|
|
6077
6126
|
case "currency":
|
|
6078
|
-
return createCurrencyValidator(attr);
|
|
6127
|
+
return createCurrencyValidator(attr, messages);
|
|
6079
6128
|
case "status":
|
|
6080
|
-
return createStatusValidator(attr);
|
|
6129
|
+
return createStatusValidator(attr, messages);
|
|
6081
6130
|
case "location":
|
|
6082
|
-
return createLocationValidator(attr);
|
|
6131
|
+
return createLocationValidator(attr, messages);
|
|
6083
6132
|
case "select":
|
|
6084
|
-
return createSelectValidator(attr);
|
|
6133
|
+
return createSelectValidator(attr, messages);
|
|
6085
6134
|
case "multiselect":
|
|
6086
|
-
return createMultiselectValidator(attr);
|
|
6135
|
+
return createMultiselectValidator(attr, messages);
|
|
6087
6136
|
case "file":
|
|
6088
|
-
return createFileValidator(attr);
|
|
6137
|
+
return createFileValidator(attr, messages);
|
|
6089
6138
|
case "user":
|
|
6090
|
-
return createUserValidator(attr);
|
|
6139
|
+
return createUserValidator(attr, messages);
|
|
6091
6140
|
case "relation":
|
|
6092
|
-
return createRelationValidator(attr);
|
|
6141
|
+
return createRelationValidator(attr, messages);
|
|
6093
6142
|
case "rating":
|
|
6094
|
-
return createRatingValidator(attr);
|
|
6143
|
+
return createRatingValidator(attr, messages);
|
|
6095
6144
|
case "formula":
|
|
6096
|
-
return createFormulaValidator(attr);
|
|
6145
|
+
return createFormulaValidator(attr, messages);
|
|
6097
6146
|
case "rollup":
|
|
6098
|
-
return createRollupValidator(attr);
|
|
6147
|
+
return createRollupValidator(attr, messages);
|
|
6099
6148
|
default:
|
|
6100
6149
|
return z4.unknown();
|
|
6101
6150
|
}
|
|
6102
6151
|
}
|
|
6152
|
+
function createFormAttributeValidator(attr, messages = DEFAULT_VALIDATION_MESSAGES) {
|
|
6153
|
+
const validator = createAttributeValidator(attr, messages);
|
|
6154
|
+
if (!attr.required) {
|
|
6155
|
+
return validator.nullish();
|
|
6156
|
+
}
|
|
6157
|
+
return validator;
|
|
6158
|
+
}
|
|
6103
6159
|
function createObjectValidator(objectDef) {
|
|
6104
6160
|
const shape = {};
|
|
6105
6161
|
for (const attr of objectDef.attributes) {
|
|
@@ -7892,6 +7948,9 @@ var RollupService = class {
|
|
|
7892
7948
|
const empty = values.filter((v) => v == null || v === "").length;
|
|
7893
7949
|
return empty / values.length;
|
|
7894
7950
|
}
|
|
7951
|
+
// Lookup - returns all values as array
|
|
7952
|
+
case "original":
|
|
7953
|
+
return values;
|
|
7895
7954
|
}
|
|
7896
7955
|
}
|
|
7897
7956
|
/**
|
|
@@ -7911,6 +7970,8 @@ var RollupService = class {
|
|
|
7911
7970
|
case "earliest":
|
|
7912
7971
|
case "latest":
|
|
7913
7972
|
return null;
|
|
7973
|
+
case "original":
|
|
7974
|
+
return [];
|
|
7914
7975
|
}
|
|
7915
7976
|
}
|
|
7916
7977
|
/**
|
|
@@ -8268,7 +8329,6 @@ var RecordService = class extends TenantAwareService {
|
|
|
8268
8329
|
* Resolve relation IDs to their display labels
|
|
8269
8330
|
* @internal
|
|
8270
8331
|
*/
|
|
8271
|
-
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: complexity is ok here
|
|
8272
8332
|
async resolveRelationLabels(relationAttrs, values) {
|
|
8273
8333
|
const resolvedMap = /* @__PURE__ */ new Map();
|
|
8274
8334
|
const idsWithAttrId = [];
|
|
@@ -9511,20 +9571,22 @@ var ViewService = class extends TenantAwareService {
|
|
|
9511
9571
|
* Get the default view for an object
|
|
9512
9572
|
*
|
|
9513
9573
|
* Priority:
|
|
9514
|
-
* 1. Custom view marked as default
|
|
9515
|
-
* 2. Native view marked as default
|
|
9516
|
-
* 3. First available view
|
|
9574
|
+
* 1. Custom view marked as default (for the specified layout)
|
|
9575
|
+
* 2. Native view marked as default (for the specified layout)
|
|
9576
|
+
* 3. First available view (for the specified layout)
|
|
9517
9577
|
*
|
|
9518
9578
|
* @param objectName - Object name
|
|
9579
|
+
* @param layout - Optional layout filter ("page" or "modal")
|
|
9519
9580
|
* @returns Default view or null
|
|
9520
9581
|
*/
|
|
9521
|
-
async getDefaultView(objectName) {
|
|
9582
|
+
async getDefaultView(objectName, layout) {
|
|
9522
9583
|
const views = await this.getViewsForObject(objectName);
|
|
9523
|
-
const
|
|
9584
|
+
const filtered = layout ? views.filter((v) => (v.layout ?? "page") === layout) : views;
|
|
9585
|
+
const customDefault = filtered.find((v) => v.default && !v.system);
|
|
9524
9586
|
if (customDefault) return customDefault;
|
|
9525
|
-
const nativeDefault =
|
|
9587
|
+
const nativeDefault = filtered.find((v) => v.default && v.system);
|
|
9526
9588
|
if (nativeDefault) return nativeDefault;
|
|
9527
|
-
return
|
|
9589
|
+
return filtered[0] ?? null;
|
|
9528
9590
|
}
|
|
9529
9591
|
/**
|
|
9530
9592
|
* Create a custom view.
|
|
@@ -9535,6 +9597,7 @@ var ViewService = class extends TenantAwareService {
|
|
|
9535
9597
|
*/
|
|
9536
9598
|
async createView(input) {
|
|
9537
9599
|
this.validateViewName(input.name);
|
|
9600
|
+
this.validateModalLayout(input.tabs, input.layout);
|
|
9538
9601
|
const existing = await this.adapter.views.findByName(input.objectName, input.name);
|
|
9539
9602
|
if (existing) {
|
|
9540
9603
|
throw new SchemaError(
|
|
@@ -9556,6 +9619,7 @@ var ViewService = class extends TenantAwareService {
|
|
|
9556
9619
|
label: input.label,
|
|
9557
9620
|
description: input.description,
|
|
9558
9621
|
icon: input.icon,
|
|
9622
|
+
layout: input.layout,
|
|
9559
9623
|
tabs: input.tabs ?? [],
|
|
9560
9624
|
default: input.default ?? false,
|
|
9561
9625
|
system: false,
|
|
@@ -9579,10 +9643,14 @@ var ViewService = class extends TenantAwareService {
|
|
|
9579
9643
|
if (dbView.system) {
|
|
9580
9644
|
throw new ProtectedResourceError("view", dbView.name, "modify");
|
|
9581
9645
|
}
|
|
9646
|
+
const effectiveLayout = input.layout ?? dbView.layout;
|
|
9647
|
+
const effectiveTabs = input.tabs ?? dbView.tabs;
|
|
9648
|
+
this.validateModalLayout(effectiveTabs, effectiveLayout);
|
|
9582
9649
|
const updated = await this.adapter.views.update(viewId, {
|
|
9583
9650
|
label: input.label,
|
|
9584
9651
|
description: input.description,
|
|
9585
9652
|
icon: input.icon,
|
|
9653
|
+
layout: input.layout,
|
|
9586
9654
|
tabs: input.tabs,
|
|
9587
9655
|
default: input.default,
|
|
9588
9656
|
metadata: input.metadata
|
|
@@ -9605,7 +9673,8 @@ var ViewService = class extends TenantAwareService {
|
|
|
9605
9673
|
await this.adapter.views.delete(viewId);
|
|
9606
9674
|
}
|
|
9607
9675
|
/**
|
|
9608
|
-
* Set a view as default for its object.
|
|
9676
|
+
* Set a view as default for its object and layout.
|
|
9677
|
+
* Only unsets other defaults for the same layout.
|
|
9609
9678
|
* Automatically uses tenant context from AsyncLocalStorage.
|
|
9610
9679
|
*
|
|
9611
9680
|
* @param viewId - View ID
|
|
@@ -9616,9 +9685,11 @@ var ViewService = class extends TenantAwareService {
|
|
|
9616
9685
|
if (!dbView) {
|
|
9617
9686
|
throw new NotFoundError("View", viewId);
|
|
9618
9687
|
}
|
|
9688
|
+
const viewLayout = dbView.layout ?? "page";
|
|
9619
9689
|
const currentViews = await this.adapter.views.findByObjectName(dbView.objectName);
|
|
9620
9690
|
for (const v of currentViews) {
|
|
9621
|
-
|
|
9691
|
+
const vLayout = v.layout ?? "page";
|
|
9692
|
+
if (v.default && v.id !== viewId && !v.system && vLayout === viewLayout) {
|
|
9622
9693
|
await this.adapter.views.update(v.id, { default: false });
|
|
9623
9694
|
}
|
|
9624
9695
|
}
|
|
@@ -9652,6 +9723,28 @@ var ViewService = class extends TenantAwareService {
|
|
|
9652
9723
|
]);
|
|
9653
9724
|
}
|
|
9654
9725
|
}
|
|
9726
|
+
/**
|
|
9727
|
+
* Validate modal layout constraints.
|
|
9728
|
+
* Modal views must have exactly one form tab.
|
|
9729
|
+
*/
|
|
9730
|
+
validateModalLayout(tabs, layout) {
|
|
9731
|
+
if (layout !== "modal") return;
|
|
9732
|
+
if (!tabs || tabs.length === 0) {
|
|
9733
|
+
throw new ValidationError("Modal views must have exactly one form tab", [
|
|
9734
|
+
{ path: ["tabs"], message: "Modal views must have exactly one form tab" }
|
|
9735
|
+
]);
|
|
9736
|
+
}
|
|
9737
|
+
if (tabs.length > 1) {
|
|
9738
|
+
throw new ValidationError("Modal views can only have one tab", [
|
|
9739
|
+
{ path: ["tabs"], message: "Modal views can only have one tab" }
|
|
9740
|
+
]);
|
|
9741
|
+
}
|
|
9742
|
+
if (tabs[0].type !== "form") {
|
|
9743
|
+
throw new ValidationError("Modal views must have a form tab", [
|
|
9744
|
+
{ path: ["tabs"], message: "Modal views must have a form tab, not a " + tabs[0].type }
|
|
9745
|
+
]);
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9655
9748
|
/**
|
|
9656
9749
|
* Convert database view to ViewDefinition
|
|
9657
9750
|
*/
|
|
@@ -9663,6 +9756,7 @@ var ViewService = class extends TenantAwareService {
|
|
|
9663
9756
|
description: dbView.description,
|
|
9664
9757
|
icon: dbView.icon,
|
|
9665
9758
|
object: dbView.objectName,
|
|
9759
|
+
layout: dbView.layout,
|
|
9666
9760
|
tabs: dbView.tabs,
|
|
9667
9761
|
default: dbView.default,
|
|
9668
9762
|
system: dbView.system,
|
|
@@ -10087,6 +10181,7 @@ export {
|
|
|
10087
10181
|
view,
|
|
10088
10182
|
group,
|
|
10089
10183
|
registry,
|
|
10184
|
+
DEFAULT_VALIDATION_MESSAGES,
|
|
10090
10185
|
textConfigSchema,
|
|
10091
10186
|
textareaConfigSchema,
|
|
10092
10187
|
richtextConfigSchema,
|
|
@@ -10131,6 +10226,7 @@ export {
|
|
|
10131
10226
|
createTextAreaValidator,
|
|
10132
10227
|
createRichtextValidator,
|
|
10133
10228
|
createAttributeValidator,
|
|
10229
|
+
createFormAttributeValidator,
|
|
10134
10230
|
createObjectValidator,
|
|
10135
10231
|
validateAttribute,
|
|
10136
10232
|
validateObject,
|