@relyio/cli 0.4.0 → 0.5.0
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/index.js +265 -1203
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3687,8 +3687,8 @@ function isCommonProtocol(protocol) {
|
|
|
3687
3687
|
return commonProtocols.includes(protocol.toLowerCase());
|
|
3688
3688
|
}
|
|
3689
3689
|
var QUERY_ENDPOINT_SEGMENT, QUERY_ENDPOINT_PATTERN, PARAMETER_EXPRESSION_SOURCE, parameterExpressionMatcher, ANCHORED_PARAMETER_EXPRESSION, parseDefault, parseParameterExpression, collectParameterExpressions, endpointPathParameters, ParameterExpressionStringSchema, QUERY_PARAMETER_TYPES, QueryParameterTypeSchema, QueryParameterScalarSchema, QueryParameterSchema, typeOfDefault, declareQueryParameters, SEARCH_SCORE_SORT_KEYS, isSearchScoreSortKey, QUERY_SYSTEM_FIELDS, isQuerySystemField, QUERY_STORAGE_PATH_PREFIX, QUERY_SYSTEM_ROOTS, SEARCH_SELECT_COLUMNS, isSearchSelectColumn, parseDynamicParameter, ParameterizedLimitSchema, ParameterizedOffsetSchema, ScalarSchema, WhereOperatorObjectSchema, FilterOperatorObjectSchema, HavingOperatorObjectSchema, WhereValueSchema, WhereConditionSchema, SortConditionSchema, EnhancedIncludeObjectSchema, IncludeDefinitionSchema, SelectMappingSchema, FilterDefinitionSchema, FullTextSearchSchema, ContentTypesSchema, SearchBlockSchema, AggregationMetricSchema, QueryCardinalitySchema, QueryCachePolicySchema, FetchBlockSchema, AggregateBlockSchema, IncludeSubQueriesSchema, QueryDefinitionSchema, CACHE_POLICY_STRING, normalizeQueryCachePolicy, CONTENT_API_ROUTE_SEGMENTS, RESERVED_TYPE_IDS, getComponentIdFromType, ComponentSchema, ContentTypeSchema, SettingsGroupSchema, SchemaDefinitionSchema;
|
|
3690
|
-
var
|
|
3691
|
-
"../../domain/schema/dist/chunk-
|
|
3690
|
+
var init_chunk_LKXAZEW4 = __esm({
|
|
3691
|
+
"../../domain/schema/dist/chunk-LKXAZEW4.js"() {
|
|
3692
3692
|
init_chunk_CE6CNF7I();
|
|
3693
3693
|
init_chunk_QG7U6KYM();
|
|
3694
3694
|
init_chunk_W6RFZ2TV();
|
|
@@ -5187,6 +5187,9 @@ function classifyCompatibility(diff2) {
|
|
|
5187
5187
|
}
|
|
5188
5188
|
return { level, safeToMerge, additionsOnly, breakingChanges };
|
|
5189
5189
|
}
|
|
5190
|
+
function isCrossVersionCheckCode(code) {
|
|
5191
|
+
return Object.hasOwn(CROSS_VERSION_CHECKS, code);
|
|
5192
|
+
}
|
|
5190
5193
|
function isConditionObject(value) {
|
|
5191
5194
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5192
5195
|
}
|
|
@@ -5339,10 +5342,10 @@ function notComparedWarning(part, refusals) {
|
|
|
5339
5342
|
suggestion: "Nothing to change for it: this deploy replaces the deployed definition, and the next deploy is compared against all of it"
|
|
5340
5343
|
};
|
|
5341
5344
|
}
|
|
5342
|
-
var USAGE_CONTAINERS, BaseValidator, ValidationUtils, NamingValidator, StructuralValidator, FieldConfigValidator, CrossReferenceValidator, ComponentValidator, ComponentFieldTypeValidator, ComponentValidationUtils, ComponentReusabilityValidator, ComponentFieldStructureValidator, ComponentUsageContextValidator, ComponentNestingValidator, FieldsetValidator, CONTENT_TYPE_PROPS, COMPONENT_PROPS, GROUP_PROPS, QUERY_BASIC_PROPS, QUERY_OPTIONAL_PROPS, QUERY_DSL_BLOCKS, LOCALE_PROPS, ROLE_PROPS, WORKFLOW_STAGE_PROPS, VIEW_PROPS, FIELDSET_PROPS, ASSET_TYPE_PROPS, ASSET_KIND_BLOCKS, ASSET_KIND_KEY_MARKER, FILE_LOCALIZATION_MARKER, FIELD_REQUIRED_CHANGE_KEY, SchemaDiffer, ADDED_LABEL, CROSS_VERSION_CHECKS, EvolutionValidator, HierarchicalContentValidator, FieldRulesValidator, LocalizationValidator, LocaleConfigValidator, SettingsGroupsValidator, SingletonContentTypesValidator, FORBIDDEN_TYPES, AssetTypesValidator, FieldUIValidator, BENEATH, ANY_JOIN, DslQueryValidator, DataIntegrityValidator, RolesValidator, EVOLUTION_VALIDATOR_KEY, CROSS_VERSION_CHECKS_SKIPPED, ValidationPipeline, SchemaValidator, FIELD_SECTIONS, OPERATION_TIER, DEPLOY_VALIDATION_CONFIG;
|
|
5345
|
+
var USAGE_CONTAINERS, BaseValidator, ValidationUtils, NamingValidator, StructuralValidator, FieldConfigValidator, CrossReferenceValidator, ComponentValidator, ComponentFieldTypeValidator, ComponentValidationUtils, ComponentReusabilityValidator, ComponentFieldStructureValidator, ComponentUsageContextValidator, ComponentNestingValidator, FieldsetValidator, CONTENT_TYPE_PROPS, COMPONENT_PROPS, GROUP_PROPS, QUERY_BASIC_PROPS, QUERY_OPTIONAL_PROPS, QUERY_DSL_BLOCKS, LOCALE_PROPS, ROLE_PROPS, WORKFLOW_STAGE_PROPS, VIEW_PROPS, FIELDSET_PROPS, ASSET_TYPE_PROPS, ASSET_KIND_BLOCKS, ASSET_KIND_KEY_MARKER, FILE_LOCALIZATION_MARKER, FIELD_REQUIRED_CHANGE_KEY, SchemaDiffer, ADDED_LABEL, CROSS_VERSION_CHECKS, CROSS_VERSION_CODES, EvolutionValidator, HierarchicalContentValidator, FieldRulesValidator, LocalizationValidator, LocaleConfigValidator, SettingsGroupsValidator, SingletonContentTypesValidator, FORBIDDEN_TYPES, AssetTypesValidator, FieldUIValidator, BENEATH, ANY_JOIN, DslQueryValidator, DataIntegrityValidator, RolesValidator, EVOLUTION_VALIDATOR_KEY, CROSS_VERSION_CHECKS_SKIPPED, ValidationPipeline, SchemaValidator, FIELD_SECTIONS, OPERATION_TIER, DEPLOY_VALIDATION_CONFIG;
|
|
5343
5346
|
var init_dist2 = __esm({
|
|
5344
5347
|
"../../domain/schema/dist/index.js"() {
|
|
5345
|
-
|
|
5348
|
+
init_chunk_LKXAZEW4();
|
|
5346
5349
|
init_chunk_EGQAMYAG();
|
|
5347
5350
|
init_chunk_LDBRHF5K();
|
|
5348
5351
|
init_chunk_GICJZDXP();
|
|
@@ -5651,32 +5654,7 @@ var init_dist2 = __esm({
|
|
|
5651
5654
|
this.checkNamingConventions(name, type, path25, result);
|
|
5652
5655
|
}
|
|
5653
5656
|
validateFieldName(field, path25, result, reservedKeywords) {
|
|
5654
|
-
if (!field.id) {
|
|
5655
|
-
result.errors.push(
|
|
5656
|
-
this.createError(
|
|
5657
|
-
"MISSING_FIELD_ID",
|
|
5658
|
-
"Field is missing required id property",
|
|
5659
|
-
path25,
|
|
5660
|
-
"error",
|
|
5661
|
-
"Add an id property to the field",
|
|
5662
|
-
true
|
|
5663
|
-
)
|
|
5664
|
-
);
|
|
5665
|
-
return;
|
|
5666
|
-
}
|
|
5667
5657
|
const fieldId = field.id;
|
|
5668
|
-
if (!ValidationUtils.isValidName(fieldId)) {
|
|
5669
|
-
result.errors.push(
|
|
5670
|
-
this.createError(
|
|
5671
|
-
"INVALID_FIELD_NAME",
|
|
5672
|
-
`Field id '${fieldId}' is invalid. Must start with a letter and contain only letters, numbers, and underscores`,
|
|
5673
|
-
`${path25}.id`,
|
|
5674
|
-
"error",
|
|
5675
|
-
'Use a valid identifier format (e.g., "myField", "my_field")',
|
|
5676
|
-
true
|
|
5677
|
-
)
|
|
5678
|
-
);
|
|
5679
|
-
}
|
|
5680
5658
|
if (reservedKeywords.includes(fieldId.toLowerCase())) {
|
|
5681
5659
|
const suggestion = ValidationUtils.findBestMatch(fieldId, [
|
|
5682
5660
|
"my" + fieldId,
|
|
@@ -5760,31 +5738,13 @@ var init_dist2 = __esm({
|
|
|
5760
5738
|
feature = "structural";
|
|
5761
5739
|
async validate(index) {
|
|
5762
5740
|
const result = this.createResult();
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
this.validateComponentStructure(index, result);
|
|
5767
|
-
this.validateQueryStructure(index, result);
|
|
5768
|
-
this.validateSettingsStructure(index, result);
|
|
5769
|
-
} catch (error2) {
|
|
5770
|
-
if (error2 instanceof z.ZodError) {
|
|
5771
|
-
this.convertZodErrors(error2, result);
|
|
5772
|
-
} else {
|
|
5773
|
-
result.errors.push(
|
|
5774
|
-
this.createError(
|
|
5775
|
-
"STRUCTURAL_VALIDATION_FAILED",
|
|
5776
|
-
"Schema structural validation failed",
|
|
5777
|
-
"root",
|
|
5778
|
-
"error",
|
|
5779
|
-
"Check schema format and required properties"
|
|
5780
|
-
)
|
|
5781
|
-
);
|
|
5782
|
-
}
|
|
5783
|
-
}
|
|
5741
|
+
this.validateContentTypeStructure(index, result);
|
|
5742
|
+
this.validateComponentStructure(index, result);
|
|
5743
|
+
this.validateSettingsStructure(index, result);
|
|
5784
5744
|
return result;
|
|
5785
5745
|
}
|
|
5786
5746
|
validateContentTypeStructure(index, result) {
|
|
5787
|
-
if (
|
|
5747
|
+
if (index.contentTypes.ids.length === 0) {
|
|
5788
5748
|
result.warnings.push(
|
|
5789
5749
|
this.createError(
|
|
5790
5750
|
"NO_CONTENT_TYPES",
|
|
@@ -5796,17 +5756,6 @@ var init_dist2 = __esm({
|
|
|
5796
5756
|
);
|
|
5797
5757
|
}
|
|
5798
5758
|
for (const [typeId, contentType] of index.contentTypes.entries) {
|
|
5799
|
-
if (!contentType.fields || contentType.fields.length === 0 && !contentType.fieldsets) {
|
|
5800
|
-
result.warnings.push(
|
|
5801
|
-
this.createError(
|
|
5802
|
-
"EMPTY_CONTENT_TYPE",
|
|
5803
|
-
`Content type '${typeId}' has no fields`,
|
|
5804
|
-
`contentTypes.${typeId}`,
|
|
5805
|
-
"warning",
|
|
5806
|
-
"Add fields to make this content type useful"
|
|
5807
|
-
)
|
|
5808
|
-
);
|
|
5809
|
-
}
|
|
5810
5759
|
this.validateFieldsStructure(
|
|
5811
5760
|
contentType.fields || [],
|
|
5812
5761
|
`contentTypes.${typeId}.fields`,
|
|
@@ -5816,7 +5765,7 @@ var init_dist2 = __esm({
|
|
|
5816
5765
|
}
|
|
5817
5766
|
validateComponentStructure(index, result) {
|
|
5818
5767
|
for (const [componentId, component] of index.components.entries) {
|
|
5819
|
-
if (
|
|
5768
|
+
if (component.fields.length === 0) {
|
|
5820
5769
|
result.errors.push(
|
|
5821
5770
|
this.createError(
|
|
5822
5771
|
"EMPTY_COMPONENT",
|
|
@@ -5831,147 +5780,23 @@ var init_dist2 = __esm({
|
|
|
5831
5780
|
}
|
|
5832
5781
|
}
|
|
5833
5782
|
}
|
|
5834
|
-
validateQueryStructure(index, result) {
|
|
5835
|
-
for (const [queryId, query] of Object.entries(index.schema.queries || {})) {
|
|
5836
|
-
if (!query.endpoint) {
|
|
5837
|
-
result.errors.push(
|
|
5838
|
-
this.createError(
|
|
5839
|
-
"MISSING_QUERY_ENDPOINT",
|
|
5840
|
-
`Query '${queryId}' is missing endpoint`,
|
|
5841
|
-
`queries.${queryId}`,
|
|
5842
|
-
"error",
|
|
5843
|
-
"All queries must have an endpoint property"
|
|
5844
|
-
)
|
|
5845
|
-
);
|
|
5846
|
-
}
|
|
5847
|
-
const blocks = queryBlocksOf(query);
|
|
5848
|
-
if (blocks.length === 0) {
|
|
5849
|
-
result.errors.push(
|
|
5850
|
-
this.createError(
|
|
5851
|
-
"MISSING_QUERY_TYPE",
|
|
5852
|
-
`Query '${queryId}' must have one of: ${QUERY_BLOCKS_SPELLED}`,
|
|
5853
|
-
`queries.${queryId}`,
|
|
5854
|
-
"error",
|
|
5855
|
-
`Add a ${QUERY_BLOCKS_SPELLED} block to define the query operation`
|
|
5856
|
-
)
|
|
5857
|
-
);
|
|
5858
|
-
}
|
|
5859
|
-
if (query.fetch) {
|
|
5860
|
-
this.validateFetchStructure(query.fetch, queryId, result);
|
|
5861
|
-
}
|
|
5862
|
-
if (query.aggregate) {
|
|
5863
|
-
this.validateAggregateStructure(query.aggregate, queryId, Boolean(query.fetch), result);
|
|
5864
|
-
}
|
|
5865
|
-
if (query.search) {
|
|
5866
|
-
this.validateSearchStructure(query.search, queryId, result);
|
|
5867
|
-
}
|
|
5868
|
-
}
|
|
5869
|
-
}
|
|
5870
|
-
validateFetchStructure(fetch2, queryId, result) {
|
|
5871
|
-
const basePath = `queries.${queryId}.fetch`;
|
|
5872
|
-
if (!fetch2.contentType && !fetch2.singleton) {
|
|
5873
|
-
result.errors.push(
|
|
5874
|
-
this.createError(
|
|
5875
|
-
"FETCH_MISSING_TARGET",
|
|
5876
|
-
`Fetch operation in query '${queryId}' must specify contentType or singleton`,
|
|
5877
|
-
basePath,
|
|
5878
|
-
"error",
|
|
5879
|
-
"Add contentType or singleton property to the fetch operation"
|
|
5880
|
-
)
|
|
5881
|
-
);
|
|
5882
|
-
}
|
|
5883
|
-
if (fetch2.contentType && fetch2.singleton) {
|
|
5884
|
-
result.errors.push(
|
|
5885
|
-
this.createError(
|
|
5886
|
-
"FETCH_MULTIPLE_TARGETS",
|
|
5887
|
-
`Fetch operation in query '${queryId}' cannot have both contentType and singleton`,
|
|
5888
|
-
basePath,
|
|
5889
|
-
"error",
|
|
5890
|
-
"Use either contentType OR singleton, not both"
|
|
5891
|
-
)
|
|
5892
|
-
);
|
|
5893
|
-
}
|
|
5894
|
-
}
|
|
5895
|
-
validateAggregateStructure(aggregate, queryId, hasFetch, result) {
|
|
5896
|
-
const basePath = `queries.${queryId}.aggregate`;
|
|
5897
|
-
if (!hasFetch && !aggregate.source) {
|
|
5898
|
-
result.errors.push(
|
|
5899
|
-
this.createError(
|
|
5900
|
-
"AGGREGATE_MISSING_SOURCE",
|
|
5901
|
-
`Aggregate operation in query '${queryId}' must specify source content type when not used with fetch`,
|
|
5902
|
-
`${basePath}.source`,
|
|
5903
|
-
"error",
|
|
5904
|
-
"Add source property to specify which content type to aggregate, or use with a fetch block"
|
|
5905
|
-
)
|
|
5906
|
-
);
|
|
5907
|
-
}
|
|
5908
|
-
}
|
|
5909
|
-
validateSearchStructure(search, queryId, result) {
|
|
5910
|
-
const basePath = `queries.${queryId}.search`;
|
|
5911
|
-
if (!search.contentType && !search.contentTypes) {
|
|
5912
|
-
result.errors.push(
|
|
5913
|
-
this.createError(
|
|
5914
|
-
"SEARCH_MISSING_CONTENT_TYPE",
|
|
5915
|
-
`Search operation in query '${queryId}' must specify contentType or contentTypes`,
|
|
5916
|
-
basePath,
|
|
5917
|
-
"error",
|
|
5918
|
-
"Add contentType for single type search, or contentTypes for multi-type/global search"
|
|
5919
|
-
)
|
|
5920
|
-
);
|
|
5921
|
-
}
|
|
5922
|
-
if (!search.query) {
|
|
5923
|
-
result.errors.push(
|
|
5924
|
-
this.createError(
|
|
5925
|
-
"SEARCH_MISSING_QUERY",
|
|
5926
|
-
`Search operation in query '${queryId}' must specify a search query`,
|
|
5927
|
-
`${basePath}.query`,
|
|
5928
|
-
"error",
|
|
5929
|
-
'Add query property with search string or parameter like "${q}"'
|
|
5930
|
-
)
|
|
5931
|
-
);
|
|
5932
|
-
}
|
|
5933
|
-
}
|
|
5934
5783
|
validateSettingsStructure(index, result) {
|
|
5935
5784
|
for (const [settingsId, settingsGroup] of index.settingsGroups.entries) {
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
`settingsGroups.${settingsId}`,
|
|
5942
|
-
"warning",
|
|
5943
|
-
"Settings groups should have configuration fields"
|
|
5944
|
-
)
|
|
5945
|
-
);
|
|
5946
|
-
} else {
|
|
5947
|
-
this.validateFieldsStructure(
|
|
5948
|
-
settingsGroup.fields,
|
|
5949
|
-
`settingsGroups.${settingsId}.fields`,
|
|
5950
|
-
result
|
|
5951
|
-
);
|
|
5952
|
-
}
|
|
5785
|
+
this.validateFieldsStructure(
|
|
5786
|
+
settingsGroup.fields,
|
|
5787
|
+
`settingsGroups.${settingsId}.fields`,
|
|
5788
|
+
result
|
|
5789
|
+
);
|
|
5953
5790
|
}
|
|
5954
5791
|
}
|
|
5955
5792
|
validateFieldsStructure(fields, basePath, result) {
|
|
5956
|
-
for (const
|
|
5957
|
-
const
|
|
5958
|
-
const fieldPath = `${basePath}.${fieldIdentifier}`;
|
|
5959
|
-
if (!field.id) {
|
|
5960
|
-
result.errors.push(
|
|
5961
|
-
this.createError(
|
|
5962
|
-
"MISSING_FIELD_ID",
|
|
5963
|
-
`Field at index ${index} is missing id`,
|
|
5964
|
-
fieldPath,
|
|
5965
|
-
"error",
|
|
5966
|
-
"All fields must have an id property"
|
|
5967
|
-
)
|
|
5968
|
-
);
|
|
5969
|
-
}
|
|
5793
|
+
for (const field of fields) {
|
|
5794
|
+
const fieldPath = `${basePath}.${field.id}`;
|
|
5970
5795
|
if (!field.type) {
|
|
5971
5796
|
result.errors.push(
|
|
5972
5797
|
this.createError(
|
|
5973
5798
|
"MISSING_FIELD_TYPE",
|
|
5974
|
-
`Field '${field.id
|
|
5799
|
+
`Field '${field.id}' is missing type`,
|
|
5975
5800
|
fieldPath,
|
|
5976
5801
|
"error",
|
|
5977
5802
|
"All fields must have a type property"
|
|
@@ -6044,53 +5869,6 @@ var init_dist2 = __esm({
|
|
|
6044
5869
|
}
|
|
6045
5870
|
}
|
|
6046
5871
|
}
|
|
6047
|
-
convertZodErrors(zodError, result) {
|
|
6048
|
-
for (const error2 of zodError.errors) {
|
|
6049
|
-
const path25 = error2.path.join(".");
|
|
6050
|
-
let message = error2.message;
|
|
6051
|
-
let suggestion;
|
|
6052
|
-
switch (error2.code) {
|
|
6053
|
-
case "invalid_enum_value": {
|
|
6054
|
-
const options = "options" in error2 ? error2.options : [];
|
|
6055
|
-
message = `Invalid value. Expected one of: ${options.join(", ")}`;
|
|
6056
|
-
suggestion = `Use one of the valid options: ${options.join(", ")}`;
|
|
6057
|
-
break;
|
|
6058
|
-
}
|
|
6059
|
-
case "invalid_type": {
|
|
6060
|
-
const expected = error2.expected;
|
|
6061
|
-
const received = error2.received;
|
|
6062
|
-
message = `Expected ${expected}, received ${received}`;
|
|
6063
|
-
suggestion = `Change the value to be of type ${expected}`;
|
|
6064
|
-
break;
|
|
6065
|
-
}
|
|
6066
|
-
case "too_small": {
|
|
6067
|
-
const minimum = error2.minimum;
|
|
6068
|
-
message = `Value is too small. Minimum: ${minimum}`;
|
|
6069
|
-
suggestion = `Increase the value to at least ${minimum}`;
|
|
6070
|
-
break;
|
|
6071
|
-
}
|
|
6072
|
-
case "too_big": {
|
|
6073
|
-
const maximum = error2.maximum;
|
|
6074
|
-
message = `Value is too large. Maximum: ${maximum}`;
|
|
6075
|
-
suggestion = `Decrease the value to at most ${maximum}`;
|
|
6076
|
-
break;
|
|
6077
|
-
}
|
|
6078
|
-
case "invalid_string": {
|
|
6079
|
-
if (error2.validation === "email") {
|
|
6080
|
-
message = "Invalid email format";
|
|
6081
|
-
suggestion = "Provide a valid email address";
|
|
6082
|
-
} else if (error2.validation === "url") {
|
|
6083
|
-
message = "Invalid URL format";
|
|
6084
|
-
suggestion = "Provide a valid URL starting with http:// or https://";
|
|
6085
|
-
}
|
|
6086
|
-
break;
|
|
6087
|
-
}
|
|
6088
|
-
}
|
|
6089
|
-
result.errors.push(
|
|
6090
|
-
this.createError("SCHEMA_VALIDATION_ERROR", message, path25 || "root", "error", suggestion)
|
|
6091
|
-
);
|
|
6092
|
-
}
|
|
6093
|
-
}
|
|
6094
5872
|
};
|
|
6095
5873
|
FieldConfigValidator = class extends BaseValidator {
|
|
6096
5874
|
feature = "fieldConfigurations";
|
|
@@ -6888,20 +6666,7 @@ var init_dist2 = __esm({
|
|
|
6888
6666
|
}
|
|
6889
6667
|
}
|
|
6890
6668
|
} else {
|
|
6891
|
-
|
|
6892
|
-
result.errors.push(
|
|
6893
|
-
this.createError(
|
|
6894
|
-
"DUPLICATE_FIELD_NAME",
|
|
6895
|
-
`Duplicate field name '${field.id}' in content type '${contentTypeId}'`,
|
|
6896
|
-
`contentTypes.${contentTypeId}.fields.${field.id}`,
|
|
6897
|
-
"error",
|
|
6898
|
-
"Field names must be unique within a content type",
|
|
6899
|
-
true
|
|
6900
|
-
)
|
|
6901
|
-
);
|
|
6902
|
-
} else {
|
|
6903
|
-
contentTypeFields.set(field.id, field.type);
|
|
6904
|
-
}
|
|
6669
|
+
contentTypeFields.set(field.id, field.type);
|
|
6905
6670
|
}
|
|
6906
6671
|
}
|
|
6907
6672
|
}
|
|
@@ -6925,20 +6690,7 @@ var init_dist2 = __esm({
|
|
|
6925
6690
|
for (const [componentId, component] of index.components.entries) {
|
|
6926
6691
|
const fieldTypes = /* @__PURE__ */ new Map();
|
|
6927
6692
|
if (component.fields)
|
|
6928
|
-
for (const
|
|
6929
|
-
if (!field.id) {
|
|
6930
|
-
result.errors.push(
|
|
6931
|
-
this.createError(
|
|
6932
|
-
"COMPONENT_FIELD_MISSING_ID",
|
|
6933
|
-
`Field at index ${index2} in component '${componentId}' is missing id`,
|
|
6934
|
-
`components.${componentId}.fields[${index2}]`,
|
|
6935
|
-
"error",
|
|
6936
|
-
"All component fields must have unique identifiers",
|
|
6937
|
-
true
|
|
6938
|
-
)
|
|
6939
|
-
);
|
|
6940
|
-
continue;
|
|
6941
|
-
}
|
|
6693
|
+
for (const field of component.fields) {
|
|
6942
6694
|
if (!field.type) {
|
|
6943
6695
|
result.errors.push(
|
|
6944
6696
|
this.createError(
|
|
@@ -6985,7 +6737,7 @@ var init_dist2 = __esm({
|
|
|
6985
6737
|
}
|
|
6986
6738
|
for (const [index2, field] of fields.entries()) {
|
|
6987
6739
|
const fieldPath = `components.${componentId}.fields.${field.id || `[${index2}]`}`;
|
|
6988
|
-
if (!field.
|
|
6740
|
+
if (!field.type) {
|
|
6989
6741
|
result.errors.push(
|
|
6990
6742
|
this.createError(
|
|
6991
6743
|
"INCOMPLETE_FIELD_STRUCTURE",
|
|
@@ -7031,17 +6783,6 @@ var init_dist2 = __esm({
|
|
|
7031
6783
|
if (component.fields)
|
|
7032
6784
|
for (const field of component.fields) {
|
|
7033
6785
|
const fieldPath = `components.${componentId}.fields.${field.id}`;
|
|
7034
|
-
if (field.id && field.id.includes(".")) {
|
|
7035
|
-
result.warnings.push(
|
|
7036
|
-
this.createError(
|
|
7037
|
-
"FIELD_NAME_SERIALIZATION_RISK",
|
|
7038
|
-
`Field '${field.id}' in component '${componentId}' contains dots which may cause serialization issues`,
|
|
7039
|
-
fieldPath,
|
|
7040
|
-
"warning",
|
|
7041
|
-
"Use underscores or camelCase instead of dots in field names"
|
|
7042
|
-
)
|
|
7043
|
-
);
|
|
7044
|
-
}
|
|
7045
6786
|
if (field.id && field.id.length > 50) {
|
|
7046
6787
|
result.warnings.push(
|
|
7047
6788
|
this.createError(
|
|
@@ -7103,22 +6844,6 @@ var init_dist2 = __esm({
|
|
|
7103
6844
|
for (const [componentId, component] of index.components.entries) {
|
|
7104
6845
|
const usagePattern = componentUsagePatterns[componentId];
|
|
7105
6846
|
if (!usagePattern) continue;
|
|
7106
|
-
if (this.isSeoComponent(componentId, component)) {
|
|
7107
|
-
for (const contentTypeId of usagePattern.usedInContentTypes) {
|
|
7108
|
-
const contentType = index.schema.contentTypes?.[contentTypeId];
|
|
7109
|
-
if (contentType && this.isNonPublicContentType(contentType)) {
|
|
7110
|
-
result.warnings.push(
|
|
7111
|
-
this.createError(
|
|
7112
|
-
"SEO_COMPONENT_IN_PRIVATE_CONTENT",
|
|
7113
|
-
`SEO component '${componentId}' is used in non-public content type '${contentTypeId}'`,
|
|
7114
|
-
`contentTypes.${contentTypeId}`,
|
|
7115
|
-
"warning",
|
|
7116
|
-
"Consider whether SEO metadata is needed for internal/private content types"
|
|
7117
|
-
)
|
|
7118
|
-
);
|
|
7119
|
-
}
|
|
7120
|
-
}
|
|
7121
|
-
}
|
|
7122
6847
|
if (this.isSystemComponent(componentId, component)) {
|
|
7123
6848
|
for (const contentTypeId of usagePattern.usedInContentTypes) {
|
|
7124
6849
|
result.warnings.push(
|
|
@@ -7278,20 +7003,6 @@ var init_dist2 = __esm({
|
|
|
7278
7003
|
}
|
|
7279
7004
|
return patterns;
|
|
7280
7005
|
}
|
|
7281
|
-
isSeoComponent(componentId, component) {
|
|
7282
|
-
const seoKeywords = ["seo", "meta", "og", "twitter", "social"];
|
|
7283
|
-
const componentName = componentId.toLowerCase();
|
|
7284
|
-
return seoKeywords.some((keyword) => componentName.includes(keyword)) || (component.fields || []).some(
|
|
7285
|
-
(field) => field.id && seoKeywords.some((keyword) => field.id.toLowerCase().includes(keyword))
|
|
7286
|
-
);
|
|
7287
|
-
}
|
|
7288
|
-
isNonPublicContentType(contentType) {
|
|
7289
|
-
const internalKeywords = ["admin", "system", "internal", "private", "draft"];
|
|
7290
|
-
const ct = contentType;
|
|
7291
|
-
const typeName = ct.id?.toLowerCase() || "";
|
|
7292
|
-
const visibility = ct.metadata?.visibility;
|
|
7293
|
-
return internalKeywords.some((keyword) => typeName.includes(keyword)) || visibility === "private";
|
|
7294
|
-
}
|
|
7295
7006
|
isSystemComponent(componentId, _component) {
|
|
7296
7007
|
const systemKeywords = ["system", "admin", "internal", "config"];
|
|
7297
7008
|
return systemKeywords.some((keyword) => componentId.toLowerCase().includes(keyword));
|
|
@@ -7305,15 +7016,12 @@ var init_dist2 = __esm({
|
|
|
7305
7016
|
);
|
|
7306
7017
|
return componentField ? {
|
|
7307
7018
|
fieldName: componentField.id,
|
|
7308
|
-
hasRules: (componentField.rules || []).length > 0
|
|
7309
|
-
isRequired: componentField.required || false
|
|
7019
|
+
hasRules: (componentField.rules || []).length > 0
|
|
7310
7020
|
} : null;
|
|
7311
7021
|
}).filter(Boolean);
|
|
7312
7022
|
if (usagePatterns.length < 2) return false;
|
|
7313
7023
|
const firstPattern = usagePatterns[0];
|
|
7314
|
-
return usagePatterns.some(
|
|
7315
|
-
(pattern) => pattern && (pattern.hasRules !== firstPattern?.hasRules || pattern.isRequired !== firstPattern?.isRequired)
|
|
7316
|
-
);
|
|
7024
|
+
return usagePatterns.some((pattern) => pattern && pattern.hasRules !== firstPattern?.hasRules);
|
|
7317
7025
|
}
|
|
7318
7026
|
};
|
|
7319
7027
|
ComponentNestingValidator = class extends BaseValidator {
|
|
@@ -8641,13 +8349,36 @@ var init_dist2 = __esm({
|
|
|
8641
8349
|
settingsGroups: "settings groups"
|
|
8642
8350
|
};
|
|
8643
8351
|
CROSS_VERSION_CHECKS = {
|
|
8644
|
-
FIELD_TYPE_CHANGE_FORBIDDEN:
|
|
8645
|
-
|
|
8646
|
-
|
|
8352
|
+
FIELD_TYPE_CHANGE_FORBIDDEN: {
|
|
8353
|
+
names: "a field's type change",
|
|
8354
|
+
severity: "error",
|
|
8355
|
+
fixable: false
|
|
8356
|
+
},
|
|
8357
|
+
REFERENCE_TARGET_REMOVED: {
|
|
8358
|
+
names: "a removed reference target",
|
|
8359
|
+
severity: "error",
|
|
8360
|
+
fixable: false
|
|
8361
|
+
},
|
|
8362
|
+
MISSING_DEPRECATION_MARKER: {
|
|
8363
|
+
names: "a replacement field beside an undeprecated one",
|
|
8364
|
+
severity: "warning",
|
|
8365
|
+
fixable: true
|
|
8366
|
+
}
|
|
8647
8367
|
};
|
|
8368
|
+
CROSS_VERSION_CODES = Object.keys(CROSS_VERSION_CHECKS);
|
|
8648
8369
|
EvolutionValidator = class extends BaseValidator {
|
|
8649
8370
|
feature = "schemaEvolution";
|
|
8650
8371
|
schemaDiffer = new SchemaDiffer();
|
|
8372
|
+
/**
|
|
8373
|
+
* Each cross-version check's finder, under the code {@link CROSS_VERSION_CHECKS} reports it by. A
|
|
8374
|
+
* code the table gains is a missing property here until it has a finder, and a finder under a code
|
|
8375
|
+
* the table does not name is an excess one.
|
|
8376
|
+
*/
|
|
8377
|
+
crossVersionFinders = {
|
|
8378
|
+
FIELD_TYPE_CHANGE_FORBIDDEN: (comparison) => this.fieldTypeChanges(comparison),
|
|
8379
|
+
REFERENCE_TARGET_REMOVED: (comparison) => this.removedReferenceTargets(comparison),
|
|
8380
|
+
MISSING_DEPRECATION_MARKER: (comparison) => this.undeprecatedReplacements(comparison)
|
|
8381
|
+
};
|
|
8651
8382
|
async validate(index) {
|
|
8652
8383
|
const result = this.createResult();
|
|
8653
8384
|
this.validateEvolutionReadiness(index, result);
|
|
@@ -8660,13 +8391,22 @@ var init_dist2 = __esm({
|
|
|
8660
8391
|
const result = this.createResult();
|
|
8661
8392
|
const newIndex = buildSchemaIndex(newSchema);
|
|
8662
8393
|
this.validateEvolutionReadiness(newIndex, result);
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8394
|
+
const comparison = {
|
|
8395
|
+
previous: oldSchema,
|
|
8396
|
+
next: newIndex,
|
|
8397
|
+
diff: this.schemaDiffer.computeDiff(oldSchema, newSchema)
|
|
8398
|
+
};
|
|
8399
|
+
for (const code of CROSS_VERSION_CODES) {
|
|
8400
|
+
const { severity, fixable } = CROSS_VERSION_CHECKS[code];
|
|
8401
|
+
const reported = severity === "error" ? result.errors : result.warnings;
|
|
8402
|
+
for (const { message, path: path25, suggestion } of this.crossVersionFinders[code](comparison)) {
|
|
8403
|
+
reported.push(this.createError(code, message, path25, severity, suggestion, fixable));
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8666
8406
|
return result;
|
|
8667
8407
|
}
|
|
8668
8408
|
/**
|
|
8669
|
-
*
|
|
8409
|
+
* Reference fields that still target a content/asset type removed in
|
|
8670
8410
|
* this change. `DataIntegrityValidator` already errors on a dangling target
|
|
8671
8411
|
* (REFERENCE_TARGET_NOT_FOUND) when it validates the new schema in isolation;
|
|
8672
8412
|
* this diff-aware pass upgrades the same situation to an attributed breaking
|
|
@@ -8676,99 +8416,81 @@ var init_dist2 = __esm({
|
|
|
8676
8416
|
* Reference fields inside asset types are covered too — {@link BaseValidator.traverseFields}
|
|
8677
8417
|
* walks asset type fields by default.
|
|
8678
8418
|
*/
|
|
8679
|
-
|
|
8680
|
-
const diff2 = this.schemaDiffer.computeDiff(oldSchema, newIndex.schema);
|
|
8419
|
+
removedReferenceTargets({ next, diff: diff2 }) {
|
|
8681
8420
|
const removedTargets = /* @__PURE__ */ new Map();
|
|
8682
8421
|
for (const id of diff2.removed.contentTypes) removedTargets.set(id, "content");
|
|
8683
8422
|
for (const id of diff2.removed.singletonContentTypes) removedTargets.set(id, "content");
|
|
8684
8423
|
for (const id of diff2.removed.assetTypes) removedTargets.set(id, "asset");
|
|
8685
|
-
|
|
8686
|
-
|
|
8424
|
+
const findings = [];
|
|
8425
|
+
if (removedTargets.size === 0) return findings;
|
|
8426
|
+
this.traverseFields(next, (field, path25) => {
|
|
8687
8427
|
if (field.type !== "reference") return;
|
|
8688
8428
|
const targets = normalizeReferenceTargets(field.config?.to);
|
|
8689
8429
|
for (const [index, targetId] of targets.entries()) {
|
|
8690
8430
|
const family = removedTargets.get(targetId);
|
|
8691
8431
|
if (!family) continue;
|
|
8692
|
-
|
|
8693
|
-
this
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
"error",
|
|
8698
|
-
`Restore the ${family} type '${targetId}', or remove/repoint the reference field '${field.id}' before deploying`,
|
|
8699
|
-
false
|
|
8700
|
-
)
|
|
8701
|
-
);
|
|
8432
|
+
findings.push({
|
|
8433
|
+
message: `Reference field '${field.id}' targets ${family} type '${targetId}', which was removed in this change`,
|
|
8434
|
+
path: `${path25}.config.to[${index}]`,
|
|
8435
|
+
suggestion: `Restore the ${family} type '${targetId}', or remove/repoint the reference field '${field.id}' before deploying`
|
|
8436
|
+
});
|
|
8702
8437
|
}
|
|
8703
8438
|
});
|
|
8439
|
+
return findings;
|
|
8704
8440
|
}
|
|
8705
8441
|
/**
|
|
8706
|
-
*
|
|
8442
|
+
* The field type immutability rule: a field keeps the type it was deployed with.
|
|
8707
8443
|
*/
|
|
8708
|
-
|
|
8709
|
-
const oldFieldTypes = this.buildFieldTypeHistory(
|
|
8710
|
-
const newFieldTypes = this.buildFieldTypeHistory(
|
|
8444
|
+
fieldTypeChanges({ previous, next }) {
|
|
8445
|
+
const oldFieldTypes = this.buildFieldTypeHistory(previous);
|
|
8446
|
+
const newFieldTypes = this.buildFieldTypeHistory(next.schema);
|
|
8447
|
+
const findings = [];
|
|
8711
8448
|
for (const [fieldKey, oldField] of oldFieldTypes.entries()) {
|
|
8712
8449
|
const newField = newFieldTypes.get(fieldKey);
|
|
8713
8450
|
if (newField && oldField.fieldType !== newField.fieldType) {
|
|
8714
8451
|
const oldType = this.normalizeFieldType(oldField.fieldType);
|
|
8715
8452
|
const newType = this.normalizeFieldType(newField.fieldType);
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
newField.path,
|
|
8721
|
-
"error",
|
|
8722
|
-
`Use deprecation workflow:
|
|
8453
|
+
findings.push({
|
|
8454
|
+
message: `Field type cannot be changed after deployment: "${oldField.fieldId}" (${oldType} \u2192 ${newType})`,
|
|
8455
|
+
path: newField.path,
|
|
8456
|
+
suggestion: `Use deprecation workflow:
|
|
8723
8457
|
\u250C\u2500 Correct approach
|
|
8724
8458
|
\u2502 fields:
|
|
8725
8459
|
\u2502 \u251C\u2500 ${oldField.fieldId}:
|
|
8726
8460
|
\u2502 \u2502 type: "${oldField.fieldType}"
|
|
8727
8461
|
\u2502 \u2502 deprecated: true # Mark old field as deprecated
|
|
8728
8462
|
\u2502 \u2514\u2500 ${oldField.fieldId}_v2:
|
|
8729
|
-
\u2502 type: "${newField.fieldType}" # Create new field with correct type
|
|
8730
|
-
|
|
8731
|
-
)
|
|
8732
|
-
);
|
|
8463
|
+
\u2502 type: "${newField.fieldType}" # Create new field with correct type`
|
|
8464
|
+
});
|
|
8733
8465
|
}
|
|
8734
8466
|
}
|
|
8467
|
+
return findings;
|
|
8735
8468
|
}
|
|
8736
8469
|
/**
|
|
8737
|
-
*
|
|
8470
|
+
* A field added beside one it appears to replace, which is not marked deprecated.
|
|
8738
8471
|
*/
|
|
8739
|
-
|
|
8740
|
-
const
|
|
8472
|
+
undeprecatedReplacements({ previous, next, diff: diff2 }) {
|
|
8473
|
+
const findings = [];
|
|
8741
8474
|
for (const contentTypeChange of diff2.modified.contentTypes) {
|
|
8742
8475
|
for (const addedFieldId of contentTypeChange.changes.addedFields) {
|
|
8743
8476
|
const potentialOriginalField = this.findPotentialOriginalField(
|
|
8744
8477
|
addedFieldId,
|
|
8745
|
-
|
|
8478
|
+
previous,
|
|
8746
8479
|
contentTypeChange.name
|
|
8747
8480
|
);
|
|
8748
|
-
if (potentialOriginalField) {
|
|
8749
|
-
|
|
8750
|
-
potentialOriginalField
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
);
|
|
8754
|
-
if (!isOriginalDeprecated) {
|
|
8755
|
-
result.warnings.push(
|
|
8756
|
-
this.createError(
|
|
8757
|
-
"MISSING_DEPRECATION_MARKER",
|
|
8758
|
-
`Field '${addedFieldId}' appears to be a replacement for '${potentialOriginalField}'. Consider marking the original field as deprecated.`,
|
|
8759
|
-
`contentTypes.${contentTypeChange.name}.fields.${potentialOriginalField}`,
|
|
8760
|
-
"warning",
|
|
8761
|
-
`Mark the original field as deprecated:
|
|
8481
|
+
if (potentialOriginalField && !this.isFieldDeprecated(potentialOriginalField, next.schema, contentTypeChange.name)) {
|
|
8482
|
+
findings.push({
|
|
8483
|
+
message: `Field '${addedFieldId}' appears to be a replacement for '${potentialOriginalField}'. Consider marking the original field as deprecated.`,
|
|
8484
|
+
path: `contentTypes.${contentTypeChange.name}.fields.${potentialOriginalField}`,
|
|
8485
|
+
suggestion: `Mark the original field as deprecated:
|
|
8762
8486
|
- id: "${potentialOriginalField}"
|
|
8763
8487
|
type: "..."
|
|
8764
|
-
deprecated: true
|
|
8765
|
-
|
|
8766
|
-
)
|
|
8767
|
-
);
|
|
8768
|
-
}
|
|
8488
|
+
deprecated: true`
|
|
8489
|
+
});
|
|
8769
8490
|
}
|
|
8770
8491
|
}
|
|
8771
8492
|
}
|
|
8493
|
+
return findings;
|
|
8772
8494
|
}
|
|
8773
8495
|
/**
|
|
8774
8496
|
* Builds a map of field types from a schema for comparison
|
|
@@ -9013,9 +8735,7 @@ var init_dist2 = __esm({
|
|
|
9013
8735
|
const safeChanges = [];
|
|
9014
8736
|
const evolutionResult = await this.validateSchemaEvolution(oldSchema, newSchema);
|
|
9015
8737
|
for (const error2 of evolutionResult.errors) {
|
|
9016
|
-
if (error2.code
|
|
9017
|
-
breakingChanges.push(error2.message);
|
|
9018
|
-
}
|
|
8738
|
+
if (isCrossVersionCheckCode(error2.code)) breakingChanges.push(error2.message);
|
|
9019
8739
|
}
|
|
9020
8740
|
const diff2 = this.schemaDiffer.computeDiff(oldSchema, newSchema);
|
|
9021
8741
|
const compatibility = classifyCompatibility(diff2);
|
|
@@ -9226,19 +8946,6 @@ var init_dist2 = __esm({
|
|
|
9226
8946
|
return fieldIds;
|
|
9227
8947
|
}
|
|
9228
8948
|
validateFieldRules(rules, fieldId, fieldPath, result, allFieldIds, _context) {
|
|
9229
|
-
if (!Array.isArray(rules)) {
|
|
9230
|
-
result.errors.push(
|
|
9231
|
-
this.createError(
|
|
9232
|
-
"INVALID_RULES_FORMAT",
|
|
9233
|
-
"Field rules must be an array",
|
|
9234
|
-
`${fieldPath}.rules`,
|
|
9235
|
-
"error",
|
|
9236
|
-
"Change rules to an array format: rules: [...]",
|
|
9237
|
-
true
|
|
9238
|
-
)
|
|
9239
|
-
);
|
|
9240
|
-
return;
|
|
9241
|
-
}
|
|
9242
8949
|
const ruleTypes = /* @__PURE__ */ new Set();
|
|
9243
8950
|
for (const [ruleIndex, rule] of rules.entries()) {
|
|
9244
8951
|
const rulePath = `${fieldPath}.rules[${ruleIndex}]`;
|
|
@@ -9261,86 +8968,16 @@ var init_dist2 = __esm({
|
|
|
9261
8968
|
this.checkCircularDependencies(rules, fieldId, fieldPath, result, allFieldIds);
|
|
9262
8969
|
this.validateRuleLogicConsistency(rules, fieldId, fieldPath, result);
|
|
9263
8970
|
}
|
|
8971
|
+
/**
|
|
8972
|
+
* A rule's shape — its type, its action, its message, a mode, a non-empty list of conditions and
|
|
8973
|
+
* each condition's operator — is the parse's (`FieldRuleSchema`), which refuses every one this
|
|
8974
|
+
* checked; none of those eleven checks could fire (REL-1497, `parse-refuses-first.test.ts`). What
|
|
8975
|
+
* is left is what the parse cannot know: which fields a condition names, and whether its operator
|
|
8976
|
+
* has the value it compares with.
|
|
8977
|
+
*/
|
|
9264
8978
|
validateSingleRule(rule, rulePath, result, allFieldIds, currentFieldId) {
|
|
9265
|
-
const
|
|
9266
|
-
|
|
9267
|
-
result.errors.push(
|
|
9268
|
-
this.createError(
|
|
9269
|
-
"INVALID_RULE_TYPE",
|
|
9270
|
-
`Invalid rule type '${rule.type}'. Must be one of: ${validRuleTypes.join(", ")}`,
|
|
9271
|
-
`${rulePath}.type`,
|
|
9272
|
-
"error",
|
|
9273
|
-
`Use one of the valid rule types: ${validRuleTypes.join(", ")}`,
|
|
9274
|
-
true
|
|
9275
|
-
)
|
|
9276
|
-
);
|
|
9277
|
-
}
|
|
9278
|
-
const hasConditions = rule.conditions && rule.conditions.conditions && rule.conditions.conditions.length > 0;
|
|
9279
|
-
if (!hasConditions) {
|
|
9280
|
-
result.errors.push(
|
|
9281
|
-
this.createError(
|
|
9282
|
-
"MISSING_RULE_CONDITION",
|
|
9283
|
-
"Rule must specify conditions with at least one condition entry",
|
|
9284
|
-
rulePath,
|
|
9285
|
-
"error",
|
|
9286
|
-
"Add a conditions object to define when the rule applies",
|
|
9287
|
-
true
|
|
9288
|
-
)
|
|
9289
|
-
);
|
|
9290
|
-
}
|
|
9291
|
-
if (hasConditions) {
|
|
9292
|
-
this.validateConditions(
|
|
9293
|
-
rule.conditions,
|
|
9294
|
-
`${rulePath}.conditions`,
|
|
9295
|
-
result,
|
|
9296
|
-
allFieldIds,
|
|
9297
|
-
currentFieldId
|
|
9298
|
-
);
|
|
9299
|
-
}
|
|
9300
|
-
this.validateRuleSpecificProperties(rule, rulePath, result);
|
|
9301
|
-
}
|
|
9302
|
-
validateConditions(conditions, conditionsPath, result, allFieldIds, currentFieldId) {
|
|
9303
|
-
if (!conditions) return;
|
|
9304
|
-
const validModes = ["all", "any", "none"];
|
|
9305
|
-
if (!validModes.includes(conditions.mode)) {
|
|
9306
|
-
result.errors.push(
|
|
9307
|
-
this.createError(
|
|
9308
|
-
"INVALID_CONDITIONS_MODE",
|
|
9309
|
-
`Invalid conditions mode '${conditions.mode}'. Must be one of: ${validModes.join(", ")}`,
|
|
9310
|
-
`${conditionsPath}.mode`,
|
|
9311
|
-
"error",
|
|
9312
|
-
`Use one of: ${validModes.join(", ")}`,
|
|
9313
|
-
true
|
|
9314
|
-
)
|
|
9315
|
-
);
|
|
9316
|
-
}
|
|
9317
|
-
if (!conditions.conditions || !Array.isArray(conditions.conditions)) {
|
|
9318
|
-
result.errors.push(
|
|
9319
|
-
this.createError(
|
|
9320
|
-
"INVALID_CONDITIONS_ARRAY",
|
|
9321
|
-
"Conditions must include a 'conditions' array",
|
|
9322
|
-
`${conditionsPath}.conditions`,
|
|
9323
|
-
"error",
|
|
9324
|
-
"Add a conditions array with at least one condition",
|
|
9325
|
-
true
|
|
9326
|
-
)
|
|
9327
|
-
);
|
|
9328
|
-
return;
|
|
9329
|
-
}
|
|
9330
|
-
if (conditions.conditions.length === 0) {
|
|
9331
|
-
result.errors.push(
|
|
9332
|
-
this.createError(
|
|
9333
|
-
"EMPTY_CONDITIONS_ARRAY",
|
|
9334
|
-
"Conditions array cannot be empty",
|
|
9335
|
-
`${conditionsPath}.conditions`,
|
|
9336
|
-
"error",
|
|
9337
|
-
"Add at least one condition to the array",
|
|
9338
|
-
true
|
|
9339
|
-
)
|
|
9340
|
-
);
|
|
9341
|
-
return;
|
|
9342
|
-
}
|
|
9343
|
-
for (const [index, condition] of conditions.conditions.entries()) {
|
|
8979
|
+
const conditionsPath = `${rulePath}.conditions`;
|
|
8980
|
+
for (const [index, condition] of rule.conditions.conditions.entries()) {
|
|
9344
8981
|
this.validateSingleCondition(
|
|
9345
8982
|
condition,
|
|
9346
8983
|
`${conditionsPath}.conditions[${index}]`,
|
|
@@ -9387,28 +9024,6 @@ var init_dist2 = __esm({
|
|
|
9387
9024
|
)
|
|
9388
9025
|
);
|
|
9389
9026
|
}
|
|
9390
|
-
const validOperators = [
|
|
9391
|
-
"equals",
|
|
9392
|
-
"not_equals",
|
|
9393
|
-
"contains",
|
|
9394
|
-
"not_contains",
|
|
9395
|
-
"greater_than",
|
|
9396
|
-
"less_than",
|
|
9397
|
-
"is_empty",
|
|
9398
|
-
"is_not_empty"
|
|
9399
|
-
];
|
|
9400
|
-
if (!validOperators.includes(condition.operator)) {
|
|
9401
|
-
result.errors.push(
|
|
9402
|
-
this.createError(
|
|
9403
|
-
"INVALID_CONDITION_OPERATOR",
|
|
9404
|
-
`Invalid operator '${condition.operator}'. Must be one of: ${validOperators.join(", ")}`,
|
|
9405
|
-
`${conditionPath}.operator`,
|
|
9406
|
-
"error",
|
|
9407
|
-
`Use one of: ${validOperators.join(", ")}`,
|
|
9408
|
-
true
|
|
9409
|
-
)
|
|
9410
|
-
);
|
|
9411
|
-
}
|
|
9412
9027
|
const operatorsRequiringValue = [
|
|
9413
9028
|
"equals",
|
|
9414
9029
|
"not_equals",
|
|
@@ -9444,70 +9059,6 @@ var init_dist2 = __esm({
|
|
|
9444
9059
|
);
|
|
9445
9060
|
}
|
|
9446
9061
|
}
|
|
9447
|
-
validateRuleSpecificProperties(rule, rulePath, result) {
|
|
9448
|
-
switch (rule.type) {
|
|
9449
|
-
case "visibility": {
|
|
9450
|
-
if ("action" in rule && rule.action && !["show", "hide"].includes(rule.action)) {
|
|
9451
|
-
result.errors.push(
|
|
9452
|
-
this.createError(
|
|
9453
|
-
"INVALID_VISIBILITY_ACTION",
|
|
9454
|
-
`Invalid visibility action '${rule.action}'. Must be 'show' or 'hide'`,
|
|
9455
|
-
`${rulePath}.action`,
|
|
9456
|
-
"error",
|
|
9457
|
-
"Use 'show' or 'hide'",
|
|
9458
|
-
true
|
|
9459
|
-
)
|
|
9460
|
-
);
|
|
9461
|
-
}
|
|
9462
|
-
break;
|
|
9463
|
-
}
|
|
9464
|
-
case "requirement": {
|
|
9465
|
-
if ("action" in rule && rule.action && !["require", "optional"].includes(rule.action)) {
|
|
9466
|
-
result.errors.push(
|
|
9467
|
-
this.createError(
|
|
9468
|
-
"INVALID_REQUIREMENT_ACTION",
|
|
9469
|
-
`Invalid requirement action '${rule.action}'. Must be 'require' or 'optional'`,
|
|
9470
|
-
`${rulePath}.action`,
|
|
9471
|
-
"error",
|
|
9472
|
-
"Use 'require' or 'optional'",
|
|
9473
|
-
true
|
|
9474
|
-
)
|
|
9475
|
-
);
|
|
9476
|
-
}
|
|
9477
|
-
break;
|
|
9478
|
-
}
|
|
9479
|
-
case "validation": {
|
|
9480
|
-
if ("message" in rule && rule.message && typeof rule.message !== "string") {
|
|
9481
|
-
result.errors.push(
|
|
9482
|
-
this.createError(
|
|
9483
|
-
"INVALID_VALIDATION_MESSAGE",
|
|
9484
|
-
"Validation message must be a string",
|
|
9485
|
-
`${rulePath}.message`,
|
|
9486
|
-
"error",
|
|
9487
|
-
"Provide a string message for validation errors",
|
|
9488
|
-
true
|
|
9489
|
-
)
|
|
9490
|
-
);
|
|
9491
|
-
}
|
|
9492
|
-
break;
|
|
9493
|
-
}
|
|
9494
|
-
case "readOnly": {
|
|
9495
|
-
if ("action" in rule && rule.action && !["enable", "disable"].includes(rule.action)) {
|
|
9496
|
-
result.errors.push(
|
|
9497
|
-
this.createError(
|
|
9498
|
-
"INVALID_READONLY_ACTION",
|
|
9499
|
-
`Invalid readOnly action '${rule.action}'. Must be 'enable' or 'disable'`,
|
|
9500
|
-
`${rulePath}.action`,
|
|
9501
|
-
"error",
|
|
9502
|
-
"Use 'enable' or 'disable'",
|
|
9503
|
-
true
|
|
9504
|
-
)
|
|
9505
|
-
);
|
|
9506
|
-
}
|
|
9507
|
-
break;
|
|
9508
|
-
}
|
|
9509
|
-
}
|
|
9510
|
-
}
|
|
9511
9062
|
checkCircularDependencies(rules, _fieldId, _fieldPath, _result, _allFieldIds) {
|
|
9512
9063
|
const referencedFields = /* @__PURE__ */ new Set();
|
|
9513
9064
|
for (const rule of rules) {
|
|
@@ -9582,6 +9133,15 @@ var init_dist2 = __esm({
|
|
|
9582
9133
|
});
|
|
9583
9134
|
return fieldIds;
|
|
9584
9135
|
}
|
|
9136
|
+
/**
|
|
9137
|
+
* A declared `localization`, in the one of its three forms the parse admits
|
|
9138
|
+
* (`LocalizationConfigSchema`): a boolean, a list of locale codes, or `{ enabled, requiredLocales? }`
|
|
9139
|
+
* with `enabled` a boolean and `requiredLocales` a list. This refused any other form
|
|
9140
|
+
* (`INVALID_LOCALIZATION_FORMAT`), an `enabled` that is not a boolean
|
|
9141
|
+
* (`INVALID_LOCALIZATION_ENABLED`) and a `requiredLocales` that is not a list
|
|
9142
|
+
* (`INVALID_REQUIRED_LOCALES`) — the parse refuses all three first, so none could fire (REL-1497,
|
|
9143
|
+
* `parse-refuses-first.test.ts`).
|
|
9144
|
+
*/
|
|
9585
9145
|
validateFieldLocalization(field, fieldPath, result, _allFieldIds, _context) {
|
|
9586
9146
|
const localization = field.localization;
|
|
9587
9147
|
const localizationPath = `${fieldPath}.localization`;
|
|
@@ -9589,24 +9149,8 @@ var init_dist2 = __esm({
|
|
|
9589
9149
|
this.validateBooleanLocalization(localization, localizationPath, result, field);
|
|
9590
9150
|
} else if (Array.isArray(localization)) {
|
|
9591
9151
|
this.validateArrayLocalization(localization, localizationPath, result, field);
|
|
9592
|
-
} else if (
|
|
9593
|
-
this.
|
|
9594
|
-
localization,
|
|
9595
|
-
localizationPath,
|
|
9596
|
-
result,
|
|
9597
|
-
field
|
|
9598
|
-
);
|
|
9599
|
-
} else {
|
|
9600
|
-
result.errors.push(
|
|
9601
|
-
this.createError(
|
|
9602
|
-
"INVALID_LOCALIZATION_FORMAT",
|
|
9603
|
-
"Localization must be a boolean, string array, or configuration object",
|
|
9604
|
-
localizationPath,
|
|
9605
|
-
"error",
|
|
9606
|
-
"Use true/false, array of locale codes, or { enabled: boolean, ... } object",
|
|
9607
|
-
true
|
|
9608
|
-
)
|
|
9609
|
-
);
|
|
9152
|
+
} else if (localization !== void 0) {
|
|
9153
|
+
this.validateRequiredLocales(localization.requiredLocales, localizationPath, result);
|
|
9610
9154
|
}
|
|
9611
9155
|
}
|
|
9612
9156
|
validateBooleanLocalization(enabled, localizationPath, result, field) {
|
|
@@ -9664,36 +9208,10 @@ var init_dist2 = __esm({
|
|
|
9664
9208
|
);
|
|
9665
9209
|
}
|
|
9666
9210
|
}
|
|
9667
|
-
|
|
9668
|
-
if (
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
"INVALID_LOCALIZATION_ENABLED",
|
|
9672
|
-
"Localization 'enabled' property must be a boolean",
|
|
9673
|
-
`${localizationPath}.enabled`,
|
|
9674
|
-
"error",
|
|
9675
|
-
"Use true or false",
|
|
9676
|
-
true
|
|
9677
|
-
)
|
|
9678
|
-
);
|
|
9679
|
-
}
|
|
9680
|
-
if (config.requiredLocales) {
|
|
9681
|
-
if (Array.isArray(config.requiredLocales)) {
|
|
9682
|
-
for (const [index, locale] of config.requiredLocales.entries()) {
|
|
9683
|
-
this.validateLocaleCode(locale, `${localizationPath}.requiredLocales[${index}]`, result);
|
|
9684
|
-
}
|
|
9685
|
-
} else {
|
|
9686
|
-
result.errors.push(
|
|
9687
|
-
this.createError(
|
|
9688
|
-
"INVALID_REQUIRED_LOCALES",
|
|
9689
|
-
"Required locales must be an array of locale codes",
|
|
9690
|
-
`${localizationPath}.requiredLocales`,
|
|
9691
|
-
"error",
|
|
9692
|
-
"Use array format: ['en-US', 'fr-FR']",
|
|
9693
|
-
true
|
|
9694
|
-
)
|
|
9695
|
-
);
|
|
9696
|
-
}
|
|
9211
|
+
validateRequiredLocales(requiredLocales, localizationPath, result) {
|
|
9212
|
+
if (requiredLocales === void 0) return;
|
|
9213
|
+
for (const [index, locale] of requiredLocales.entries()) {
|
|
9214
|
+
this.validateLocaleCode(locale, `${localizationPath}.requiredLocales[${index}]`, result);
|
|
9697
9215
|
}
|
|
9698
9216
|
}
|
|
9699
9217
|
validateFieldFallback(field, fieldPath, result, allFieldIds, _context) {
|
|
@@ -10080,93 +9598,13 @@ var init_dist2 = __esm({
|
|
|
10080
9598
|
});
|
|
10081
9599
|
}
|
|
10082
9600
|
/**
|
|
10083
|
-
*
|
|
9601
|
+
* The locale list's shape — exactly one default, unique codes, fallbacks to declared locales,
|
|
9602
|
+
* none to itself and no cycle — is the parse's (`LocalesArraySchema`), which refuses each first,
|
|
9603
|
+
* so the six checks this made of it could not fire (REL-1497, `parse-refuses-first.test.ts`).
|
|
9604
|
+
* What is left is advice the parse does not give.
|
|
10084
9605
|
*/
|
|
10085
9606
|
validateLocaleConfiguration(locales, result) {
|
|
10086
|
-
const
|
|
10087
|
-
if (defaultLocales.length === 0) {
|
|
10088
|
-
result.errors.push(
|
|
10089
|
-
this.createError(
|
|
10090
|
-
"NO_DEFAULT_LOCALE",
|
|
10091
|
-
"No default locale defined. Exactly one locale must be marked as default.",
|
|
10092
|
-
"locales",
|
|
10093
|
-
"error",
|
|
10094
|
-
"Add 'default: true' to one of your locale definitions",
|
|
10095
|
-
true
|
|
10096
|
-
)
|
|
10097
|
-
);
|
|
10098
|
-
} else if (defaultLocales.length > 1) {
|
|
10099
|
-
result.errors.push(
|
|
10100
|
-
this.createError(
|
|
10101
|
-
"MULTIPLE_DEFAULT_LOCALES",
|
|
10102
|
-
`Multiple default locales defined: ${defaultLocales.map((l) => l.code).join(", ")}`,
|
|
10103
|
-
"locales",
|
|
10104
|
-
"error",
|
|
10105
|
-
"Only one locale can be the default",
|
|
10106
|
-
true
|
|
10107
|
-
)
|
|
10108
|
-
);
|
|
10109
|
-
}
|
|
10110
|
-
const seenCodes = /* @__PURE__ */ new Set();
|
|
10111
|
-
for (const [index, locale] of locales.entries()) {
|
|
10112
|
-
if (seenCodes.has(locale.code)) {
|
|
10113
|
-
result.errors.push(
|
|
10114
|
-
this.createError(
|
|
10115
|
-
"DUPLICATE_LOCALE_CODE",
|
|
10116
|
-
`Duplicate locale code '${locale.code}'`,
|
|
10117
|
-
`locales[${index}]`,
|
|
10118
|
-
"error",
|
|
10119
|
-
"Each locale must have a unique code",
|
|
10120
|
-
true
|
|
10121
|
-
)
|
|
10122
|
-
);
|
|
10123
|
-
}
|
|
10124
|
-
seenCodes.add(locale.code);
|
|
10125
|
-
}
|
|
10126
|
-
const localeCodes = new Set(locales.map((l) => l.code));
|
|
10127
|
-
for (const [index, locale] of locales.entries()) {
|
|
10128
|
-
if (!locale.fallback) continue;
|
|
10129
|
-
for (const [fallbackIndex, fallbackCode] of locale.fallback.entries()) {
|
|
10130
|
-
if (!localeCodes.has(fallbackCode)) {
|
|
10131
|
-
result.errors.push(
|
|
10132
|
-
this.createError(
|
|
10133
|
-
"INVALID_LOCALE_FALLBACK",
|
|
10134
|
-
`Locale '${locale.code}' has fallback to non-existent locale '${fallbackCode}'`,
|
|
10135
|
-
`locales[${index}].fallback[${fallbackIndex}]`,
|
|
10136
|
-
"error",
|
|
10137
|
-
`Reference an existing locale: ${[...localeCodes].join(", ")}`,
|
|
10138
|
-
true
|
|
10139
|
-
)
|
|
10140
|
-
);
|
|
10141
|
-
}
|
|
10142
|
-
if (fallbackCode === locale.code) {
|
|
10143
|
-
result.errors.push(
|
|
10144
|
-
this.createError(
|
|
10145
|
-
"SELF_REFERENCING_LOCALE_FALLBACK",
|
|
10146
|
-
`Locale '${locale.code}' references itself in fallback chain`,
|
|
10147
|
-
`locales[${index}].fallback[${fallbackIndex}]`,
|
|
10148
|
-
"error",
|
|
10149
|
-
"Remove self-reference from fallback chain",
|
|
10150
|
-
true
|
|
10151
|
-
)
|
|
10152
|
-
);
|
|
10153
|
-
}
|
|
10154
|
-
}
|
|
10155
|
-
const circularPath = this.detectCircularFallback(locale.code, locales);
|
|
10156
|
-
if (circularPath) {
|
|
10157
|
-
result.errors.push(
|
|
10158
|
-
this.createError(
|
|
10159
|
-
"CIRCULAR_LOCALE_FALLBACK",
|
|
10160
|
-
`Circular fallback chain detected: ${circularPath.join(" \u2192 ")}`,
|
|
10161
|
-
`locales[${index}].fallback`,
|
|
10162
|
-
"error",
|
|
10163
|
-
"Remove circular references in fallback chain",
|
|
10164
|
-
true
|
|
10165
|
-
)
|
|
10166
|
-
);
|
|
10167
|
-
}
|
|
10168
|
-
}
|
|
10169
|
-
const defaultLocale = defaultLocales[0];
|
|
9607
|
+
const defaultLocale = locales.find((l) => l.default === true);
|
|
10170
9608
|
if (defaultLocale?.fallback && defaultLocale.fallback.length > 0) {
|
|
10171
9609
|
result.warnings.push(
|
|
10172
9610
|
this.createError(
|
|
@@ -10224,34 +9662,6 @@ var init_dist2 = __esm({
|
|
|
10224
9662
|
}
|
|
10225
9663
|
});
|
|
10226
9664
|
}
|
|
10227
|
-
/**
|
|
10228
|
-
* Detects circular fallback chains starting from a given locale
|
|
10229
|
-
*/
|
|
10230
|
-
detectCircularFallback(startCode, locales) {
|
|
10231
|
-
const visited = /* @__PURE__ */ new Set();
|
|
10232
|
-
const path25 = [];
|
|
10233
|
-
const localeMap = new Map(locales.map((l) => [l.code, l]));
|
|
10234
|
-
const visit = (code) => {
|
|
10235
|
-
if (visited.has(code)) {
|
|
10236
|
-
const cycleStart = path25.indexOf(code);
|
|
10237
|
-
return [...path25.slice(cycleStart), code];
|
|
10238
|
-
}
|
|
10239
|
-
const locale = localeMap.get(code);
|
|
10240
|
-
if (!locale?.fallback || locale.fallback.length === 0) {
|
|
10241
|
-
return null;
|
|
10242
|
-
}
|
|
10243
|
-
visited.add(code);
|
|
10244
|
-
path25.push(code);
|
|
10245
|
-
for (const fallbackCode of locale.fallback) {
|
|
10246
|
-
const cycle = visit(fallbackCode);
|
|
10247
|
-
if (cycle) return cycle;
|
|
10248
|
-
}
|
|
10249
|
-
path25.pop();
|
|
10250
|
-
visited.delete(code);
|
|
10251
|
-
return null;
|
|
10252
|
-
};
|
|
10253
|
-
return visit(startCode);
|
|
10254
|
-
}
|
|
10255
9665
|
};
|
|
10256
9666
|
SettingsGroupsValidator = class extends BaseValidator {
|
|
10257
9667
|
feature = "settingsGroups";
|
|
@@ -10328,53 +9738,27 @@ var init_dist2 = __esm({
|
|
|
10328
9738
|
)
|
|
10329
9739
|
);
|
|
10330
9740
|
}
|
|
10331
|
-
if (
|
|
10332
|
-
result.
|
|
9741
|
+
if (settingsGroup.displayName.length < 3) {
|
|
9742
|
+
result.warnings.push(
|
|
10333
9743
|
this.createError(
|
|
10334
|
-
"
|
|
10335
|
-
`Settings group '${groupId}'
|
|
9744
|
+
"SHORT_SETTINGS_GROUP_DISPLAY_NAME",
|
|
9745
|
+
`Settings group '${groupId}' has a very short displayName`,
|
|
10336
9746
|
`${groupPath}.displayName`,
|
|
10337
|
-
"
|
|
10338
|
-
"
|
|
10339
|
-
true
|
|
9747
|
+
"warning",
|
|
9748
|
+
"Use a more descriptive displayName (at least 3 characters)"
|
|
10340
9749
|
)
|
|
10341
9750
|
);
|
|
10342
|
-
} else {
|
|
10343
|
-
if (settingsGroup.displayName.length < 3) {
|
|
10344
|
-
result.warnings.push(
|
|
10345
|
-
this.createError(
|
|
10346
|
-
"SHORT_SETTINGS_GROUP_DISPLAY_NAME",
|
|
10347
|
-
`Settings group '${groupId}' has a very short displayName`,
|
|
10348
|
-
`${groupPath}.displayName`,
|
|
10349
|
-
"warning",
|
|
10350
|
-
"Use a more descriptive displayName (at least 3 characters)"
|
|
10351
|
-
)
|
|
10352
|
-
);
|
|
10353
|
-
}
|
|
10354
9751
|
}
|
|
10355
9752
|
if (settingsGroup.description) {
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
result.warnings.push(
|
|
10360
|
-
this.createError(
|
|
10361
|
-
"SHORT_SETTINGS_GROUP_DESCRIPTION",
|
|
10362
|
-
`Settings group '${groupId}' has a very short description`,
|
|
10363
|
-
`${groupPath}.description`,
|
|
10364
|
-
"warning",
|
|
10365
|
-
"Provide a more detailed description for better understanding"
|
|
10366
|
-
)
|
|
10367
|
-
);
|
|
10368
|
-
}
|
|
10369
|
-
} else {
|
|
10370
|
-
result.errors.push(
|
|
9753
|
+
stats.groupsWithDescriptions++;
|
|
9754
|
+
if (settingsGroup.description.length < 10) {
|
|
9755
|
+
result.warnings.push(
|
|
10371
9756
|
this.createError(
|
|
10372
|
-
"
|
|
10373
|
-
`Settings group '${groupId}'
|
|
9757
|
+
"SHORT_SETTINGS_GROUP_DESCRIPTION",
|
|
9758
|
+
`Settings group '${groupId}' has a very short description`,
|
|
10374
9759
|
`${groupPath}.description`,
|
|
10375
|
-
"
|
|
10376
|
-
"
|
|
10377
|
-
true
|
|
9760
|
+
"warning",
|
|
9761
|
+
"Provide a more detailed description for better understanding"
|
|
10378
9762
|
)
|
|
10379
9763
|
);
|
|
10380
9764
|
}
|
|
@@ -10389,47 +9773,13 @@ var init_dist2 = __esm({
|
|
|
10389
9773
|
)
|
|
10390
9774
|
);
|
|
10391
9775
|
}
|
|
10392
|
-
if (!settingsGroup.fields || !Array.isArray(settingsGroup.fields)) {
|
|
10393
|
-
result.errors.push(
|
|
10394
|
-
this.createError(
|
|
10395
|
-
"MISSING_SETTINGS_FIELDS_ARRAY",
|
|
10396
|
-
`Settings group '${groupId}' must have a fields array`,
|
|
10397
|
-
`${groupPath}.fields`,
|
|
10398
|
-
"error",
|
|
10399
|
-
"Add a fields array with field configurations",
|
|
10400
|
-
true
|
|
10401
|
-
)
|
|
10402
|
-
);
|
|
10403
|
-
} else if (settingsGroup.fields.length === 0) {
|
|
10404
|
-
result.warnings.push(
|
|
10405
|
-
this.createError(
|
|
10406
|
-
"EMPTY_SETTINGS_GROUP_FIELDS",
|
|
10407
|
-
`Settings group '${groupId}' has no fields`,
|
|
10408
|
-
`${groupPath}.fields`,
|
|
10409
|
-
"warning",
|
|
10410
|
-
"Add fields or remove this empty group"
|
|
10411
|
-
)
|
|
10412
|
-
);
|
|
10413
|
-
}
|
|
10414
9776
|
}
|
|
10415
9777
|
validateSettingsGroupFields(groupId, settingsGroup, result, allFieldIds, stats) {
|
|
10416
9778
|
const groupPath = `settingsGroups.${groupId}`;
|
|
10417
|
-
if (!Array.isArray(settingsGroup.fields)) {
|
|
10418
|
-
return;
|
|
10419
|
-
}
|
|
10420
9779
|
stats.totalFields += settingsGroup.fields.length;
|
|
10421
|
-
const groupFieldIds = /* @__PURE__ */ new Set();
|
|
10422
9780
|
for (const [index, field] of settingsGroup.fields.entries()) {
|
|
10423
9781
|
const fieldPath = `${groupPath}.fields[${index}]`;
|
|
10424
|
-
this.validateSettingsField(
|
|
10425
|
-
field,
|
|
10426
|
-
fieldPath,
|
|
10427
|
-
result,
|
|
10428
|
-
groupFieldIds,
|
|
10429
|
-
allFieldIds,
|
|
10430
|
-
groupId,
|
|
10431
|
-
stats
|
|
10432
|
-
);
|
|
9782
|
+
this.validateSettingsField(field, fieldPath, result, allFieldIds, groupId, stats);
|
|
10433
9783
|
}
|
|
10434
9784
|
if (settingsGroup.fields.length > 15) {
|
|
10435
9785
|
result.warnings.push(
|
|
@@ -10443,57 +9793,21 @@ var init_dist2 = __esm({
|
|
|
10443
9793
|
);
|
|
10444
9794
|
}
|
|
10445
9795
|
if (settingsGroup.fields.length >= 8 && settingsGroup.fields.length <= 15) {
|
|
10446
|
-
result.info.push(
|
|
10447
|
-
this.createError(
|
|
10448
|
-
"CONSIDER_SUBGROUPING",
|
|
10449
|
-
`Settings group '${groupId}' with ${settingsGroup.fields.length} fields might benefit from logical subgrouping`,
|
|
10450
|
-
`${groupPath}`,
|
|
10451
|
-
"info",
|
|
10452
|
-
"Consider organizing related fields together or using field prefixes for clarity"
|
|
10453
|
-
)
|
|
10454
|
-
);
|
|
10455
|
-
}
|
|
10456
|
-
}
|
|
10457
|
-
validateSettingsField(field, fieldPath, result, groupFieldIds, allFieldIds, groupId, stats) {
|
|
10458
|
-
if (!field.id || typeof field.id !== "string") {
|
|
10459
|
-
result.errors.push(
|
|
10460
|
-
this.createError(
|
|
10461
|
-
"MISSING_FIELD_ID",
|
|
10462
|
-
"Field must have an id property",
|
|
10463
|
-
`${fieldPath}.id`,
|
|
10464
|
-
"error",
|
|
10465
|
-
"Add a unique string id for this field",
|
|
10466
|
-
true
|
|
10467
|
-
)
|
|
10468
|
-
);
|
|
10469
|
-
return;
|
|
10470
|
-
}
|
|
10471
|
-
if (groupFieldIds.has(field.id)) {
|
|
10472
|
-
result.errors.push(
|
|
10473
|
-
this.createError(
|
|
10474
|
-
"DUPLICATE_FIELD_ID",
|
|
10475
|
-
`Duplicate field ID '${field.id}' in settings group '${groupId}'`,
|
|
10476
|
-
`${fieldPath}.id`,
|
|
10477
|
-
"error",
|
|
10478
|
-
"Use unique field IDs within each settings group",
|
|
10479
|
-
true
|
|
10480
|
-
)
|
|
10481
|
-
);
|
|
10482
|
-
} else {
|
|
10483
|
-
groupFieldIds.add(field.id);
|
|
10484
|
-
}
|
|
10485
|
-
if (!ValidationUtils.isValidName(field.id)) {
|
|
10486
|
-
result.warnings.push(
|
|
9796
|
+
result.info.push(
|
|
10487
9797
|
this.createError(
|
|
10488
|
-
"
|
|
10489
|
-
`
|
|
10490
|
-
`${
|
|
10491
|
-
"
|
|
10492
|
-
"
|
|
9798
|
+
"CONSIDER_SUBGROUPING",
|
|
9799
|
+
`Settings group '${groupId}' with ${settingsGroup.fields.length} fields might benefit from logical subgrouping`,
|
|
9800
|
+
`${groupPath}`,
|
|
9801
|
+
"info",
|
|
9802
|
+
"Consider organizing related fields together or using field prefixes for clarity"
|
|
10493
9803
|
)
|
|
10494
9804
|
);
|
|
10495
9805
|
}
|
|
10496
|
-
|
|
9806
|
+
}
|
|
9807
|
+
validateSettingsField(field, fieldPath, result, allFieldIds, groupId, stats) {
|
|
9808
|
+
if (field.type) {
|
|
9809
|
+
this.validateFieldTypeForSettings(field, fieldPath, result);
|
|
9810
|
+
} else {
|
|
10497
9811
|
result.errors.push(
|
|
10498
9812
|
this.createError(
|
|
10499
9813
|
"MISSING_FIELD_TYPE",
|
|
@@ -10504,8 +9818,6 @@ var init_dist2 = __esm({
|
|
|
10504
9818
|
true
|
|
10505
9819
|
)
|
|
10506
9820
|
);
|
|
10507
|
-
} else {
|
|
10508
|
-
this.validateFieldTypeForSettings(field, fieldPath, result);
|
|
10509
9821
|
}
|
|
10510
9822
|
if (field.localization !== void 0) {
|
|
10511
9823
|
this.validateSettingsFieldLocalization(field, fieldPath, result);
|
|
@@ -10768,7 +10080,7 @@ var init_dist2 = __esm({
|
|
|
10768
10080
|
singletonsWithSlugFields: 0,
|
|
10769
10081
|
singletonsWithUniqueFields: 0
|
|
10770
10082
|
};
|
|
10771
|
-
if (
|
|
10083
|
+
if (index.singletonContentTypes.ids.length === 0) {
|
|
10772
10084
|
result.info.push(
|
|
10773
10085
|
this.createError(
|
|
10774
10086
|
"NO_SINGLETON_CONTENT_TYPES",
|
|
@@ -10807,18 +10119,6 @@ var init_dist2 = __esm({
|
|
|
10807
10119
|
}
|
|
10808
10120
|
validateSingletonStructure(singletonId, singletonType, result, stats) {
|
|
10809
10121
|
const singletonPath = `singletonContentTypes.${singletonId}`;
|
|
10810
|
-
if (!ValidationUtils.isValidName(singletonId)) {
|
|
10811
|
-
result.errors.push(
|
|
10812
|
-
this.createError(
|
|
10813
|
-
"INVALID_SINGLETON_ID",
|
|
10814
|
-
`Singleton content type ID '${singletonId}' is invalid`,
|
|
10815
|
-
singletonPath,
|
|
10816
|
-
"error",
|
|
10817
|
-
"Use camelCase or snake_case starting with a letter",
|
|
10818
|
-
true
|
|
10819
|
-
)
|
|
10820
|
-
);
|
|
10821
|
-
}
|
|
10822
10122
|
const reservedKeywords = ValidationUtils.getReservedKeywords();
|
|
10823
10123
|
if (reservedKeywords.includes(singletonId.toLowerCase())) {
|
|
10824
10124
|
result.errors.push(
|
|
@@ -10832,18 +10132,7 @@ var init_dist2 = __esm({
|
|
|
10832
10132
|
)
|
|
10833
10133
|
);
|
|
10834
10134
|
}
|
|
10835
|
-
if (
|
|
10836
|
-
result.errors.push(
|
|
10837
|
-
this.createError(
|
|
10838
|
-
"MISSING_SINGLETON_DISPLAY_NAME",
|
|
10839
|
-
`Singleton content type '${singletonId}' must have a displayName`,
|
|
10840
|
-
`${singletonPath}.displayName`,
|
|
10841
|
-
"error",
|
|
10842
|
-
"Add a descriptive displayName property",
|
|
10843
|
-
true
|
|
10844
|
-
)
|
|
10845
|
-
);
|
|
10846
|
-
} else {
|
|
10135
|
+
if (singletonType.displayName) {
|
|
10847
10136
|
if (singletonType.displayName.length < 3) {
|
|
10848
10137
|
result.warnings.push(
|
|
10849
10138
|
this.createError(
|
|
@@ -10855,30 +10144,28 @@ var init_dist2 = __esm({
|
|
|
10855
10144
|
)
|
|
10856
10145
|
);
|
|
10857
10146
|
}
|
|
10147
|
+
} else {
|
|
10148
|
+
result.errors.push(
|
|
10149
|
+
this.createError(
|
|
10150
|
+
"MISSING_SINGLETON_DISPLAY_NAME",
|
|
10151
|
+
`Singleton content type '${singletonId}' must have a displayName`,
|
|
10152
|
+
`${singletonPath}.displayName`,
|
|
10153
|
+
"error",
|
|
10154
|
+
"Add a descriptive displayName property",
|
|
10155
|
+
true
|
|
10156
|
+
)
|
|
10157
|
+
);
|
|
10858
10158
|
}
|
|
10859
10159
|
if (singletonType.description) {
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
result.warnings.push(
|
|
10864
|
-
this.createError(
|
|
10865
|
-
"SHORT_SINGLETON_DESCRIPTION",
|
|
10866
|
-
`Singleton content type '${singletonId}' has a very short description`,
|
|
10867
|
-
`${singletonPath}.description`,
|
|
10868
|
-
"warning",
|
|
10869
|
-
"Provide a more detailed description for better understanding"
|
|
10870
|
-
)
|
|
10871
|
-
);
|
|
10872
|
-
}
|
|
10873
|
-
} else {
|
|
10874
|
-
result.errors.push(
|
|
10160
|
+
stats.singletonsWithDescriptions++;
|
|
10161
|
+
if (singletonType.description.length < 10) {
|
|
10162
|
+
result.warnings.push(
|
|
10875
10163
|
this.createError(
|
|
10876
|
-
"
|
|
10877
|
-
`Singleton content type '${singletonId}'
|
|
10164
|
+
"SHORT_SINGLETON_DESCRIPTION",
|
|
10165
|
+
`Singleton content type '${singletonId}' has a very short description`,
|
|
10878
10166
|
`${singletonPath}.description`,
|
|
10879
|
-
"
|
|
10880
|
-
"
|
|
10881
|
-
true
|
|
10167
|
+
"warning",
|
|
10168
|
+
"Provide a more detailed description for better understanding"
|
|
10882
10169
|
)
|
|
10883
10170
|
);
|
|
10884
10171
|
}
|
|
@@ -10906,21 +10193,7 @@ var init_dist2 = __esm({
|
|
|
10906
10193
|
);
|
|
10907
10194
|
stats.singletonsWithHierarchical++;
|
|
10908
10195
|
}
|
|
10909
|
-
|
|
10910
|
-
const hasFieldsets = singletonType.fieldsets && Array.isArray(singletonType.fieldsets) && singletonType.fieldsets.length > 0;
|
|
10911
|
-
if (!hasDirectFields && !hasFieldsets) {
|
|
10912
|
-
result.errors.push(
|
|
10913
|
-
this.createError(
|
|
10914
|
-
"SINGLETON_NO_FIELDS",
|
|
10915
|
-
`Singleton content type '${singletonId}' has no fields or fieldsets`,
|
|
10916
|
-
`${singletonPath}.fields`,
|
|
10917
|
-
"error",
|
|
10918
|
-
"Add fields or fieldsets to define the singleton's structure",
|
|
10919
|
-
true
|
|
10920
|
-
)
|
|
10921
|
-
);
|
|
10922
|
-
}
|
|
10923
|
-
if (hasFieldsets) {
|
|
10196
|
+
if (singletonType.fieldsets && singletonType.fieldsets.length > 0) {
|
|
10924
10197
|
stats.singletonsWithFieldsets++;
|
|
10925
10198
|
}
|
|
10926
10199
|
}
|
|
@@ -10928,26 +10201,9 @@ var init_dist2 = __esm({
|
|
|
10928
10201
|
const singletonPath = `singletonContentTypes.${singletonId}`;
|
|
10929
10202
|
const allFields = this.getAllFieldsFromSingleton(singletonType);
|
|
10930
10203
|
stats.totalFields += allFields.length;
|
|
10931
|
-
const fieldIds = /* @__PURE__ */ new Set();
|
|
10932
10204
|
let hasLocalizationEnabled = false;
|
|
10933
10205
|
for (const [index, field] of allFields.entries()) {
|
|
10934
10206
|
const fieldPath = this.getFieldPath(singletonPath, field, index, singletonType);
|
|
10935
|
-
if (field.id) {
|
|
10936
|
-
if (fieldIds.has(field.id)) {
|
|
10937
|
-
result.errors.push(
|
|
10938
|
-
this.createError(
|
|
10939
|
-
"DUPLICATE_SINGLETON_FIELD_ID",
|
|
10940
|
-
`Duplicate field ID '${field.id}' in singleton '${singletonId}'`,
|
|
10941
|
-
fieldPath,
|
|
10942
|
-
"error",
|
|
10943
|
-
"Use unique field IDs within each singleton",
|
|
10944
|
-
true
|
|
10945
|
-
)
|
|
10946
|
-
);
|
|
10947
|
-
} else {
|
|
10948
|
-
fieldIds.add(field.id);
|
|
10949
|
-
}
|
|
10950
|
-
}
|
|
10951
10207
|
this.validateSingletonFieldType(field, fieldPath, result, stats, singletonId);
|
|
10952
10208
|
if (isFieldLocalized(field)) {
|
|
10953
10209
|
hasLocalizationEnabled = true;
|
|
@@ -10993,20 +10249,6 @@ var init_dist2 = __esm({
|
|
|
10993
10249
|
);
|
|
10994
10250
|
stats.singletonsWithSlugFields++;
|
|
10995
10251
|
}
|
|
10996
|
-
if (field.type === "reference") {
|
|
10997
|
-
const config = field.config || {};
|
|
10998
|
-
if (config.maxItems && config.maxItems > 10) {
|
|
10999
|
-
result.info.push(
|
|
11000
|
-
this.createError(
|
|
11001
|
-
"LARGE_REFERENCE_LIST_IN_SINGLETON",
|
|
11002
|
-
`Singleton field '${field.id}' allows ${config.maxItems} references`,
|
|
11003
|
-
fieldPath,
|
|
11004
|
-
"info",
|
|
11005
|
-
"Consider if a large reference list is appropriate for singleton content, or if this should be a regular content type"
|
|
11006
|
-
)
|
|
11007
|
-
);
|
|
11008
|
-
}
|
|
11009
|
-
}
|
|
11010
10252
|
const problematicFieldNames = ["title", "name", "identifier", "key", "index"];
|
|
11011
10253
|
if (field.id && problematicFieldNames.some((name) => field.id.toLowerCase().includes(name))) {
|
|
11012
10254
|
result.info.push(
|
|
@@ -11317,18 +10559,6 @@ var init_dist2 = __esm({
|
|
|
11317
10559
|
}
|
|
11318
10560
|
validateStructure(assetTypeId, assetType, result) {
|
|
11319
10561
|
const path25 = `assetTypes.${assetTypeId}`;
|
|
11320
|
-
if (!ValidationUtils.isValidName(assetTypeId)) {
|
|
11321
|
-
result.errors.push(
|
|
11322
|
-
this.createError(
|
|
11323
|
-
"INVALID_ASSET_TYPE_ID",
|
|
11324
|
-
`Asset type ID '${assetTypeId}' is invalid`,
|
|
11325
|
-
path25,
|
|
11326
|
-
"error",
|
|
11327
|
-
"Use camelCase or snake_case starting with a letter",
|
|
11328
|
-
true
|
|
11329
|
-
)
|
|
11330
|
-
);
|
|
11331
|
-
}
|
|
11332
10562
|
if (ValidationUtils.getReservedKeywords().includes(assetTypeId.toLowerCase())) {
|
|
11333
10563
|
result.errors.push(
|
|
11334
10564
|
this.createError(
|
|
@@ -11341,7 +10571,7 @@ var init_dist2 = __esm({
|
|
|
11341
10571
|
)
|
|
11342
10572
|
);
|
|
11343
10573
|
}
|
|
11344
|
-
if (!assetType.displayName
|
|
10574
|
+
if (!assetType.displayName) {
|
|
11345
10575
|
result.errors.push(
|
|
11346
10576
|
this.createError(
|
|
11347
10577
|
"MISSING_ASSET_TYPE_DISPLAY_NAME",
|
|
@@ -11353,48 +10583,12 @@ var init_dist2 = __esm({
|
|
|
11353
10583
|
)
|
|
11354
10584
|
);
|
|
11355
10585
|
}
|
|
11356
|
-
if (assetType.displayField) {
|
|
11357
|
-
const exists = this.getAllFields(assetType).some((f) => f.id === assetType.displayField);
|
|
11358
|
-
if (!exists) {
|
|
11359
|
-
result.errors.push(
|
|
11360
|
-
this.createError(
|
|
11361
|
-
"INVALID_ASSET_TYPE_DISPLAY_FIELD",
|
|
11362
|
-
`Asset type '${assetTypeId}' displayField '${assetType.displayField}' does not exist`,
|
|
11363
|
-
`${path25}.displayField`,
|
|
11364
|
-
"error",
|
|
11365
|
-
"Reference an existing field id",
|
|
11366
|
-
true
|
|
11367
|
-
)
|
|
11368
|
-
);
|
|
11369
|
-
}
|
|
11370
|
-
}
|
|
11371
10586
|
}
|
|
11372
10587
|
validateFields(assetTypeId, assetType, result, componentIds) {
|
|
11373
10588
|
const path25 = `assetTypes.${assetTypeId}`;
|
|
11374
10589
|
const fields = this.getAllFields(assetType);
|
|
11375
|
-
const fieldIds = /* @__PURE__ */ new Set();
|
|
11376
10590
|
for (const field of fields) {
|
|
11377
|
-
const fieldPath = `${path25}.fields.${field.id
|
|
11378
|
-
if (!field.id) {
|
|
11379
|
-
result.errors.push(
|
|
11380
|
-
this.createError("MISSING_FIELD_ID", "Field must have an id", `${fieldPath}.id`, "error")
|
|
11381
|
-
);
|
|
11382
|
-
continue;
|
|
11383
|
-
}
|
|
11384
|
-
if (fieldIds.has(field.id)) {
|
|
11385
|
-
result.errors.push(
|
|
11386
|
-
this.createError(
|
|
11387
|
-
"DUPLICATE_ASSET_TYPE_FIELD_ID",
|
|
11388
|
-
`Duplicate field ID '${field.id}' in asset type '${assetTypeId}'`,
|
|
11389
|
-
`${fieldPath}.id`,
|
|
11390
|
-
"error",
|
|
11391
|
-
"Use unique field IDs within each asset type",
|
|
11392
|
-
true
|
|
11393
|
-
)
|
|
11394
|
-
);
|
|
11395
|
-
} else {
|
|
11396
|
-
fieldIds.add(field.id);
|
|
11397
|
-
}
|
|
10591
|
+
const fieldPath = `${path25}.fields.${field.id}`;
|
|
11398
10592
|
if (field.type && FORBIDDEN_TYPES.has(field.type)) {
|
|
11399
10593
|
result.errors.push(
|
|
11400
10594
|
this.createError(
|
|
@@ -11454,33 +10648,6 @@ var init_dist2 = __esm({
|
|
|
11454
10648
|
}
|
|
11455
10649
|
validateKind(assetTypeId, assetType, result, schemaLocales, stats) {
|
|
11456
10650
|
const path25 = `assetTypes.${assetTypeId}`;
|
|
11457
|
-
const presentKinds = ASSET_KINDS.filter((k) => assetType[k] !== void 0);
|
|
11458
|
-
if (presentKinds.length === 0) {
|
|
11459
|
-
result.errors.push(
|
|
11460
|
-
this.createError(
|
|
11461
|
-
"MISSING_ASSET_KIND",
|
|
11462
|
-
`Asset type '${assetTypeId}' must declare exactly one kind key (image, video, or file)`,
|
|
11463
|
-
path25,
|
|
11464
|
-
"error",
|
|
11465
|
-
"Add one of image, video, or file",
|
|
11466
|
-
true
|
|
11467
|
-
)
|
|
11468
|
-
);
|
|
11469
|
-
return;
|
|
11470
|
-
}
|
|
11471
|
-
if (presentKinds.length > 1) {
|
|
11472
|
-
result.errors.push(
|
|
11473
|
-
this.createError(
|
|
11474
|
-
"MULTIPLE_ASSET_KINDS",
|
|
11475
|
-
`Asset type '${assetTypeId}' declares multiple kind keys (${presentKinds.join(", ")}). Use exactly one.`,
|
|
11476
|
-
path25,
|
|
11477
|
-
"error",
|
|
11478
|
-
"Keep only one of image, video, or file",
|
|
11479
|
-
true
|
|
11480
|
-
)
|
|
11481
|
-
);
|
|
11482
|
-
return;
|
|
11483
|
-
}
|
|
11484
10651
|
const resolved = resolveAssetType(assetType);
|
|
11485
10652
|
if (!resolved) return;
|
|
11486
10653
|
const kind = resolved.kind;
|
|
@@ -11636,20 +10803,7 @@ var init_dist2 = __esm({
|
|
|
11636
10803
|
validateTransformLimits(path25, transform, result) {
|
|
11637
10804
|
const width = transform.width;
|
|
11638
10805
|
const height = transform.height;
|
|
11639
|
-
|
|
11640
|
-
if (format2 === "heic") {
|
|
11641
|
-
result.errors.push(
|
|
11642
|
-
this.createError(
|
|
11643
|
-
"INVALID_OUTPUT_FORMAT_HEIC",
|
|
11644
|
-
`Output format 'heic' is not supported; HEIC is a decodable input only. Use avif/webp/jpeg/png.`,
|
|
11645
|
-
`${path25}.format`,
|
|
11646
|
-
"error",
|
|
11647
|
-
"Choose a web-safe output format",
|
|
11648
|
-
true
|
|
11649
|
-
)
|
|
11650
|
-
);
|
|
11651
|
-
format2 = void 0;
|
|
11652
|
-
}
|
|
10806
|
+
const format2 = transform.format;
|
|
11653
10807
|
const maxDim = format2 === "avif" ? CF_IMAGES_LIMITS.maxDimensionAvifPx : CF_IMAGES_LIMITS.maxDimensionPx;
|
|
11654
10808
|
if (width && width > maxDim) {
|
|
11655
10809
|
result.errors.push(
|
|
@@ -11689,24 +10843,8 @@ var init_dist2 = __esm({
|
|
|
11689
10843
|
}
|
|
11690
10844
|
}
|
|
11691
10845
|
validateVideoKind(assetTypeId, kindPath, kindConfig, schemaLocales, result) {
|
|
11692
|
-
const poster = kindConfig.poster;
|
|
11693
10846
|
const captions = kindConfig.captions;
|
|
11694
10847
|
const watermark = kindConfig.watermark;
|
|
11695
|
-
if (poster && typeof poster.defaultTimestampPct === "number") {
|
|
11696
|
-
const pct = poster.defaultTimestampPct;
|
|
11697
|
-
if (pct < 0 || pct > 1) {
|
|
11698
|
-
result.errors.push(
|
|
11699
|
-
this.createError(
|
|
11700
|
-
"INVALID_POSTER_TIMESTAMP",
|
|
11701
|
-
`video.poster.defaultTimestampPct must be between 0.0 and 1.0 (got ${pct})`,
|
|
11702
|
-
`${kindPath}.poster.defaultTimestampPct`,
|
|
11703
|
-
"error",
|
|
11704
|
-
"Use a value between 0.0 and 1.0",
|
|
11705
|
-
true
|
|
11706
|
-
)
|
|
11707
|
-
);
|
|
11708
|
-
}
|
|
11709
|
-
}
|
|
11710
10848
|
if (captions?.requiredLocales && Array.isArray(captions.requiredLocales)) {
|
|
11711
10849
|
for (const locale of captions.requiredLocales) {
|
|
11712
10850
|
if (!schemaLocales.has(locale)) {
|
|
@@ -14476,30 +13614,6 @@ var init_dist2 = __esm({
|
|
|
14476
13614
|
);
|
|
14477
13615
|
}
|
|
14478
13616
|
}
|
|
14479
|
-
if (config.maxItems !== void 0 && (!Number.isInteger(config.maxItems) || config.maxItems <= 0)) {
|
|
14480
|
-
result.errors.push(
|
|
14481
|
-
this.createError(
|
|
14482
|
-
"INVALID_MAX_ITEMS",
|
|
14483
|
-
`Field '${field.id}' has invalid maxItems: ${config.maxItems}`,
|
|
14484
|
-
`${path25}.config.maxItems`,
|
|
14485
|
-
"error",
|
|
14486
|
-
"maxItems must be a positive integer",
|
|
14487
|
-
true
|
|
14488
|
-
)
|
|
14489
|
-
);
|
|
14490
|
-
}
|
|
14491
|
-
if (config.minItems !== void 0 && config.maxItems !== void 0 && config.minItems > config.maxItems) {
|
|
14492
|
-
result.errors.push(
|
|
14493
|
-
this.createError(
|
|
14494
|
-
"INVALID_ITEMS_RANGE",
|
|
14495
|
-
`Field '${field.id}' has minItems greater than maxItems`,
|
|
14496
|
-
`${path25}.config`,
|
|
14497
|
-
"error",
|
|
14498
|
-
"Ensure minItems \u2264 maxItems",
|
|
14499
|
-
true
|
|
14500
|
-
)
|
|
14501
|
-
);
|
|
14502
|
-
}
|
|
14503
13617
|
}
|
|
14504
13618
|
validateRichTextFieldIntegrity(field, path25, result, index) {
|
|
14505
13619
|
const config = field.config || {};
|
|
@@ -14535,22 +13649,6 @@ var init_dist2 = __esm({
|
|
|
14535
13649
|
);
|
|
14536
13650
|
}
|
|
14537
13651
|
}
|
|
14538
|
-
if (config.allowedBlocks && Array.isArray(config.allowedBlocks)) {
|
|
14539
|
-
const validBlocks = ["paragraph", "heading", "list", "quote", "code", "divider", "table"];
|
|
14540
|
-
for (const [index2, block] of config.allowedBlocks.entries()) {
|
|
14541
|
-
if (!validBlocks.includes(block)) {
|
|
14542
|
-
result.warnings.push(
|
|
14543
|
-
this.createError(
|
|
14544
|
-
"UNKNOWN_RICH_TEXT_BLOCK",
|
|
14545
|
-
`Rich text field '${field.id}' allows unknown block type '${block}'`,
|
|
14546
|
-
`${path25}.config.allowedBlocks[${index2}]`,
|
|
14547
|
-
"warning",
|
|
14548
|
-
`Use standard block types: ${validBlocks.join(", ")}`
|
|
14549
|
-
)
|
|
14550
|
-
);
|
|
14551
|
-
}
|
|
14552
|
-
}
|
|
14553
|
-
}
|
|
14554
13652
|
}
|
|
14555
13653
|
validateEnumFieldIntegrity(field, path25, result) {
|
|
14556
13654
|
const config = field.config || {};
|
|
@@ -14646,35 +13744,18 @@ var init_dist2 = __esm({
|
|
|
14646
13744
|
this.validateRequiredFieldDistribution(index, result);
|
|
14647
13745
|
}
|
|
14648
13746
|
validateRuleDependencies(rule, rulePath, context, result) {
|
|
14649
|
-
const
|
|
14650
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
)
|
|
14662
|
-
);
|
|
14663
|
-
}
|
|
14664
|
-
if (condition.field && condition.operator) {
|
|
14665
|
-
const referencedField = this.findFieldInContext(condition.field, context);
|
|
14666
|
-
if (referencedField && !this.isCompatibleComparator(condition.operator, referencedField.type)) {
|
|
14667
|
-
result.warnings.push(
|
|
14668
|
-
this.createError(
|
|
14669
|
-
"INCOMPATIBLE_RULE_OPERATOR",
|
|
14670
|
-
`Operator '${condition.operator}' may not be compatible with field type '${referencedField.type}'`,
|
|
14671
|
-
`${rulePath}.conditions.list[${condIndex}].operator`,
|
|
14672
|
-
"warning",
|
|
14673
|
-
"Verify that the operator is appropriate for the field type"
|
|
14674
|
-
)
|
|
14675
|
-
);
|
|
14676
|
-
}
|
|
14677
|
-
}
|
|
13747
|
+
for (const [condIndex, condition] of rule.conditions.conditions.entries()) {
|
|
13748
|
+
if (condition.field && !this.fieldExistsInContext(condition.field, context)) {
|
|
13749
|
+
result.errors.push(
|
|
13750
|
+
this.createError(
|
|
13751
|
+
"CONDITION_REFERENCES_NONEXISTENT_FIELD",
|
|
13752
|
+
`Rule condition references non-existent field '${condition.field}'`,
|
|
13753
|
+
`${rulePath}.conditions.conditions[${condIndex}].field`,
|
|
13754
|
+
"error",
|
|
13755
|
+
"Reference only existing fields in conditions",
|
|
13756
|
+
true
|
|
13757
|
+
)
|
|
13758
|
+
);
|
|
14678
13759
|
}
|
|
14679
13760
|
}
|
|
14680
13761
|
}
|
|
@@ -14866,11 +13947,11 @@ var init_dist2 = __esm({
|
|
|
14866
13947
|
validateComponentIntegrity(index, result) {
|
|
14867
13948
|
for (const [componentId, component] of index.components.entries) {
|
|
14868
13949
|
const componentPath = `components.${componentId}`;
|
|
14869
|
-
if (
|
|
13950
|
+
if (component.fields.length < 2) {
|
|
14870
13951
|
result.warnings.push(
|
|
14871
13952
|
this.createError(
|
|
14872
13953
|
"COMPONENT_TOO_SIMPLE",
|
|
14873
|
-
`Component '${componentId}' has only ${component.fields
|
|
13954
|
+
`Component '${componentId}' has only ${component.fields.length} field(s)`,
|
|
14874
13955
|
componentPath,
|
|
14875
13956
|
"warning",
|
|
14876
13957
|
"Components should group multiple related fields to justify reusability"
|
|
@@ -15110,14 +14191,6 @@ var init_dist2 = __esm({
|
|
|
15110
14191
|
}
|
|
15111
14192
|
return null;
|
|
15112
14193
|
}
|
|
15113
|
-
isCompatibleComparator(comparator, fieldType) {
|
|
15114
|
-
const numericComparators = ["greaterThan", "lessThan"];
|
|
15115
|
-
const numericTypes = ["integer", "decimal"];
|
|
15116
|
-
if (numericComparators.includes(comparator) && !numericTypes.includes(fieldType)) {
|
|
15117
|
-
return false;
|
|
15118
|
-
}
|
|
15119
|
-
return true;
|
|
15120
|
-
}
|
|
15121
14194
|
getAllFields(contentType) {
|
|
15122
14195
|
const fields = [];
|
|
15123
14196
|
if (contentType.fields) {
|
|
@@ -15240,18 +14313,6 @@ var init_dist2 = __esm({
|
|
|
15240
14313
|
validateRoleStructure(role, rolePath, result, stats) {
|
|
15241
14314
|
if (role.baseRole) {
|
|
15242
14315
|
stats.rolesWithBaseRole++;
|
|
15243
|
-
if (!isBuiltInRole(role.baseRole)) {
|
|
15244
|
-
result.errors.push(
|
|
15245
|
-
this.createError(
|
|
15246
|
-
"INVALID_BASE_ROLE",
|
|
15247
|
-
`Role '${role.id}' has invalid baseRole '${role.baseRole}'`,
|
|
15248
|
-
`${rolePath}.baseRole`,
|
|
15249
|
-
"error",
|
|
15250
|
-
`Valid base roles are: ${BUILT_IN_ROLES.join(", ")}`,
|
|
15251
|
-
true
|
|
15252
|
-
)
|
|
15253
|
-
);
|
|
15254
|
-
}
|
|
15255
14316
|
}
|
|
15256
14317
|
if (role.includes && role.includes.length > 0) {
|
|
15257
14318
|
stats.rolesWithIncludes++;
|
|
@@ -15259,17 +14320,6 @@ var init_dist2 = __esm({
|
|
|
15259
14320
|
if (role.permissions && role.permissions.length > 0) {
|
|
15260
14321
|
stats.rolesWithExplicitPermissions++;
|
|
15261
14322
|
}
|
|
15262
|
-
if (role.displayName.length > 128) {
|
|
15263
|
-
result.warnings.push(
|
|
15264
|
-
this.createError(
|
|
15265
|
-
"LONG_ROLE_DISPLAY_NAME",
|
|
15266
|
-
`Role '${role.id}' has a very long displayName (${role.displayName.length} chars)`,
|
|
15267
|
-
`${rolePath}.displayName`,
|
|
15268
|
-
"warning",
|
|
15269
|
-
"Consider using a shorter display name for better UI presentation"
|
|
15270
|
-
)
|
|
15271
|
-
);
|
|
15272
|
-
}
|
|
15273
14323
|
if (!role.description) {
|
|
15274
14324
|
result.info.push(
|
|
15275
14325
|
this.createError(
|
|
@@ -15346,21 +14396,6 @@ var init_dist2 = __esm({
|
|
|
15346
14396
|
}
|
|
15347
14397
|
for (const [permIndex, permission] of role.permissions.entries()) {
|
|
15348
14398
|
const permPath = `${rolePath}.permissions[${permIndex}]`;
|
|
15349
|
-
for (const [actionIndex, action] of permission.actions.entries()) {
|
|
15350
|
-
if (!ROLE_ACTIONS.includes(action)) {
|
|
15351
|
-
const suggestion = ValidationUtils.findBestMatch(action, [...ROLE_ACTIONS]);
|
|
15352
|
-
result.errors.push(
|
|
15353
|
-
this.createError(
|
|
15354
|
-
"INVALID_ROLE_ACTION",
|
|
15355
|
-
`Role '${role.id}' has invalid action '${action}'`,
|
|
15356
|
-
`${permPath}.actions[${actionIndex}]`,
|
|
15357
|
-
"error",
|
|
15358
|
-
suggestion ? `Did you mean '${suggestion}'? Valid actions: ${ROLE_ACTIONS.join(", ")}` : `Valid actions are: ${ROLE_ACTIONS.join(", ")}`,
|
|
15359
|
-
true
|
|
15360
|
-
)
|
|
15361
|
-
);
|
|
15362
|
-
}
|
|
15363
|
-
}
|
|
15364
14399
|
for (const [tagIndex, tag] of permission.tags.entries()) {
|
|
15365
14400
|
stats.totalAccessTagsUsed.add(tag);
|
|
15366
14401
|
if (!definedAccessTags.has(tag)) {
|
|
@@ -15565,7 +14600,7 @@ var init_dist2 = __esm({
|
|
|
15565
14600
|
}
|
|
15566
14601
|
};
|
|
15567
14602
|
EVOLUTION_VALIDATOR_KEY = "evolution";
|
|
15568
|
-
CROSS_VERSION_CHECKS_SKIPPED = Object.entries(CROSS_VERSION_CHECKS).map(([code, check]) => `${check} (${code})`).join(", ");
|
|
14603
|
+
CROSS_VERSION_CHECKS_SKIPPED = Object.entries(CROSS_VERSION_CHECKS).map(([code, check]) => `${check.names} (${code})`).join(", ");
|
|
15569
14604
|
ValidationPipeline = class {
|
|
15570
14605
|
config;
|
|
15571
14606
|
validators = /* @__PURE__ */ new Map();
|
|
@@ -16796,7 +15831,7 @@ async function preview(options) {
|
|
|
16796
15831
|
return failed(extractApiError(error2, "Pre-deploy validation failed"));
|
|
16797
15832
|
}
|
|
16798
15833
|
const validationErrors = status.validationErrors ?? [];
|
|
16799
|
-
const validationWarnings = status.validationWarnings
|
|
15834
|
+
const validationWarnings = status.validationWarnings;
|
|
16800
15835
|
const gitCommitSha = getCurrentGitCommitSha() || void 0;
|
|
16801
15836
|
const previewData = {
|
|
16802
15837
|
branchName,
|
|
@@ -16889,7 +15924,8 @@ async function run(options) {
|
|
|
16889
15924
|
version: deployResult.version,
|
|
16890
15925
|
durationMs: Date.now() - start,
|
|
16891
15926
|
preview: previewData,
|
|
16892
|
-
verified
|
|
15927
|
+
verified,
|
|
15928
|
+
validationWarnings: deployResult.validationWarnings
|
|
16893
15929
|
};
|
|
16894
15930
|
}
|
|
16895
15931
|
async function verifyDeploy(branchId, projectRoot) {
|
|
@@ -18836,6 +17872,7 @@ async function runLocalVsRemote(options) {
|
|
|
18836
17872
|
hasChanges: status.hasChanges ?? false,
|
|
18837
17873
|
changes: { ...DEFAULT_CHANGES2, ...status.changes },
|
|
18838
17874
|
validationErrors: status.validationErrors ?? [],
|
|
17875
|
+
validationWarnings: status.validationWarnings,
|
|
18839
17876
|
localSchema: loaded.schema
|
|
18840
17877
|
};
|
|
18841
17878
|
}
|
|
@@ -22524,7 +21561,7 @@ var init_banner = __esm({
|
|
|
22524
21561
|
init_dev_cockpit_context();
|
|
22525
21562
|
init_dev_cockpit_format();
|
|
22526
21563
|
init_startup_info();
|
|
22527
|
-
CLI_VERSION2 = "0.
|
|
21564
|
+
CLI_VERSION2 = "0.5.0" ;
|
|
22528
21565
|
BRAND_GLYPH = "\u25B6";
|
|
22529
21566
|
BRAND_NAME = "RelyIO";
|
|
22530
21567
|
LABEL_WIDTH = 9;
|
|
@@ -30679,6 +29716,13 @@ function displayDeploySuccess(version, branchName) {
|
|
|
30679
29716
|
|
|
30680
29717
|
// src/utils/json-output.ts
|
|
30681
29718
|
init_change_buckets();
|
|
29719
|
+
function listIssues(issues) {
|
|
29720
|
+
return issues.map((issue) => ({
|
|
29721
|
+
path: issue.path,
|
|
29722
|
+
message: issue.message,
|
|
29723
|
+
...issue.code && { code: issue.code }
|
|
29724
|
+
}));
|
|
29725
|
+
}
|
|
30682
29726
|
function listBucket(bucket) {
|
|
30683
29727
|
return {
|
|
30684
29728
|
added: bucket.added,
|
|
@@ -30722,25 +29766,23 @@ function createStatusJsonOutput(params) {
|
|
|
30722
29766
|
complexity: statistics?.complexity
|
|
30723
29767
|
},
|
|
30724
29768
|
...failure && { error: failure },
|
|
30725
|
-
...validationErrors.length > 0 && {
|
|
30726
|
-
|
|
30727
|
-
path: e.path,
|
|
30728
|
-
message: e.message,
|
|
30729
|
-
...e.code && { code: e.code }
|
|
30730
|
-
}))
|
|
30731
|
-
},
|
|
30732
|
-
...validationWarnings.length > 0 && {
|
|
30733
|
-
warnings: validationWarnings.map((w) => ({
|
|
30734
|
-
path: w.path,
|
|
30735
|
-
message: w.message,
|
|
30736
|
-
...w.code && { code: w.code }
|
|
30737
|
-
}))
|
|
30738
|
-
},
|
|
29769
|
+
...validationErrors.length > 0 && { errors: listIssues(validationErrors) },
|
|
29770
|
+
...validationWarnings.length > 0 && { warnings: listIssues(validationWarnings) },
|
|
30739
29771
|
...divergence && { divergence }
|
|
30740
29772
|
};
|
|
30741
29773
|
}
|
|
30742
29774
|
function createDeployJsonOutput(params) {
|
|
30743
|
-
const {
|
|
29775
|
+
const {
|
|
29776
|
+
success: success2,
|
|
29777
|
+
branchName,
|
|
29778
|
+
branchId,
|
|
29779
|
+
version,
|
|
29780
|
+
changes,
|
|
29781
|
+
gitCommitSha,
|
|
29782
|
+
notes,
|
|
29783
|
+
validationWarnings,
|
|
29784
|
+
error: error2
|
|
29785
|
+
} = params;
|
|
30744
29786
|
return {
|
|
30745
29787
|
success: success2,
|
|
30746
29788
|
...version && { version, deployedAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
@@ -30754,6 +29796,7 @@ function createDeployJsonOutput(params) {
|
|
|
30754
29796
|
},
|
|
30755
29797
|
...gitCommitSha && { git: { commitSha: gitCommitSha } },
|
|
30756
29798
|
...notes && { notes },
|
|
29799
|
+
warnings: listIssues(validationWarnings),
|
|
30757
29800
|
...error2 && { error: error2 }
|
|
30758
29801
|
};
|
|
30759
29802
|
}
|
|
@@ -30787,7 +29830,8 @@ function createDiffJsonOutput(params) {
|
|
|
30787
29830
|
schemaSourcePath,
|
|
30788
29831
|
hasChanges,
|
|
30789
29832
|
changes,
|
|
30790
|
-
localSchema
|
|
29833
|
+
localSchema,
|
|
29834
|
+
validationWarnings
|
|
30791
29835
|
} = params;
|
|
30792
29836
|
const fieldCount = (key, name) => {
|
|
30793
29837
|
const section = localSchema?.[key];
|
|
@@ -30813,7 +29857,8 @@ function createDiffJsonOutput(params) {
|
|
|
30813
29857
|
deleted: bucket.deleted,
|
|
30814
29858
|
...bucket.enabled && { enabled: bucket.enabled }
|
|
30815
29859
|
})),
|
|
30816
|
-
summary: countChanges(changes)
|
|
29860
|
+
summary: countChanges(changes),
|
|
29861
|
+
warnings: listIssues(validationWarnings)
|
|
30817
29862
|
};
|
|
30818
29863
|
}
|
|
30819
29864
|
function countOf(count, noun) {
|
|
@@ -31265,10 +30310,16 @@ function nothingToDeploy(preview2) {
|
|
|
31265
30310
|
branchName: preview2.branchName,
|
|
31266
30311
|
branchId: preview2.branchId,
|
|
31267
30312
|
changes: preview2.changes,
|
|
31268
|
-
gitCommitSha: preview2.gitCommitSha
|
|
30313
|
+
gitCommitSha: preview2.gitCommitSha,
|
|
30314
|
+
validationWarnings: preview2.validationWarnings
|
|
31269
30315
|
})
|
|
31270
30316
|
);
|
|
31271
30317
|
}
|
|
30318
|
+
var issueKey = (issue) => JSON.stringify([issue.code, issue.path, issue.message]);
|
|
30319
|
+
function warningsNotShown(deployed, shown) {
|
|
30320
|
+
const seen = new Set(shown.map((warning2) => issueKey(warning2)));
|
|
30321
|
+
return deployed.filter((warning2) => !seen.has(issueKey(warning2)));
|
|
30322
|
+
}
|
|
31272
30323
|
async function handleDeploy(options) {
|
|
31273
30324
|
const { json = false } = options;
|
|
31274
30325
|
process.on("SIGINT", () => interrupted(json));
|
|
@@ -31379,24 +30430,26 @@ async function handleDeploy(options) {
|
|
|
31379
30430
|
displayInfo("Your schema is already up to date with the remote branch");
|
|
31380
30431
|
return;
|
|
31381
30432
|
}
|
|
31382
|
-
|
|
31383
|
-
|
|
31384
|
-
THEME.primary("\u2502 ") + THEME.muted(
|
|
31385
|
-
`Target: ${previewData.branchName} (${previewData.branchId.slice(0, 8)}...)`
|
|
31386
|
-
)
|
|
31387
|
-
);
|
|
31388
|
-
console.log(
|
|
31389
|
-
THEME.primary("\u2502 ") + THEME.muted(`Schema: ${formatSchemaSource(previewData)}`)
|
|
31390
|
-
);
|
|
31391
|
-
if (previewData.gitCommitSha) {
|
|
30433
|
+
if (!json) {
|
|
30434
|
+
displaySection("Deployment Preview", "sparkles");
|
|
31392
30435
|
console.log(
|
|
31393
|
-
THEME.primary("\u2502 ") + THEME.muted(
|
|
30436
|
+
THEME.primary("\u2502 ") + THEME.muted(
|
|
30437
|
+
`Target: ${previewData.branchName} (${previewData.branchId.slice(0, 8)}...)`
|
|
30438
|
+
)
|
|
31394
30439
|
);
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
30440
|
+
console.log(
|
|
30441
|
+
THEME.primary("\u2502 ") + THEME.muted(`Schema: ${formatSchemaSource(previewData)}`)
|
|
30442
|
+
);
|
|
30443
|
+
if (previewData.gitCommitSha) {
|
|
30444
|
+
console.log(
|
|
30445
|
+
THEME.primary("\u2502 ") + THEME.muted(`Git SHA: ${previewData.gitCommitSha.slice(0, 8)}...`)
|
|
30446
|
+
);
|
|
30447
|
+
}
|
|
30448
|
+
displaySectionEnd();
|
|
30449
|
+
displaySchemaChanges(previewData.changes);
|
|
30450
|
+
if (previewData.validationWarnings.length > 0) {
|
|
30451
|
+
console.log(formatValidationErrors(previewData.validationWarnings));
|
|
30452
|
+
}
|
|
31400
30453
|
}
|
|
31401
30454
|
let notes;
|
|
31402
30455
|
if (!json && !options.yes) {
|
|
@@ -31493,12 +30546,17 @@ async function handleDeploy(options) {
|
|
|
31493
30546
|
version: result.version,
|
|
31494
30547
|
changes: result.preview.changes,
|
|
31495
30548
|
gitCommitSha: result.preview.gitCommitSha,
|
|
31496
|
-
notes
|
|
30549
|
+
notes,
|
|
30550
|
+
validationWarnings: result.validationWarnings
|
|
31497
30551
|
})
|
|
31498
30552
|
);
|
|
31499
30553
|
}
|
|
31500
30554
|
deploySpinner?.succeed("Schema deployment completed successfully");
|
|
31501
30555
|
displayDeploySuccess(result.version, result.preview.branchName);
|
|
30556
|
+
const unseenWarnings = warningsNotShown(result.validationWarnings, previewData.validationWarnings);
|
|
30557
|
+
if (unseenWarnings.length > 0) {
|
|
30558
|
+
console.log(formatValidationErrors(unseenWarnings));
|
|
30559
|
+
}
|
|
31502
30560
|
console.log();
|
|
31503
30561
|
switch (result.verified) {
|
|
31504
30562
|
case "passed": {
|
|
@@ -32133,7 +31191,7 @@ function sandboxCommands(program2) {
|
|
|
32133
31191
|
}
|
|
32134
31192
|
|
|
32135
31193
|
// src/commands/version.ts
|
|
32136
|
-
var CLI_VERSION = "0.
|
|
31194
|
+
var CLI_VERSION = "0.5.0" ;
|
|
32137
31195
|
async function handleVersion(_options) {
|
|
32138
31196
|
console.log(heading("RelyIO CLI Version Information"));
|
|
32139
31197
|
const versionInfo = [
|
|
@@ -32504,7 +31562,7 @@ async function performStatusCheck(branchName, options) {
|
|
|
32504
31562
|
hasChanges: response.hasChanges ?? false,
|
|
32505
31563
|
...response.changes ?? defaultChanges,
|
|
32506
31564
|
validationErrors: response.validationErrors ?? [],
|
|
32507
|
-
validationWarnings: response.validationWarnings
|
|
31565
|
+
validationWarnings: response.validationWarnings,
|
|
32508
31566
|
recommendations: response.recommendations ?? [],
|
|
32509
31567
|
statistics: response.statistics,
|
|
32510
31568
|
complexityAnalysis: response.complexityAnalysis
|
|
@@ -33679,19 +32737,23 @@ async function handleDiff(options) {
|
|
|
33679
32737
|
schemaSourcePath: result.schemaSourcePath,
|
|
33680
32738
|
hasChanges: result.hasChanges,
|
|
33681
32739
|
changes: result.changes,
|
|
33682
|
-
localSchema: result.localSchema
|
|
32740
|
+
localSchema: result.localSchema,
|
|
32741
|
+
validationWarnings: result.validationWarnings
|
|
33683
32742
|
})
|
|
33684
32743
|
);
|
|
33685
32744
|
return;
|
|
33686
32745
|
}
|
|
33687
32746
|
displayDiffHeader(result.branchName, result.branchId);
|
|
33688
|
-
if (
|
|
32747
|
+
if (result.hasChanges) {
|
|
32748
|
+
displayDiffSummary(result.changes);
|
|
32749
|
+
displayDetailedDiff(result.changes, result.localSchema);
|
|
32750
|
+
} else {
|
|
33689
32751
|
console.log(THEME3.muted("No changes between local schema and remote branch"));
|
|
33690
32752
|
console.log();
|
|
33691
|
-
return;
|
|
33692
32753
|
}
|
|
33693
|
-
|
|
33694
|
-
|
|
32754
|
+
if (result.validationWarnings.length > 0) {
|
|
32755
|
+
console.log(formatValidationErrors(result.validationWarnings));
|
|
32756
|
+
}
|
|
33695
32757
|
return;
|
|
33696
32758
|
}
|
|
33697
32759
|
if (json) {
|
|
@@ -36403,7 +35465,7 @@ Examples:
|
|
|
36403
35465
|
}
|
|
36404
35466
|
|
|
36405
35467
|
// src/index.ts
|
|
36406
|
-
var CLI_VERSION3 = "0.
|
|
35468
|
+
var CLI_VERSION3 = "0.5.0" ;
|
|
36407
35469
|
var program = new Command();
|
|
36408
35470
|
program.name("relyio").description("RelyIO CLI - Content Management, Simplified").version(CLI_VERSION3);
|
|
36409
35471
|
registerGlobalOptions(program);
|