wcc-contentful 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +51 -0
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.rubocop.yml +240 -0
- data/.rubocop_todo.yml +13 -0
- data/CHANGELOG.md +7 -1
- data/Gemfile +4 -2
- data/Guardfile +36 -0
- data/README.md +1 -1
- data/Rakefile +5 -3
- data/bin/rspec +3 -0
- data/lib/generators/wcc/USAGE +24 -0
- data/lib/generators/wcc/menu_generator.rb +67 -0
- data/lib/generators/wcc/templates/.keep +0 -0
- data/lib/generators/wcc/templates/Procfile +3 -0
- data/lib/generators/wcc/templates/contentful_shell_wrapper +342 -0
- data/lib/generators/wcc/templates/menu/generated_add_menus.ts +85 -0
- data/lib/generators/wcc/templates/menu/menu.rb +25 -0
- data/lib/generators/wcc/templates/menu/menu_button.rb +25 -0
- data/lib/generators/wcc/templates/release +9 -0
- data/lib/generators/wcc/templates/wcc_contentful.rb +18 -0
- data/lib/wcc/contentful.rb +93 -26
- data/lib/wcc/contentful/client_ext.rb +15 -0
- data/lib/wcc/contentful/configuration.rb +93 -0
- data/lib/wcc/contentful/content_type_indexer.rb +153 -0
- data/lib/wcc/contentful/exceptions.rb +34 -0
- data/lib/wcc/contentful/graphql.rb +15 -0
- data/lib/wcc/contentful/graphql/builder.rb +172 -0
- data/lib/wcc/contentful/graphql/types.rb +54 -0
- data/lib/wcc/contentful/helpers.rb +28 -0
- data/lib/wcc/contentful/indexed_representation.rb +111 -0
- data/lib/wcc/contentful/model.rb +24 -0
- data/lib/wcc/contentful/model/menu.rb +7 -0
- data/lib/wcc/contentful/model/menu_button.rb +15 -0
- data/lib/wcc/contentful/model_builder.rb +151 -0
- data/lib/wcc/contentful/model_validators.rb +64 -0
- data/lib/wcc/contentful/model_validators/dsl.rb +165 -0
- data/lib/wcc/contentful/simple_client.rb +127 -0
- data/lib/wcc/contentful/simple_client/response.rb +160 -0
- data/lib/wcc/contentful/store.rb +8 -0
- data/lib/wcc/contentful/store/cdn_adapter.rb +79 -0
- data/lib/wcc/contentful/store/memory_store.rb +75 -0
- data/lib/wcc/contentful/store/postgres_store.rb +132 -0
- data/lib/wcc/contentful/version.rb +3 -1
- data/wcc-contentful.gemspec +49 -24
- metadata +261 -16
- data/lib/wcc/contentful/redirect.rb +0 -33
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wcc
|
4
|
+
class MenuGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
6
|
+
|
7
|
+
def create_menus_migration
|
8
|
+
now = Time.now.strftime('%Y%m%d%H%M')
|
9
|
+
copy_file 'menu/generated_add_menus.ts',
|
10
|
+
"db/migrate/#{now}01_generated_add_menus.ts"
|
11
|
+
end
|
12
|
+
|
13
|
+
def ensure_migration_tools_installed
|
14
|
+
in_root do
|
15
|
+
run 'npm init -y' unless File.exist?('package.json')
|
16
|
+
package = JSON.parse(File.read('package.json'))
|
17
|
+
deps = package['dependencies']
|
18
|
+
|
19
|
+
unless deps.try(:[], 'contentful-migration-cli').present?
|
20
|
+
run 'npm install --save watermarkchurch/migration-cli'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def ensure_wrapper_script_in_bin_dir
|
26
|
+
unless inside('bin') { File.exist?('contentful') }
|
27
|
+
copy_file 'contentful_shell_wrapper', 'bin/contentful'
|
28
|
+
end
|
29
|
+
|
30
|
+
if inside('bin') { File.exist?('release') }
|
31
|
+
release = inside('bin') { File.read('release') }
|
32
|
+
unless release.include?('contentful migrate')
|
33
|
+
insert_into_file('bin/release', after: 'bundle exec rake db:migrate') do
|
34
|
+
<<~HEREDOC
|
35
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
36
|
+
$DIR/contentful migrate -y
|
37
|
+
HEREDOC
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
copy_file 'release', 'bin/release'
|
42
|
+
end
|
43
|
+
|
44
|
+
if in_root { File.exist?('Procfile') }
|
45
|
+
procfile = in_root { File.read('Procfile') }
|
46
|
+
unless procfile.include?('release:')
|
47
|
+
insert_into_file('Procfile') do
|
48
|
+
'release: bin/release'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
copy_file 'Procfile'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def ensure_initializer_exists
|
57
|
+
return if inside('config/initializers') { File.exist?('wcc_contentful.rb') }
|
58
|
+
|
59
|
+
copy_file 'wcc_contentful.rb', 'config/initializers/wcc_contentful.rb'
|
60
|
+
end
|
61
|
+
|
62
|
+
def drop_model_overrides_in_lib_dir
|
63
|
+
copy_file 'menu/menu.rb', 'lib/wcc/contentful/model/menu.rb'
|
64
|
+
copy_file 'menu/menu_button.rb', 'lib/wcc/contentful/model/menu_button.rb'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
File without changes
|
@@ -0,0 +1,342 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
COLOR_NC='\033[0m' # No Color
|
4
|
+
COLOR_GRAY='\033[1;30m'
|
5
|
+
COLOR_RED='\033[0;31m'
|
6
|
+
COLOR_LCYAN='\033[1;36m'
|
7
|
+
COLOR_YELLOW='\033[1;33m'
|
8
|
+
COLOR_LGREEN='\033[1;32m'
|
9
|
+
|
10
|
+
logv() {
|
11
|
+
([[ ! -z "$VERBOSE" ]] && >&2 echo -e "${COLOR_GRAY}$@${COLOR_NC}") || true
|
12
|
+
}
|
13
|
+
|
14
|
+
logerr() {
|
15
|
+
>&2 echo -e "${COLOR_RED}$@${COLOR_NC}"
|
16
|
+
}
|
17
|
+
|
18
|
+
## *** Argument Parsing & validation ***
|
19
|
+
|
20
|
+
usage() {
|
21
|
+
echo "$0 <command> [opts]
|
22
|
+
Commands:
|
23
|
+
migrate [dir|file]
|
24
|
+
runs pending migration files in the given directory
|
25
|
+
* [dir|file] optional - Default: db/migrate
|
26
|
+
|
27
|
+
setup [file]
|
28
|
+
initializes a space with bare-minimum schema and seeds
|
29
|
+
* [file] optional - default: db/contentful-schema.json
|
30
|
+
|
31
|
+
backup [file]
|
32
|
+
downloads a backup of the current space to the given file
|
33
|
+
* [file] optional - default: timestamped file in current directory
|
34
|
+
|
35
|
+
clean [no-init]
|
36
|
+
Deletes all data in a given space and optionally sets it up again
|
37
|
+
using 'bin/contentful setup'.
|
38
|
+
* [no-init] optional - Skips the 'setup' step at the end.
|
39
|
+
|
40
|
+
restore [file]
|
41
|
+
restores a given backup file into the current space
|
42
|
+
* [file] optional - default: the most recent backup file in the current directory
|
43
|
+
|
44
|
+
restore_from -s [to space ID] <from space ID>
|
45
|
+
restores all data from the given space into the current space
|
46
|
+
* <space ID> required - the ID of the space to receive data from
|
47
|
+
* -s [to space ID] optional - the current working space. Default: \$CONTENTFUL_SPACE_ID
|
48
|
+
|
49
|
+
generate [name]
|
50
|
+
Creates a sample migration in the db/migrate directory
|
51
|
+
* [name] optional - default: 'contentful_migration'
|
52
|
+
|
53
|
+
Flags:" && \
|
54
|
+
grep " .)\ #" $0
|
55
|
+
echo "
|
56
|
+
Examples:" && \
|
57
|
+
grep -i "#\ example:" $0 | awk '{$1=""; $2=""; print " "$0}'
|
58
|
+
}
|
59
|
+
|
60
|
+
parse_args() {
|
61
|
+
OPTIND=1
|
62
|
+
local s=$(echo "$1" | tr '[:upper:]' '[:lower:]')
|
63
|
+
case "$s" in
|
64
|
+
migrate|setup|backup|export|restore|restore_from|import|generate|clean|help|h|\?)
|
65
|
+
export subcommand=$s
|
66
|
+
OPTIND=2
|
67
|
+
;;
|
68
|
+
esac
|
69
|
+
|
70
|
+
# Parse flags
|
71
|
+
while getopts ":hyvs:a:" arg; do
|
72
|
+
case $arg in
|
73
|
+
y) # Yes - skip prompts
|
74
|
+
export YES="-y"
|
75
|
+
;;
|
76
|
+
s) # Contentful Space ID - overrides env var CONTENTFUL_SPACE_ID
|
77
|
+
export CONTENTFUL_SPACE_ID=$OPTARG
|
78
|
+
;;
|
79
|
+
a) # Contentful Mgmt Token - overrides env var CONTENTFUL_MANAGEMENT_TOKEN
|
80
|
+
export CONTENTFUL_MANAGEMENT_TOKEN=$OPTARG
|
81
|
+
;;
|
82
|
+
v) # Verbose mode - extra output
|
83
|
+
export VERBOSE=true
|
84
|
+
;;
|
85
|
+
h) # Display help.
|
86
|
+
usage
|
87
|
+
exit 0
|
88
|
+
;;
|
89
|
+
*)
|
90
|
+
logerr "Unknown option: '$OPTARG'"
|
91
|
+
usage
|
92
|
+
exit -1
|
93
|
+
;;
|
94
|
+
esac
|
95
|
+
done
|
96
|
+
|
97
|
+
export OPTIND
|
98
|
+
}
|
99
|
+
|
100
|
+
parse_args $@ && shift $(($OPTIND - 1))
|
101
|
+
# If they put args before the command like 'bin/contentful -s 1xab migrate -y', try parsing again
|
102
|
+
[[ -z "$subcommand" ]] && parse_args $@ && shift $(($OPTIND - 1))
|
103
|
+
|
104
|
+
require_environment() {
|
105
|
+
[[ -z "$CONTENTFUL_SPACE_ID" ]] && logerr "Please set CONTENTFUL_SPACE_ID environment variable or use '-s' flag." && exit -1;
|
106
|
+
[[ -z "$CONTENTFUL_MANAGEMENT_TOKEN" ]] && logerr "Please set CONTENTFUL_MANAGEMENT_TOKEN environment variable or use '-a' flag." && exit -1;
|
107
|
+
if [[ ! -f node_modules/.bin/contentful-migration ]]; then
|
108
|
+
command -v npm >/dev/null 2>&1 || (logerr "I require 'npm' but it's not installed. Please install nodejs."; exit -1)
|
109
|
+
logv "npm install"
|
110
|
+
npm install
|
111
|
+
[[ -f node_modules/.bin/contentful-migration ]] || (logerr "Failed installing node modules - please ensure contentful CLI is installed"; exit -1)
|
112
|
+
fi
|
113
|
+
}
|
114
|
+
|
115
|
+
## *** Utility functions ***
|
116
|
+
|
117
|
+
confirm() {
|
118
|
+
[[ -z "$2" ]] && [[ ! -z "$YES" ]] && logv "$1 (y/n): confirmed by -y flag" && return 0;
|
119
|
+
|
120
|
+
while true; do
|
121
|
+
if [[ -z "$2" ]]; then
|
122
|
+
read -p $'\033[1;36m'"$1"' (y/n): '$'\033[0m' yn
|
123
|
+
else
|
124
|
+
# double confirm - extra dangerous.
|
125
|
+
read -p $'\033[0;31m'"$1"' (y/n): '$'\033[0m' yn
|
126
|
+
fi
|
127
|
+
case $yn in
|
128
|
+
[Yy]* ) return 0;;
|
129
|
+
[Nn]* ) return 1;;
|
130
|
+
* ) echo "Please answer yes or no.";;
|
131
|
+
esac
|
132
|
+
done
|
133
|
+
}
|
134
|
+
|
135
|
+
get_space_name() {
|
136
|
+
logv "curl -s https://api.contentful.com/spaces/$1?access_token=****"
|
137
|
+
curl -s https://api.contentful.com/spaces/$1?access_token=$CONTENTFUL_MANAGEMENT_TOKEN | jq -r .name | tr '[:upper:]' '[:lower:]'
|
138
|
+
}
|
139
|
+
|
140
|
+
set -e
|
141
|
+
|
142
|
+
# *** Commands ***
|
143
|
+
|
144
|
+
# Example: bin/contentful migrate -y -s 1xab -a $MY_TOKEN db/migrate/20180101120000_add_content_type_dog.ts
|
145
|
+
# equivalent to: bin/rake db:migrate
|
146
|
+
migrate() {
|
147
|
+
ARG="$1"
|
148
|
+
[[ -z "$ARG" ]] && ARG="db/migrate"
|
149
|
+
[[ -d "$ARG" ]] && ARG="batch $ARG"
|
150
|
+
|
151
|
+
require_environment
|
152
|
+
|
153
|
+
logv "contentful-migration -s $CONTENTFUL_SPACE_ID -a ***** $YES -p $ARG"
|
154
|
+
node_modules/.bin/ts-node node_modules/.bin/contentful-migration \
|
155
|
+
-s $CONTENTFUL_SPACE_ID -a $CONTENTFUL_MANAGEMENT_TOKEN \
|
156
|
+
$YES -p $ARG
|
157
|
+
|
158
|
+
mkdir -p db
|
159
|
+
logv "contentful-export -s --export-dir db --content-file contentful-schema.json --space-id $CONTENTFUL_SPACE_ID --management-token ***** --query-entries 'content_type=migrationHistory' --query-assets 'sys.id=false'"
|
160
|
+
node_modules/.bin/contentful-export --export-dir db --content-file contentful-schema.json \
|
161
|
+
--space-id $CONTENTFUL_SPACE_ID --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
|
162
|
+
--query-entries 'content_type=migrationHistory' \
|
163
|
+
--query-assets 'sys.id=false'
|
164
|
+
|
165
|
+
if [[ $(git diff-index --name-only HEAD | grep 'db/contentful-schema.json') == "" ]]; then
|
166
|
+
echo -e "${COLOR_LGREEN}✓ Schema in contentful space is equivalent to stored schema${COLOR_NC}"
|
167
|
+
else
|
168
|
+
echo -e "${COLOR_YELLOW}⚠️ Schema changed after running migrations${COLOR_NC}"
|
169
|
+
fi
|
170
|
+
}
|
171
|
+
|
172
|
+
# Example: bin/contentful backup -s 1xab -a $MY_TOKEN 2018_01_01.1xab.dump.json
|
173
|
+
# equivalent to: bin/rake db:dump[2018_01_01.dump]
|
174
|
+
backup() {
|
175
|
+
FILE="$1"
|
176
|
+
[[ ! -z "$FILE" ]] && FILE="--content-file $FILE" && shift
|
177
|
+
|
178
|
+
require_environment
|
179
|
+
|
180
|
+
logv "contentful-export $FILE --space-id $CONTENTFUL_SPACE_ID --management-token ***** $@"
|
181
|
+
node_modules/.bin/contentful-export $FILE \
|
182
|
+
--space-id $CONTENTFUL_SPACE_ID --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
|
183
|
+
$@
|
184
|
+
}
|
185
|
+
|
186
|
+
# Example: bin/contentful restore -y -s 1xab -a $MY_TOKEN 2018_01_01.1xab.dump.json
|
187
|
+
# equivalent to: bin/rake db:restore[2018_01_01.dump]
|
188
|
+
restore() {
|
189
|
+
FILE="$1"
|
190
|
+
if [[ -z "$FILE" ]]; then
|
191
|
+
FILE=$(ls contentful-export-$CONTENTFUL_SPACE_ID-* | sort -r | head -n 1)
|
192
|
+
[[ -z "$FILE" ]] && logerr "No file given on command line" && exit -1
|
193
|
+
fi
|
194
|
+
|
195
|
+
confirm "Import $FILE into $CONTENTFUL_SPACE_ID?" || exit -1
|
196
|
+
|
197
|
+
require_environment
|
198
|
+
|
199
|
+
logv "contentful-import --space-id $CONTENTFUL_SPACE_ID --management-token ***** --content-file $FILE"
|
200
|
+
node_modules/.bin/contentful-import \
|
201
|
+
--space-id $CONTENTFUL_SPACE_ID --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
|
202
|
+
--content-file $FILE
|
203
|
+
}
|
204
|
+
|
205
|
+
# Example: bin/contentful setup -y -s 1xab -a $MY_TOKEN db/my-schema.json
|
206
|
+
# equivalent to: bin/rake db:setup
|
207
|
+
setup() {
|
208
|
+
FILE="$1"
|
209
|
+
[[ -z "$FILE" ]] && FILE=db/contentful-schema.json
|
210
|
+
|
211
|
+
confirm "Initialize space $CONTENTFUL_SPACE_ID from seed file $FILE?" || exit -1
|
212
|
+
|
213
|
+
require_environment
|
214
|
+
|
215
|
+
logv "contentful-import --space-id $CONTENTFUL_SPACE_ID --management-token ***** --content-file $FILE"
|
216
|
+
node_modules/.bin/contentful-import \
|
217
|
+
--space-id $CONTENTFUL_SPACE_ID --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
|
218
|
+
--content-file $FILE
|
219
|
+
|
220
|
+
migrate
|
221
|
+
}
|
222
|
+
|
223
|
+
# Example: bin/contentful clean -s 1xab -a $MY_TOKEN
|
224
|
+
clean() {
|
225
|
+
command -v jq >/dev/null 2>&1 || (logerr "I require 'jq' but it's not installed. Please run 'brew install jq'"; exit -1)
|
226
|
+
|
227
|
+
require_environment
|
228
|
+
|
229
|
+
name=$(get_space_name $CONTENTFUL_SPACE_ID)
|
230
|
+
|
231
|
+
confirm "This will delete all data and content types from $name. Are you sure?" || exit -1
|
232
|
+
[[ "$name" != *staging ]] && [[ "$name" != *test ]] && confirm "$name is not a staging or test environment! Are you really sure?" dangerous!
|
233
|
+
|
234
|
+
local bkup_file="contentful-export-$CONTENTFUL_SPACE_ID-`date +"%Y-%m-%dT%H-%M-%S"`.json"
|
235
|
+
backup $bkup_file
|
236
|
+
content_types=$(cat $bkup_file | jq -r '.contentTypes[].sys.id')
|
237
|
+
entries=$(cat $bkup_file | jq -r '.entries[].sys.id')
|
238
|
+
assets=$(cat $bkup_file | jq -r '.assets[].sys.id')
|
239
|
+
|
240
|
+
delete() {
|
241
|
+
logv "curl -XDELETE https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/$1/$2/published\?access_token\=*****"
|
242
|
+
curl -s --fail -XDELETE https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/$1/$2/published\?access_token\=$CONTENTFUL_MANAGEMENT_TOKEN > /dev/null
|
243
|
+
logv "curl -XDELETE https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/$1/$2\?access_token\=*****"
|
244
|
+
curl -s --fail -XDELETE https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/$1/$2\?access_token\=$CONTENTFUL_MANAGEMENT_TOKEN > /dev/null
|
245
|
+
}
|
246
|
+
|
247
|
+
[[ ! -z "$assets" ]] && while read -r id; do delete 'assets' $id; done <<< "${assets}"
|
248
|
+
[[ ! -z "$entries" ]] && while read -r id; do delete 'entries' $id; done <<< "${entries}"
|
249
|
+
[[ ! -z "$content_types" ]] && while read -r id; do delete 'content_types' $id; done <<< "${content_types}"
|
250
|
+
|
251
|
+
echo -e "${COLOR_LGREEN}All content deleted - prior content saved at${COLOR_NC} $bkup_file"
|
252
|
+
[[ "$1" == "no-init" ]] || (setup || logerr "Error setting up space $name!")
|
253
|
+
}
|
254
|
+
|
255
|
+
# Example: bin/contentful restore_from -s $staging_space_id -a $MY_TOKEN $production_space_id
|
256
|
+
restore_from() {
|
257
|
+
command -v jq >/dev/null 2>&1 || (logerr "I require 'jq' but it's not installed. Please run 'brew install jq'"; exit -1)
|
258
|
+
|
259
|
+
require_environment
|
260
|
+
|
261
|
+
from_space_id=$1
|
262
|
+
[[ -z "$from_space_id" ]] && logerr "Please provide the space ID from which to restore data" && exit -1
|
263
|
+
to_space_id=$CONTENTFUL_SPACE_ID
|
264
|
+
|
265
|
+
from_name=$(get_space_name $from_space_id)
|
266
|
+
to_name=$(get_space_name $CONTENTFUL_SPACE_ID)
|
267
|
+
|
268
|
+
echo -e "${COLOR_LCYAN}This will backup all data from $from_name, delete all data in $to_name, and then write the $from_name data over it.${COLOR_NC}"
|
269
|
+
confirm "Continue?" || exit -1
|
270
|
+
export YES='-y' # don't keep bugging the user
|
271
|
+
|
272
|
+
export CONTENTFUL_SPACE_ID=$from_space_id
|
273
|
+
local bkup_file="contentful-export-$from_space_id-`date +"%Y-%m-%dT%H-%M-%S"`.json"
|
274
|
+
logv "bin/contentful backup -s $CONTENTFUL_SPACE_ID $bkup_file"
|
275
|
+
backup $bkup_file --skip-roles --skip-webhooks
|
276
|
+
|
277
|
+
export CONTENTFUL_SPACE_ID=$to_space_id
|
278
|
+
logv "bin/contentful clean -s $CONTENTFUL_SPACE_ID"
|
279
|
+
clean no-init
|
280
|
+
|
281
|
+
logv "bin/contentful restore -s $CONTENTFUL_SPACE_ID $bkup_file"
|
282
|
+
restore $bkup_file
|
283
|
+
}
|
284
|
+
|
285
|
+
# Example: bin/contentful generate add content type dog
|
286
|
+
# equivalent to: bin/rails generate migration add_content_type_dog
|
287
|
+
generate() {
|
288
|
+
migration="
|
289
|
+
import Migration from 'contentful-migration-cli'
|
290
|
+
|
291
|
+
export = function (migration: Migration) {
|
292
|
+
const dog = migration.createContentType('dog', {
|
293
|
+
name: 'Dog'
|
294
|
+
})
|
295
|
+
|
296
|
+
const name = dog.createField('name')
|
297
|
+
name.name('Name')
|
298
|
+
.type('Symbol')
|
299
|
+
.required(true)
|
300
|
+
}
|
301
|
+
"
|
302
|
+
|
303
|
+
timestamp=$(date +%Y%m%d%H%M%S)
|
304
|
+
filename="$@"
|
305
|
+
[[ -z "$filename" ]] && filename="contentful_migration"
|
306
|
+
filename=${filename// /\_}
|
307
|
+
filename="db/migrate/${timestamp}_${filename}.ts"
|
308
|
+
echo "$migration" > $filename
|
309
|
+
echo "generated file $filename"
|
310
|
+
}
|
311
|
+
|
312
|
+
case $subcommand in
|
313
|
+
migrate)
|
314
|
+
migrate $@
|
315
|
+
;;
|
316
|
+
backup|export)
|
317
|
+
backup $@
|
318
|
+
;;
|
319
|
+
restore|import)
|
320
|
+
restore $@
|
321
|
+
;;
|
322
|
+
setup)
|
323
|
+
setup $@
|
324
|
+
;;
|
325
|
+
generate)
|
326
|
+
generate $@
|
327
|
+
;;
|
328
|
+
clean)
|
329
|
+
clean $@
|
330
|
+
;;
|
331
|
+
restore_from)
|
332
|
+
restore_from $@
|
333
|
+
;;
|
334
|
+
help|h|\?)
|
335
|
+
usage
|
336
|
+
;;
|
337
|
+
*)
|
338
|
+
logerr "Unknown command: '$1'"
|
339
|
+
usage
|
340
|
+
exit -1
|
341
|
+
;;
|
342
|
+
esac
|
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
import Migration from 'contentful-migration-cli'
|
3
|
+
|
4
|
+
export = function (migration: Migration) {
|
5
|
+
const menu = migration.createContentType('menu')
|
6
|
+
.name('Menu')
|
7
|
+
.description('A Menu contains a number of Menu Buttons or other Menus, which ' +
|
8
|
+
'will be rendered as drop-downs.')
|
9
|
+
.displayField('name')
|
10
|
+
|
11
|
+
menu.createField('name')
|
12
|
+
.name('Menu Name')
|
13
|
+
.type('Symbol')
|
14
|
+
.required(true)
|
15
|
+
|
16
|
+
menu.createField('topButton')
|
17
|
+
.name('Top Button')
|
18
|
+
.type('Link')
|
19
|
+
.linkType('Entry')
|
20
|
+
.validations([
|
21
|
+
{
|
22
|
+
linkContentType: [ 'menuButton' ],
|
23
|
+
message: 'The Top Button must be a button linking to a URL or page. ' +
|
24
|
+
'If the menu is a dropdown, this button is visible when it is collapsed.'
|
25
|
+
}
|
26
|
+
])
|
27
|
+
|
28
|
+
menu.createField('items')
|
29
|
+
.name('Items')
|
30
|
+
.type('Array')
|
31
|
+
.items({
|
32
|
+
type: 'Link',
|
33
|
+
linkType: 'Entry',
|
34
|
+
validations: [
|
35
|
+
{
|
36
|
+
linkContentType: [ 'menu', 'menuButton' ],
|
37
|
+
message: 'The items must be either buttons or drop-down menus'
|
38
|
+
}
|
39
|
+
]
|
40
|
+
})
|
41
|
+
|
42
|
+
const menuButton = migration.createContentType('menuButton')
|
43
|
+
.name('Menu Button')
|
44
|
+
.description('A Menu Button is a clickable button that goes on a Menu. ' +
|
45
|
+
'It has a link to a Page or a URL.')
|
46
|
+
.displayField('text')
|
47
|
+
|
48
|
+
menuButton.createField('text')
|
49
|
+
.name('Text')
|
50
|
+
.type('Symbol')
|
51
|
+
.required(true)
|
52
|
+
.validations([
|
53
|
+
{
|
54
|
+
size: { min: 1, max: 60 },
|
55
|
+
message: 'A Menu Button should have a very short text field - ideally a ' +
|
56
|
+
'single word. Please limit the text to 60 characters.'
|
57
|
+
}
|
58
|
+
])
|
59
|
+
|
60
|
+
menuButton.createField('icon')
|
61
|
+
.name('Icon')
|
62
|
+
.type('Link')
|
63
|
+
.linkType('Asset')
|
64
|
+
|
65
|
+
menuButton.createField('externalLink')
|
66
|
+
.name('External Link')
|
67
|
+
.type('Symbol')
|
68
|
+
.validations([
|
69
|
+
{
|
70
|
+
regexp: { pattern: "^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$" },
|
71
|
+
message: "The external link must be a URL like 'https://www.watermark.org/'"
|
72
|
+
}
|
73
|
+
])
|
74
|
+
|
75
|
+
menuButton.createField('link')
|
76
|
+
.name('Page Link')
|
77
|
+
.type('Link')
|
78
|
+
.linkType('Entry')
|
79
|
+
.validations([
|
80
|
+
{
|
81
|
+
linkContentType: [ 'page' ],
|
82
|
+
message: 'The Page Link must be a link to a Page which has a slug.'
|
83
|
+
}
|
84
|
+
])
|
85
|
+
}
|