@amplytools/react-native-amply-sdk 0.10.1 → 0.12.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/AmplyReactNative.podspec
CHANGED
package/android/build.gradle
CHANGED
|
@@ -15,7 +15,7 @@ buildscript {
|
|
|
15
15
|
apply plugin: 'com.android.library'
|
|
16
16
|
apply plugin: 'org.jetbrains.kotlin.android'
|
|
17
17
|
|
|
18
|
-
def amplySdkVersion = project.findProperty('amplySdkVersion') ?: System.getenv('AMPLY_SDK_VERSION') ?: '0.
|
|
18
|
+
def amplySdkVersion = project.findProperty('amplySdkVersion') ?: System.getenv('AMPLY_SDK_VERSION') ?: '0.12.0'
|
|
19
19
|
group = 'tools.amply'
|
|
20
20
|
version = amplySdkVersion
|
|
21
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amplytools/react-native-amply-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "React Native SDK for Amply: Mobile SDK to orchestrate in-app experiences and campaigns remotely, without app releases",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -33,12 +33,13 @@
|
|
|
33
33
|
"build": "expo-module build",
|
|
34
34
|
"build:plugin": "expo-module build plugin",
|
|
35
35
|
"clean": "expo-module clean",
|
|
36
|
-
"test": "node scripts/codegen.js --check && expo-module test && yarn check:seam-tokens",
|
|
36
|
+
"test": "node scripts/codegen.js --check && expo-module test && yarn check:seam-tokens && yarn check:sample-parity",
|
|
37
37
|
"prepare": "expo-module prepare",
|
|
38
38
|
"prepublishOnly": "expo-module prepublishOnly",
|
|
39
39
|
"codegen": "node scripts/codegen.js",
|
|
40
40
|
"codegen:check": "node scripts/codegen.js --check",
|
|
41
|
-
"check:seam-tokens": "bash scripts/check-seam-tokens.sh"
|
|
41
|
+
"check:seam-tokens": "bash scripts/check-seam-tokens.sh",
|
|
42
|
+
"check:sample-parity": "bash scripts/check-sample-parity.sh"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"expo": ">=54.0.0",
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Every control the sample spec requires must exist in every sample that claims the
|
|
4
|
+
# platform, tagged with its manifest id. Nothing else notices when one of them is missing.
|
|
5
|
+
#
|
|
6
|
+
# The six Amply samples are six copies of the same screen, and they drifted because
|
|
7
|
+
# copy-paste has no compiler. In the KMP repo, `ios-spm-sample/HomeViewController.swift`
|
|
8
|
+
# reached 886 lines while its CocoaPods twin sat at 566 — the same screen, forked and then
|
|
9
|
+
# edited on one side only, with `GateDemo.swift` existing in exactly one of them. Both
|
|
10
|
+
# projects built clean the whole time. Nobody noticed, because nothing checked. The two RN
|
|
11
|
+
# examples here forked the same way: `bare/src/hooks/useAmplyDemo.ts` and
|
|
12
|
+
# `expo/src/hooks/useAmplyDemo.ts` are two copies of one hook, and `bare` still imports the
|
|
13
|
+
# SDK under a legacy alias no integrator would type.
|
|
14
|
+
#
|
|
15
|
+
# This is that check. It greps each example's own sources for every manifest id required on
|
|
16
|
+
# the `rn` column and fails naming the id, the example, and where it looked. It is a parity
|
|
17
|
+
# check, not a UI test: it answers "is this control present in this sample", which is the
|
|
18
|
+
# only question consistency actually turns on.
|
|
19
|
+
#
|
|
20
|
+
# Spec: multiplatform-library-template/samples/SAMPLE_APP_SPEC.md (canonical, KMP repo)
|
|
21
|
+
# Manifest: example/sample-manifest.txt (verbatim copy of the KMP repo's canonical file;
|
|
22
|
+
# this script diffs the two when both are present)
|
|
23
|
+
#
|
|
24
|
+
# Usage: bash scripts/check-sample-parity.sh
|
|
25
|
+
set -uo pipefail
|
|
26
|
+
|
|
27
|
+
cd "$(dirname "$0")/.."
|
|
28
|
+
|
|
29
|
+
MANIFEST="example/sample-manifest.txt"
|
|
30
|
+
SPEC_PATH="multiplatform-library-template/samples/SAMPLE_APP_SPEC.md"
|
|
31
|
+
|
|
32
|
+
if [ ! -f "$MANIFEST" ]; then
|
|
33
|
+
echo "check-sample-parity: FAIL — missing $MANIFEST" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Quote characters an id can be wrapped in: JSX uses ", JS also uses ' and ` for template
|
|
38
|
+
# literals. The id literal must sit next to `testID` on one line.
|
|
39
|
+
Q="[\"'\`]"
|
|
40
|
+
|
|
41
|
+
# ---------------------------------------------------------------------------------------
|
|
42
|
+
# The canonical copy. The manifest lives in the KMP repo; this repo carries a duplicate
|
|
43
|
+
# because it is published to npm and mirrored publicly and so cannot depend on a sibling
|
|
44
|
+
# checkout existing. Duplication that nothing checks is drift with extra steps, so: when
|
|
45
|
+
# the KMP repo is reachable, diff it and fail on any difference. When it is not, say so
|
|
46
|
+
# loudly and print the revision, so a stale copy shows up in the output instead of passing
|
|
47
|
+
# silently.
|
|
48
|
+
# ---------------------------------------------------------------------------------------
|
|
49
|
+
revision=$(grep -m1 '^# revision:' "$MANIFEST" | sed 's/^# revision:[[:space:]]*//')
|
|
50
|
+
if [ -z "$revision" ]; then
|
|
51
|
+
echo "check-sample-parity: FAIL — $MANIFEST has no '# revision:' header" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
peer=""
|
|
56
|
+
for candidate in \
|
|
57
|
+
"${AMPLY_SAMPLE_MANIFEST_PEER:-}" \
|
|
58
|
+
"../multiplatform-library-template/samples/sample-manifest.txt"
|
|
59
|
+
do
|
|
60
|
+
[ -n "$candidate" ] && [ -f "$candidate" ] && { peer="$candidate"; break; }
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
if [ -n "$peer" ]; then
|
|
64
|
+
if ! diff -u "$peer" "$MANIFEST" > /tmp/check-sample-parity-peer.diff 2>&1; then
|
|
65
|
+
echo "check-sample-parity: FAIL — this repo's manifest copy has diverged from the canonical one." >&2
|
|
66
|
+
echo " canonical: $peer" >&2
|
|
67
|
+
echo " copy: $MANIFEST" >&2
|
|
68
|
+
sed 's/^/ /' /tmp/check-sample-parity-peer.diff >&2
|
|
69
|
+
rm -f /tmp/check-sample-parity-peer.diff
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
rm -f /tmp/check-sample-parity-peer.diff
|
|
73
|
+
peer_state="verified byte-identical against $peer"
|
|
74
|
+
else
|
|
75
|
+
peer_state="NOT VERIFIED — the KMP repo was not found; set AMPLY_SAMPLE_MANIFEST_PEER to check it"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# ---------------------------------------------------------------------------------------
|
|
79
|
+
# Parse the manifest into: id <TAB> android <TAB> ios <TAB> rn <TAB> note
|
|
80
|
+
# ---------------------------------------------------------------------------------------
|
|
81
|
+
rows=$(
|
|
82
|
+
awk -F'|' '
|
|
83
|
+
/^[[:space:]]*#/ { next }
|
|
84
|
+
/^[[:space:]]*$/ { next }
|
|
85
|
+
NF < 4 { next }
|
|
86
|
+
{
|
|
87
|
+
for (i = 1; i <= NF; i++) { gsub(/^[[:space:]]+|[[:space:]]+$/, "", $i) }
|
|
88
|
+
note = (NF >= 5) ? $5 : ""
|
|
89
|
+
print $1 "\t" $2 "\t" $3 "\t" $4 "\t" note
|
|
90
|
+
}
|
|
91
|
+
' "$MANIFEST"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if [ -z "$rows" ]; then
|
|
95
|
+
echo "check-sample-parity: FAIL — parsed zero rows from $MANIFEST; the parser is broken" >&2
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
row_count=$(printf '%s\n' "$rows" | wc -l | tr -d ' ')
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------------------
|
|
102
|
+
# The examples. Each one searches its own sources plus the shared UI module. An absent root
|
|
103
|
+
# is skipped rather than fatal; an example with NO existing root at all is fatal, because
|
|
104
|
+
# that means this list is stale.
|
|
105
|
+
#
|
|
106
|
+
# The shared module is on BOTH examples' search paths, and that is a trap this check walks
|
|
107
|
+
# into unless it is told not to. A control id living in example/shared satisfies the grep
|
|
108
|
+
# for bare and expo alike — including for a host that never imports the module and still
|
|
109
|
+
# renders its own old screen. That is not hypothetical: on the day the shared module landed,
|
|
110
|
+
# `expo` reported "all 40 required controls present" while app/index.tsx was still building
|
|
111
|
+
# its own ScrollView out of useAmplyDemo. Green, and completely wrong.
|
|
112
|
+
#
|
|
113
|
+
# The native samples do not have this hole. Both Xcode projects list ../ios-shared/Sources
|
|
114
|
+
# and both Gradle modules include the shared srcDir, so on those platforms presence in the
|
|
115
|
+
# shared source IS compilation into the target. Metro resolving a package is not the same
|
|
116
|
+
# claim: a module on the search path is only rendered if something imports it.
|
|
117
|
+
#
|
|
118
|
+
# So each RN host must also prove it MOUNTS the shared module. `mount` below is a file that
|
|
119
|
+
# must exist and must import SHARED_PKG. Without this, the consolidation can be reported
|
|
120
|
+
# complete while half of it was never wired.
|
|
121
|
+
# ---------------------------------------------------------------------------------------
|
|
122
|
+
SHARED_PKG="@amply/sample-shared"
|
|
123
|
+
samples=(
|
|
124
|
+
"bare|example/bare/src example/shared|example/bare/src/App.tsx"
|
|
125
|
+
"expo|example/expo/app example/expo/src example/expo/components example/shared|example/expo/app/index.tsx"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
ATTR="testID"
|
|
129
|
+
INCLUDES="--include=*.ts --include=*.tsx --include=*.js --include=*.jsx"
|
|
130
|
+
|
|
131
|
+
fail=0
|
|
132
|
+
checked_total=0
|
|
133
|
+
|
|
134
|
+
echo "check-sample-parity: manifest revision $revision — $row_count rows"
|
|
135
|
+
echo " peer copy: $peer_state"
|
|
136
|
+
echo
|
|
137
|
+
|
|
138
|
+
for entry in "${samples[@]}"; do
|
|
139
|
+
name="${entry%%|*}"
|
|
140
|
+
rest="${entry#*|}"
|
|
141
|
+
roots="${rest%%|*}"
|
|
142
|
+
mount="${rest#*|}"
|
|
143
|
+
|
|
144
|
+
existing_roots=""
|
|
145
|
+
for r in $roots; do
|
|
146
|
+
[ -d "$r" ] && existing_roots="$existing_roots $r"
|
|
147
|
+
done
|
|
148
|
+
|
|
149
|
+
if [ -z "$existing_roots" ]; then
|
|
150
|
+
echo "check-sample-parity: FAIL — example '$name' has no source root on disk (looked in: $roots)" >&2
|
|
151
|
+
echo " the sample list in this script is stale." >&2
|
|
152
|
+
fail=1
|
|
153
|
+
continue
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# Does this host actually MOUNT the shared module, or does it merely have it on a search
|
|
157
|
+
# path? Only the second is true of a host still rendering its own screen, and the id grep
|
|
158
|
+
# below cannot tell the difference — every shared id would satisfy it either way.
|
|
159
|
+
if [ -d "example/shared" ]; then
|
|
160
|
+
if [ ! -f "$mount" ]; then
|
|
161
|
+
echo "check-sample-parity: FAIL — example '$name' has no entry point at $mount" >&2
|
|
162
|
+
echo " the mount path in this script is stale." >&2
|
|
163
|
+
fail=1
|
|
164
|
+
continue
|
|
165
|
+
fi
|
|
166
|
+
if ! grep -qF "$SHARED_PKG" "$mount"; then
|
|
167
|
+
echo "check-sample-parity: FAIL — example '$name' does not mount the shared UI module." >&2
|
|
168
|
+
echo " $mount never imports $SHARED_PKG, so this example still" >&2
|
|
169
|
+
echo " renders its own screen. Every control id below would be" >&2
|
|
170
|
+
echo " satisfied by example/shared regardless — a green that means" >&2
|
|
171
|
+
echo " nothing. Mount the shared module in $mount." >&2
|
|
172
|
+
fail=1
|
|
173
|
+
continue
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
missing=()
|
|
178
|
+
unbound=()
|
|
179
|
+
required=0
|
|
180
|
+
|
|
181
|
+
while IFS=$'\t' read -r id android ios rn note; do
|
|
182
|
+
[ "$rn" = "x" ] || continue
|
|
183
|
+
required=$((required + 1))
|
|
184
|
+
|
|
185
|
+
id_esc=$(printf '%s' "$id" | sed 's/[.[\*^$()+?{}|\\]/\\&/g')
|
|
186
|
+
|
|
187
|
+
case "$note" in
|
|
188
|
+
launcharg:*)
|
|
189
|
+
# Not a UI control — the launch key just has to appear in the source. On RN the
|
|
190
|
+
# transport is a deeplink query param rather than a launch argument (neither
|
|
191
|
+
# example can read one without a new native dependency); the key spelling is the
|
|
192
|
+
# same, which is why one manifest row covers all three platforms.
|
|
193
|
+
# shellcheck disable=SC2086
|
|
194
|
+
if ! grep -RIlE $INCLUDES -e "$id_esc" $existing_roots > /dev/null 2>&1; then
|
|
195
|
+
missing+=("$id")
|
|
196
|
+
fi
|
|
197
|
+
continue
|
|
198
|
+
;;
|
|
199
|
+
prefix:*) pattern="${Q}${id_esc}\\." ;;
|
|
200
|
+
*) pattern="${Q}${id_esc}${Q}" ;;
|
|
201
|
+
esac
|
|
202
|
+
|
|
203
|
+
# shellcheck disable=SC2086
|
|
204
|
+
hits=$(grep -RInE $INCLUDES -e "$pattern" $existing_roots 2>/dev/null)
|
|
205
|
+
if [ -z "$hits" ]; then
|
|
206
|
+
missing+=("$id")
|
|
207
|
+
continue
|
|
208
|
+
fi
|
|
209
|
+
if ! printf '%s\n' "$hits" | grep -q "$ATTR"; then
|
|
210
|
+
unbound+=("$id")
|
|
211
|
+
fi
|
|
212
|
+
done <<< "$rows"
|
|
213
|
+
|
|
214
|
+
checked_total=$((checked_total + required))
|
|
215
|
+
|
|
216
|
+
if [ ${#missing[@]} -eq 0 ] && [ ${#unbound[@]} -eq 0 ]; then
|
|
217
|
+
echo " OK $name (rn) — all $required required controls present"
|
|
218
|
+
continue
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
fail=1
|
|
222
|
+
echo " FAIL $name (rn) — $((${#missing[@]} + ${#unbound[@]})) of $required required controls not satisfied"
|
|
223
|
+
echo " searched:$existing_roots"
|
|
224
|
+
if [ ${#missing[@]} -gt 0 ]; then
|
|
225
|
+
echo " missing (${#missing[@]}):"
|
|
226
|
+
for id in "${missing[@]}"; do echo " - $id"; done
|
|
227
|
+
fi
|
|
228
|
+
if [ ${#unbound[@]} -gt 0 ]; then
|
|
229
|
+
echo " present but not on a line with \`$ATTR\` (${#unbound[@]}):"
|
|
230
|
+
for id in "${unbound[@]}"; do echo " - $id"; done
|
|
231
|
+
fi
|
|
232
|
+
echo
|
|
233
|
+
done
|
|
234
|
+
|
|
235
|
+
# ---------------------------------------------------------------------------------------
|
|
236
|
+
# Retired ids: controls that were required once and must NOT come back. A presence-only
|
|
237
|
+
# check cannot see a control that should have been deleted, so without this a removal is
|
|
238
|
+
# held together by trust. Failed on sight, wherever they appear.
|
|
239
|
+
# ---------------------------------------------------------------------------------------
|
|
240
|
+
retired_ids=$(grep -E '^# +retired: +amply\.' "$MANIFEST" | sed -E 's/^# +retired: +([^ ]+).*/\1/')
|
|
241
|
+
for rid in $retired_ids; do
|
|
242
|
+
rid_esc=$(printf '%s' "$rid" | sed 's/[.[\*^$()+?{}|\\]/\\&/g')
|
|
243
|
+
# shellcheck disable=SC2086
|
|
244
|
+
retired_roots=""
|
|
245
|
+
for r in example/bare/src example/expo/app example/expo/src example/expo/components example/shared; do [ -d "$r" ] && retired_roots="$retired_roots $r"; done
|
|
246
|
+
# shellcheck disable=SC2086
|
|
247
|
+
hits=$(grep -RIlE --include=*.ts --include=*.tsx --include=*.js --include=*.jsx -e "${Q}${rid_esc}${Q}" $retired_roots 2>/dev/null || true)
|
|
248
|
+
if [ -n "$hits" ]; then
|
|
249
|
+
echo "check-sample-parity: FAIL — retired control '$rid' is still in the source:" >&2
|
|
250
|
+
printf ' %s\n' $hits >&2
|
|
251
|
+
echo " It was deliberately removed; see the manifest's Retired block." >&2
|
|
252
|
+
fail=1
|
|
253
|
+
fi
|
|
254
|
+
done
|
|
255
|
+
|
|
256
|
+
if [ "$fail" -ne 0 ]; then
|
|
257
|
+
echo "check-sample-parity: FAIL" >&2
|
|
258
|
+
echo " Each missing id is a control $SPEC_PATH requires and the example" >&2
|
|
259
|
+
echo " does not have. Tag the real widget with it: testID=\"<id>\"." >&2
|
|
260
|
+
exit 1
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
echo "check-sample-parity: OK — manifest revision $revision, $checked_total control checks across ${#samples[@]} examples."
|