Fix collection schema import compatibility

Normalize portable field settings during export and import, serialize collection category association updates as arrays, and ignore generated exports and macOS metadata.
This commit is contained in:
Ethan
2026-08-05 12:08:11 +08:00
parent 48d1b4e443
commit 9dc20b03e5
3 changed files with 16 additions and 38 deletions
+1
View File
@@ -1 +1,2 @@
.DS_Store .DS_Store
exports/
+4 -1
View File
@@ -147,7 +147,10 @@ read_collection() {
portable_schema() { portable_schema() {
jq ' jq '
.data as $collection .data as $collection
| ($collection.fields // []) as $fields | (($collection.fields // []) | map(
. as $field
| (($field | del(.settings)) + ($field.settings // {}))
)) as $fields
| [$fields[] | [$fields[]
| select(.interface == "m2o" or .interface == "o2m" or .interface == "m2m" or .interface == "o2o") | select(.interface == "m2o" or .interface == "o2m" or .interface == "m2m" or .interface == "o2o")
| .foreignKey | .foreignKey
+11 -37
View File
@@ -321,24 +321,7 @@ make_collection_payload() {
jq --argjson index "$PLAN_INDEX" --argjson relations "$RELATION_INTERFACES" ' jq --argjson index "$PLAN_INDEX" --argjson relations "$RELATION_INTERFACES" '
def compact_field: def compact_field:
. as $field . as $field
| ({name:$field.name, interface:$field.interface} | (($field | del(.settings, .collectionName)) + ($field.settings // {}));
+ (if $field | has("title") then {title:$field.title} else {} end)
+ (if $field | has("description") then {description:$field.description} else {} end)
+ (if $field | has("target") then {target:$field.target} else {} end)
+ (if $field | has("validation") then {validation:$field.validation} else {} end)
+ (if $field | has("validators") then {validators:$field.validators} else {} end)
+ (if $field | has("defaultValue") then {defaultValue:$field.defaultValue} else {} end)
+ (if $field | has("enum") then {enum:$field.enum} else {} end)
+ (if $field | has("reverseName") then {reverseName:$field.reverseName} else {} end)
+ (if $field | has("reverseTitle") then {reverseTitle:$field.reverseTitle} else {} end)
+ (if $field | has("reverseInterface") then {reverseInterface:$field.reverseInterface} else {} end)
+ (if $field | has("reverseField") then {reverseField:$field.reverseField} else {} end))
+ (((($field.settings // {}) + ($field | del(
.name, .title, .interface, .description, .target, .validation, .validators,
.defaultValue, .enum, .reverseName, .reverseTitle, .reverseInterface,
.reverseField, .settings
))) as $settings
| if $settings == {} then {} else {settings:$settings} end));
.[$index].schema as $schema .[$index].schema as $schema
| ({name:$schema.name, title:$schema.title, template:$schema.template, verify:true, replaceFields:false} | ({name:$schema.name, title:$schema.title, template:$schema.template, verify:true, replaceFields:false}
+ (if $schema | has("description") then {description:$schema.description} else {} end) + (if $schema | has("description") then {description:$schema.description} else {} end)
@@ -363,24 +346,8 @@ make_relation_payload() {
jq --argjson planIndex "$PLAN_INDEX" --argjson fieldIndex "$FIELD_INDEX" ' jq --argjson planIndex "$PLAN_INDEX" --argjson fieldIndex "$FIELD_INDEX" '
.[$planIndex] as $item .[$planIndex] as $item
| $item.schema.fields[$fieldIndex] as $field | $item.schema.fields[$fieldIndex] as $field
| ({collectionName:$item.collection, name:$field.name, interface:$field.interface} | (($field | del(.settings, .collectionName)) + ($field.settings // {}))
+ (if $field | has("title") then {title:$field.title} else {} end) + {collectionName:$item.collection}
+ (if $field | has("description") then {description:$field.description} else {} end)
+ (if $field | has("target") then {target:$field.target} else {} end)
+ (if $field | has("validation") then {validation:$field.validation} else {} end)
+ (if $field | has("validators") then {validators:$field.validators} else {} end)
+ (if $field | has("defaultValue") then {defaultValue:$field.defaultValue} else {} end)
+ (if $field | has("enum") then {enum:$field.enum} else {} end)
+ (if $field | has("reverseName") then {reverseName:$field.reverseName} else {} end)
+ (if $field | has("reverseTitle") then {reverseTitle:$field.reverseTitle} else {} end)
+ (if $field | has("reverseInterface") then {reverseInterface:$field.reverseInterface} else {} end)
+ (if $field | has("reverseField") then {reverseField:$field.reverseField} else {} end))
+ (((($field.settings // {}) + ($field | del(
.collectionName, .name, .title, .interface, .description, .target,
.validation, .validators, .defaultValue, .enum, .reverseName,
.reverseTitle, .reverseInterface, .reverseField, .settings
))) as $settings
| if $settings == {} then {} else {settings:$settings} end))
' "$PLAN_FILE" ' "$PLAN_FILE"
} }
@@ -456,11 +423,15 @@ while [ "$CATEGORY_INDEX" -lt "$TARGET_CATEGORY_COUNT" ]; do
if [ "$CURRENT_MEMBERS" != "$DESIRED_MEMBERS" ]; then if [ "$CURRENT_MEMBERS" != "$DESIRED_MEMBERS" ]; then
CATEGORY_VALUES=$(printf '%s' "$DESIRED_MEMBERS" | jq -c '{collections:map({name:.})}') CATEGORY_VALUES=$(printf '%s' "$DESIRED_MEMBERS" | jq -c '{collections:map({name:.})}')
echo " update category $CATEGORY_NAME" >&2 echo " update category $CATEGORY_NAME" >&2
# Repeat the single association flag so nb CLI serializes it as an array.
# A single query value is parsed by NocoBase as a string and causes
# UpdateGuard to fail with "list.filter is not a function".
run_nb nb api resource update \ run_nb nb api resource update \
--resource collectionCategories \ --resource collectionCategories \
--filter-by-tk "$CATEGORY_ID" \ --filter-by-tk "$CATEGORY_ID" \
--values "$CATEGORY_VALUES" \ --values "$CATEGORY_VALUES" \
--update-association-values collections \ --update-association-values collections \
--update-association-values collections \
-e "$ENV_NAME" -y -j >/dev/null -e "$ENV_NAME" -y -j >/dev/null
fi fi
CATEGORY_INDEX=$((CATEGORY_INDEX + 1)) CATEGORY_INDEX=$((CATEGORY_INDEX + 1))
@@ -469,7 +440,10 @@ done
portable_schema() { portable_schema() {
jq ' jq '
.data as $collection .data as $collection
| ($collection.fields // []) as $fields | (($collection.fields // []) | map(
. as $field
| (($field | del(.settings)) + ($field.settings // {}))
)) as $fields
| [$fields[] | [$fields[]
| select(.interface == "m2o" or .interface == "o2m" or .interface == "m2m" or .interface == "o2o") | select(.interface == "m2o" or .interface == "o2m" or .interface == "m2m" or .interface == "o2o")
| .foreignKey | .foreignKey