@tidecloak/create-nextjs 0.12.16 → 0.12.27

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tidecloak/create-nextjs",
3
- "version": "0.12.16",
3
+ "version": "0.12.27",
4
4
  "type": "module",
5
5
  "description": "Scaffold a TideCloak-ready Next.js app with optional IAM setup and working auth - start building instantly with a live example",
6
6
  "bin": {
@@ -111,7 +111,7 @@
111
111
  "providerId": "declarative-user-profile",
112
112
  "config": {
113
113
  "kc.user.profile.config": [
114
- "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}"
114
+ "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}],\"unmanagedAttributePolicy\":\"ENABLED\"}"
115
115
  ]
116
116
  }
117
117
  }
@@ -1,9 +1,26 @@
1
1
  #!/usr/bin/env bash
2
+ set -euo pipefail
2
3
 
3
- # Load overrides from .env in the project root
4
- if [ -f "./.env.example" ]; then
5
- # shellcheck disable=SC1090
6
- source "./.env.example"
4
+ # ─────────────────────────────────────────────────────────────────────────────
5
+ # Resolve script directory (run from anywhere)
6
+ # ─────────────────────────────────────────────────────────────────────────────
7
+ SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)"
8
+
9
+ # ─────────────────────────────────────────────────────────────────────────────
10
+ # Load overrides from .env.example (CRLF-safe)
11
+ # ─────────────────────────────────────────────────────────────────────────────
12
+ ENV_FILE="${SCRIPT_DIR}/.env.example"
13
+ if [[ -f "$ENV_FILE" ]]; then
14
+ if grep -q $'\r' "$ENV_FILE"; then
15
+ TMP_ENV="$(mktemp)"
16
+ tr -d '\r' < "$ENV_FILE" > "$TMP_ENV"
17
+ # shellcheck disable=SC1090
18
+ source "$TMP_ENV"
19
+ rm -f "$TMP_ENV"
20
+ else
21
+ # shellcheck disable=SC1090
22
+ source "$ENV_FILE"
23
+ fi
7
24
  fi
8
25
 
9
26
  # ─────────────────────────────────────────────────────────────────────────────
@@ -11,23 +28,49 @@ fi
11
28
  # ─────────────────────────────────────────────────────────────────────────────
12
29
  TIDECLOAK_LOCAL_URL="${TIDECLOAK_LOCAL_URL:-http://localhost:8080}"
13
30
  CLIENT_APP_URL="${CLIENT_APP_URL:-http://localhost:3000}"
14
- REALM_JSON_PATH="${REALM_JSON_PATH:-./realm.json}"
15
- ADAPTER_OUTPUT_PATH="${ADAPTER_OUTPUT_PATH:-./tidecloak.json}"
31
+ ADAPTER_OUTPUT_PATH="${ADAPTER_OUTPUT_PATH:-${SCRIPT_DIR}/tidecloak.json}"
16
32
  NEW_REALM_NAME="${NEW_REALM_NAME:-nextjs-test}"
17
- REALM_MGMT_CLIENT_ID="realm-management"
18
- ADMIN_ROLE_NAME="tide-realm-admin"
33
+ REALM_MGMT_CLIENT_ID="${REALM_MGMT_CLIENT_ID:-realm-management}"
34
+ ADMIN_ROLE_NAME="${ADMIN_ROLE_NAME:-tide-realm-admin}"
19
35
  KC_USER="${KC_USER:-admin}"
20
36
  KC_PASSWORD="${KC_PASSWORD:-password}"
21
37
  CLIENT_NAME="${CLIENT_NAME:-myclient}"
22
38
 
23
39
  # ─────────────────────────────────────────────────────────────────────────────
24
- # sed -i portability
40
+ # Find realm.json robustly
41
+ # Priority: env → same dir → parent → current working dir
25
42
  # ─────────────────────────────────────────────────────────────────────────────
26
- if sed --version >/dev/null 2>&1; then
27
- SED_INPLACE=(-i)
28
- else
29
- SED_INPLACE=(-i '')
43
+ CANDIDATES=()
44
+ [[ "${REALM_JSON_PATH:-}" != "" ]] && CANDIDATES+=("${REALM_JSON_PATH}")
45
+ CANDIDATES+=("${SCRIPT_DIR}/realm.json" "${SCRIPT_DIR}/../realm.json" "$(pwd)/realm.json")
46
+
47
+ REALM_JSON_PATH=""
48
+ for p in "${CANDIDATES[@]}"; do
49
+ if [[ -f "$p" ]]; then REALM_JSON_PATH="$p"; break; fi
50
+ done
51
+
52
+ echo "🔍 realm.json search candidates:"
53
+ for p in "${CANDIDATES[@]}"; do echo " - $p"; done
54
+
55
+ if [[ -z "${REALM_JSON_PATH}" ]]; then
56
+ echo "❌ Could not find realm.json in the checked locations above." >&2
57
+ echo " Put realm.json next to the script: ${SCRIPT_DIR}/realm.json" >&2
58
+ echo " OR run with: REALM_JSON_PATH=/absolute/path/realm.json bash init/tcinit.sh" >&2
59
+ exit 1
30
60
  fi
61
+ echo "✅ Using realm.json: ${REALM_JSON_PATH}"
62
+
63
+ # ─────────────────────────────────────────────────────────────────────────────
64
+ # Dependency checks
65
+ # ─────────────────────────────────────────────────────────────────────────────
66
+ need_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "❌ Missing dependency: $1" >&2; exit 1; }; }
67
+ need_cmd curl
68
+ need_cmd jq
69
+ need_cmd sed
70
+ need_cmd mktemp
71
+
72
+ # sed -i portability
73
+ if sed --version >/dev/null 2>&1; then SED_INPLACE=(-i); else SED_INPLACE=(-i ''); fi
31
74
 
32
75
  # ─────────────────────────────────────────────────────────────────────────────
33
76
  # Helper: grab an admin token
@@ -42,19 +85,28 @@ get_admin_token() {
42
85
  | jq -r .access_token
43
86
  }
44
87
 
88
+ # ─────────────────────────────────────────────────────────────────────────────
89
+ # Cleanup handler
90
+ # ─────────────────────────────────────────────────────────────────────────────
91
+ TMP_REALM_JSON=""
92
+ cleanup() {
93
+ [[ -n "${TMP_REALM_JSON}" && -f "${TMP_REALM_JSON}" ]] && rm -f "${TMP_REALM_JSON}" || true
94
+ [[ -f "${SCRIPT_DIR}/.realm_name" ]] && rm -f "${SCRIPT_DIR}/.realm_name" || true
95
+ }
96
+ trap cleanup EXIT
97
+
45
98
  # ─────────────────────────────────────────────────────────────────────────────
46
99
  # Step 1: prepare realm JSON
47
100
  # ─────────────────────────────────────────────────────────────────────────────
48
101
  REALM_NAME="${NEW_REALM_NAME}"
49
- echo "${REALM_NAME}" > "./.realm_name"
102
+ echo "${REALM_NAME}" > "${SCRIPT_DIR}/.realm_name"
50
103
 
51
104
  TMP_REALM_JSON="$(mktemp)"
52
105
  cp "${REALM_JSON_PATH}" "${TMP_REALM_JSON}"
53
106
 
54
- # replace placeholders
55
107
  sed "${SED_INPLACE[@]}" "s|http://localhost:3000|${CLIENT_APP_URL}|g" "${TMP_REALM_JSON}"
56
- sed "${SED_INPLACE[@]}" "s|nextjs-test|${REALM_NAME}|g" "${TMP_REALM_JSON}"
57
- sed "${SED_INPLACE[@]}" "s|myclient|${CLIENT_NAME}|g" "${TMP_REALM_JSON}"
108
+ sed "${SED_INPLACE[@]}" "s|nextjs-test|${REALM_NAME}|g" "${TMP_REALM_JSON}"
109
+ sed "${SED_INPLACE[@]}" "s|myclient|${CLIENT_NAME}|g" "${TMP_REALM_JSON}"
58
110
 
59
111
  # ─────────────────────────────────────────────────────────────────────────────
60
112
  # Step 2: create realm (allow 409 if already exists)
@@ -80,17 +132,15 @@ fi
80
132
  TOKEN="$(get_admin_token)"
81
133
  echo "🔐 Initializing Tide realm + IGA..."
82
134
 
83
- response=$(curl -i -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/setUpTideRealm" \
135
+ curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/setUpTideRealm" \
84
136
  -H "Authorization: Bearer ${TOKEN}" \
85
137
  -H "Content-Type: application/x-www-form-urlencoded" \
86
- --data-urlencode "email=email@tide.org" 2>&1)
138
+ --data-urlencode "email=email@tide.org" >/dev/null
87
139
 
88
- # toggle IGA
89
140
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/toggle-iga" \
90
141
  -H "Authorization: Bearer ${TOKEN}" \
91
142
  -H "Content-Type: application/x-www-form-urlencoded" \
92
- --data-urlencode "isIGAEnabled=true" \
93
- > /dev/null
143
+ --data-urlencode "isIGAEnabled=true" >/dev/null
94
144
 
95
145
  echo "✅ Tide realm + IGA done."
96
146
 
@@ -103,7 +153,7 @@ approve_and_commit() {
103
153
  TOKEN="$(get_admin_token)"
104
154
  curl -s -X GET "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/${TYPE}/requests" \
105
155
  -H "Authorization: Bearer ${TOKEN}" \
106
- | jq -c '.[]' | while read -r req; do
156
+ | jq -c '.[]' | while IFS= read -r req; do
107
157
  payload=$(jq -n \
108
158
  --arg id "$(jq -r .draftRecordId <<< "${req}")" \
109
159
  --arg cst "$(jq -r .changeSetType <<< "${req}")" \
@@ -113,14 +163,12 @@ approve_and_commit() {
113
163
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/sign" \
114
164
  -H "Authorization: Bearer ${TOKEN}" \
115
165
  -H "Content-Type: application/json" \
116
- -d "${payload}" \
117
- > /dev/null
166
+ -d "${payload}" >/dev/null
118
167
 
119
168
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/commit" \
120
169
  -H "Authorization: Bearer ${TOKEN}" \
121
170
  -H "Content-Type: application/json" \
122
- -d "${payload}" \
123
- > /dev/null
171
+ -d "${payload}" >/dev/null
124
172
  done
125
173
  echo "✅ ${TYPE^} change-sets done."
126
174
  }
@@ -134,18 +182,15 @@ echo "👤 Creating new admin user..."
134
182
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users" \
135
183
  -H "Authorization: Bearer ${TOKEN}" \
136
184
  -H "Content-Type: application/json" \
137
- -d '{"username":"admin","email":"admin@tidecloak.com","firstName":"admin","lastName":"user","enabled":true}' \
138
- > /dev/null
185
+ -d '{"username":"admin","email":"admin@tidecloak.com","firstName":"admin","lastName":"user","enabled":true}' >/dev/null || true
139
186
 
140
187
  USER_ID=$(curl -s -X GET \
141
188
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users?username=admin" \
142
- -H "Authorization: Bearer ${TOKEN}" \
143
- | jq -r '.[0].id')
189
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
144
190
 
145
191
  CLIENT_UUID=$(curl -s -X GET \
146
192
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients?clientId=${REALM_MGMT_CLIENT_ID}" \
147
- -H "Authorization: Bearer ${TOKEN}" \
148
- | jq -r '.[0].id')
193
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
149
194
 
150
195
  ROLE_JSON=$(curl -s -X GET \
151
196
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/roles/${ADMIN_ROLE_NAME}" \
@@ -154,8 +199,7 @@ ROLE_JSON=$(curl -s -X GET \
154
199
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users/${USER_ID}/role-mappings/clients/${CLIENT_UUID}" \
155
200
  -H "Authorization: Bearer ${TOKEN}" \
156
201
  -H "Content-Type: application/json" \
157
- -d "[${ROLE_JSON}]" \
158
- > /dev/null
202
+ -d "[${ROLE_JSON}]" >/dev/null
159
203
 
160
204
  echo "✅ Admin user & role done."
161
205
 
@@ -216,32 +260,25 @@ UPDATED_JSON=$(jq --arg d "${CLIENT_APP_URL}" '.config.CustomAdminUIDomain = $d'
216
260
  curl -s -X PUT "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/identity-provider/instances/tide" \
217
261
  -H "Authorization: Bearer ${TOKEN}" \
218
262
  -H "Content-Type: application/json" \
219
- -d "${UPDATED_JSON}" \
220
- > /dev/null
263
+ -d "${UPDATED_JSON}" >/dev/null
221
264
 
222
265
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/sign-idp-settings" \
223
- -H "Authorization: Bearer ${TOKEN}" \
224
- > /dev/null
266
+ -H "Authorization: Bearer ${TOKEN}" >/dev/null
225
267
 
226
268
  echo "✅ CustomAdminUIDomain updated + signed."
227
269
 
228
-
229
270
  # ─────────────────────────────────────────────────────────────────────────────
230
- # Step 7: fetch adapter config + cleanup
271
+ # Step 7: fetch adapter config
231
272
  # ─────────────────────────────────────────────────────────────────────────────
232
273
  TOKEN="$(get_admin_token)"
233
274
  echo "📥 Fetching adapter config…"
234
275
  CLIENT_UUID=$(curl -s -X GET \
235
276
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_NAME}" \
236
- -H "Authorization: Bearer ${TOKEN}" \
237
- | jq -r '.[0].id')
277
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
238
278
 
239
279
  curl -s -X GET \
240
280
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/get-installations-provider?clientId=${CLIENT_UUID}&providerId=keycloak-oidc-keycloak-json" \
241
- -H "Authorization: Bearer ${TOKEN}" \
242
- > "${ADAPTER_OUTPUT_PATH}"
281
+ -H "Authorization: Bearer ${TOKEN}" > "${ADAPTER_OUTPUT_PATH}"
243
282
 
244
283
  echo "✅ Adapter config saved to ${ADAPTER_OUTPUT_PATH}"
245
- rm -f "${PROJECT_ROOT}/.realm_name" "${TMP_REALM_JSON}"
246
-
247
284
  echo "🎉 All done!"
@@ -9,9 +9,10 @@
9
9
  "init": "bash init/tcinit.sh"
10
10
  },
11
11
  "dependencies": {
12
- "next": "14.x",
13
- "react": "18.x",
14
- "react-dom": "18.x",
15
- "@tidecloak/nextjs": "^0.12.16"
12
+ "@tidecloak/nextjs": "^0.12.27",
13
+ "eslint-config-next": "^16.0.1",
14
+ "next": "^16.0.1",
15
+ "react": "^19.2.0",
16
+ "react-dom": "^19.2.0"
16
17
  }
17
18
  }
@@ -9,9 +9,10 @@
9
9
  "init": "bash init/tcinit.sh"
10
10
  },
11
11
  "dependencies": {
12
- "next": "14.x",
13
- "react": "18.x",
14
- "react-dom": "18.x",
15
- "@tidecloak/nextjs": "^0.9.12"
12
+ "@tidecloak/nextjs": "^0.9.12",
13
+ "eslint-config-next": "^16.0.1",
14
+ "next": "^16.0.1",
15
+ "react": "^19.2.0",
16
+ "react-dom": "^19.2.0"
16
17
  }
17
18
  }
@@ -111,7 +111,7 @@
111
111
  "providerId": "declarative-user-profile",
112
112
  "config": {
113
113
  "kc.user.profile.config": [
114
- "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}"
114
+ "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}],\"unmanagedAttributePolicy\":\"ENABLED\"}"
115
115
  ]
116
116
  }
117
117
  }
@@ -1,9 +1,26 @@
1
1
  #!/usr/bin/env bash
2
+ set -euo pipefail
2
3
 
3
- # Load overrides from .env in the project root
4
- if [ -f "./.env.example" ]; then
5
- # shellcheck disable=SC1090
6
- source "./.env.example"
4
+ # ─────────────────────────────────────────────────────────────────────────────
5
+ # Resolve script directory (run from anywhere)
6
+ # ─────────────────────────────────────────────────────────────────────────────
7
+ SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)"
8
+
9
+ # ─────────────────────────────────────────────────────────────────────────────
10
+ # Load overrides from .env.example (CRLF-safe)
11
+ # ─────────────────────────────────────────────────────────────────────────────
12
+ ENV_FILE="${SCRIPT_DIR}/.env.example"
13
+ if [[ -f "$ENV_FILE" ]]; then
14
+ if grep -q $'\r' "$ENV_FILE"; then
15
+ TMP_ENV="$(mktemp)"
16
+ tr -d '\r' < "$ENV_FILE" > "$TMP_ENV"
17
+ # shellcheck disable=SC1090
18
+ source "$TMP_ENV"
19
+ rm -f "$TMP_ENV"
20
+ else
21
+ # shellcheck disable=SC1090
22
+ source "$ENV_FILE"
23
+ fi
7
24
  fi
8
25
 
9
26
  # ─────────────────────────────────────────────────────────────────────────────
@@ -11,23 +28,49 @@ fi
11
28
  # ─────────────────────────────────────────────────────────────────────────────
12
29
  TIDECLOAK_LOCAL_URL="${TIDECLOAK_LOCAL_URL:-http://localhost:8080}"
13
30
  CLIENT_APP_URL="${CLIENT_APP_URL:-http://localhost:3000}"
14
- REALM_JSON_PATH="${REALM_JSON_PATH:-./realm.json}"
15
- ADAPTER_OUTPUT_PATH="${ADAPTER_OUTPUT_PATH:-./tidecloak.json}"
31
+ ADAPTER_OUTPUT_PATH="${ADAPTER_OUTPUT_PATH:-${SCRIPT_DIR}/tidecloak.json}"
16
32
  NEW_REALM_NAME="${NEW_REALM_NAME:-nextjs-test}"
17
- REALM_MGMT_CLIENT_ID="realm-management"
18
- ADMIN_ROLE_NAME="tide-realm-admin"
33
+ REALM_MGMT_CLIENT_ID="${REALM_MGMT_CLIENT_ID:-realm-management}"
34
+ ADMIN_ROLE_NAME="${ADMIN_ROLE_NAME:-tide-realm-admin}"
19
35
  KC_USER="${KC_USER:-admin}"
20
36
  KC_PASSWORD="${KC_PASSWORD:-password}"
21
37
  CLIENT_NAME="${CLIENT_NAME:-myclient}"
22
38
 
23
39
  # ─────────────────────────────────────────────────────────────────────────────
24
- # sed -i portability
40
+ # Find realm.json robustly
41
+ # Priority: env → same dir → parent → current working dir
25
42
  # ─────────────────────────────────────────────────────────────────────────────
26
- if sed --version >/dev/null 2>&1; then
27
- SED_INPLACE=(-i)
28
- else
29
- SED_INPLACE=(-i '')
43
+ CANDIDATES=()
44
+ [[ "${REALM_JSON_PATH:-}" != "" ]] && CANDIDATES+=("${REALM_JSON_PATH}")
45
+ CANDIDATES+=("${SCRIPT_DIR}/realm.json" "${SCRIPT_DIR}/../realm.json" "$(pwd)/realm.json")
46
+
47
+ REALM_JSON_PATH=""
48
+ for p in "${CANDIDATES[@]}"; do
49
+ if [[ -f "$p" ]]; then REALM_JSON_PATH="$p"; break; fi
50
+ done
51
+
52
+ echo "🔍 realm.json search candidates:"
53
+ for p in "${CANDIDATES[@]}"; do echo " - $p"; done
54
+
55
+ if [[ -z "${REALM_JSON_PATH}" ]]; then
56
+ echo "❌ Could not find realm.json in the checked locations above." >&2
57
+ echo " Put realm.json next to the script: ${SCRIPT_DIR}/realm.json" >&2
58
+ echo " OR run with: REALM_JSON_PATH=/absolute/path/realm.json bash init/tcinit.sh" >&2
59
+ exit 1
30
60
  fi
61
+ echo "✅ Using realm.json: ${REALM_JSON_PATH}"
62
+
63
+ # ─────────────────────────────────────────────────────────────────────────────
64
+ # Dependency checks
65
+ # ─────────────────────────────────────────────────────────────────────────────
66
+ need_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "❌ Missing dependency: $1" >&2; exit 1; }; }
67
+ need_cmd curl
68
+ need_cmd jq
69
+ need_cmd sed
70
+ need_cmd mktemp
71
+
72
+ # sed -i portability
73
+ if sed --version >/dev/null 2>&1; then SED_INPLACE=(-i); else SED_INPLACE=(-i ''); fi
31
74
 
32
75
  # ─────────────────────────────────────────────────────────────────────────────
33
76
  # Helper: grab an admin token
@@ -42,19 +85,28 @@ get_admin_token() {
42
85
  | jq -r .access_token
43
86
  }
44
87
 
88
+ # ─────────────────────────────────────────────────────────────────────────────
89
+ # Cleanup handler
90
+ # ─────────────────────────────────────────────────────────────────────────────
91
+ TMP_REALM_JSON=""
92
+ cleanup() {
93
+ [[ -n "${TMP_REALM_JSON}" && -f "${TMP_REALM_JSON}" ]] && rm -f "${TMP_REALM_JSON}" || true
94
+ [[ -f "${SCRIPT_DIR}/.realm_name" ]] && rm -f "${SCRIPT_DIR}/.realm_name" || true
95
+ }
96
+ trap cleanup EXIT
97
+
45
98
  # ─────────────────────────────────────────────────────────────────────────────
46
99
  # Step 1: prepare realm JSON
47
100
  # ─────────────────────────────────────────────────────────────────────────────
48
101
  REALM_NAME="${NEW_REALM_NAME}"
49
- echo "${REALM_NAME}" > "./.realm_name"
102
+ echo "${REALM_NAME}" > "${SCRIPT_DIR}/.realm_name"
50
103
 
51
104
  TMP_REALM_JSON="$(mktemp)"
52
105
  cp "${REALM_JSON_PATH}" "${TMP_REALM_JSON}"
53
106
 
54
- # replace placeholders
55
107
  sed "${SED_INPLACE[@]}" "s|http://localhost:3000|${CLIENT_APP_URL}|g" "${TMP_REALM_JSON}"
56
- sed "${SED_INPLACE[@]}" "s|nextjs-test|${REALM_NAME}|g" "${TMP_REALM_JSON}"
57
- sed "${SED_INPLACE[@]}" "s|myclient|${CLIENT_NAME}|g" "${TMP_REALM_JSON}"
108
+ sed "${SED_INPLACE[@]}" "s|nextjs-test|${REALM_NAME}|g" "${TMP_REALM_JSON}"
109
+ sed "${SED_INPLACE[@]}" "s|myclient|${CLIENT_NAME}|g" "${TMP_REALM_JSON}"
58
110
 
59
111
  # ─────────────────────────────────────────────────────────────────────────────
60
112
  # Step 2: create realm (allow 409 if already exists)
@@ -80,17 +132,15 @@ fi
80
132
  TOKEN="$(get_admin_token)"
81
133
  echo "🔐 Initializing Tide realm + IGA..."
82
134
 
83
- response=$(curl -i -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/setUpTideRealm" \
135
+ curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/setUpTideRealm" \
84
136
  -H "Authorization: Bearer ${TOKEN}" \
85
137
  -H "Content-Type: application/x-www-form-urlencoded" \
86
- --data-urlencode "email=email@tide.org" 2>&1)
138
+ --data-urlencode "email=email@tide.org" >/dev/null
87
139
 
88
- # toggle IGA
89
140
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/toggle-iga" \
90
141
  -H "Authorization: Bearer ${TOKEN}" \
91
142
  -H "Content-Type: application/x-www-form-urlencoded" \
92
- --data-urlencode "isIGAEnabled=true" \
93
- > /dev/null
143
+ --data-urlencode "isIGAEnabled=true" >/dev/null
94
144
 
95
145
  echo "✅ Tide realm + IGA done."
96
146
 
@@ -103,7 +153,7 @@ approve_and_commit() {
103
153
  TOKEN="$(get_admin_token)"
104
154
  curl -s -X GET "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/${TYPE}/requests" \
105
155
  -H "Authorization: Bearer ${TOKEN}" \
106
- | jq -c '.[]' | while read -r req; do
156
+ | jq -c '.[]' | while IFS= read -r req; do
107
157
  payload=$(jq -n \
108
158
  --arg id "$(jq -r .draftRecordId <<< "${req}")" \
109
159
  --arg cst "$(jq -r .changeSetType <<< "${req}")" \
@@ -113,14 +163,12 @@ approve_and_commit() {
113
163
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/sign" \
114
164
  -H "Authorization: Bearer ${TOKEN}" \
115
165
  -H "Content-Type: application/json" \
116
- -d "${payload}" \
117
- > /dev/null
166
+ -d "${payload}" >/dev/null
118
167
 
119
168
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/tide-admin/change-set/commit" \
120
169
  -H "Authorization: Bearer ${TOKEN}" \
121
170
  -H "Content-Type: application/json" \
122
- -d "${payload}" \
123
- > /dev/null
171
+ -d "${payload}" >/dev/null
124
172
  done
125
173
  echo "✅ ${TYPE^} change-sets done."
126
174
  }
@@ -134,18 +182,15 @@ echo "👤 Creating new admin user..."
134
182
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users" \
135
183
  -H "Authorization: Bearer ${TOKEN}" \
136
184
  -H "Content-Type: application/json" \
137
- -d '{"username":"admin","email":"admin@tidecloak.com","firstName":"admin","lastName":"user","enabled":true}' \
138
- > /dev/null
185
+ -d '{"username":"admin","email":"admin@tidecloak.com","firstName":"admin","lastName":"user","enabled":true}' >/dev/null || true
139
186
 
140
187
  USER_ID=$(curl -s -X GET \
141
188
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users?username=admin" \
142
- -H "Authorization: Bearer ${TOKEN}" \
143
- | jq -r '.[0].id')
189
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
144
190
 
145
191
  CLIENT_UUID=$(curl -s -X GET \
146
192
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients?clientId=${REALM_MGMT_CLIENT_ID}" \
147
- -H "Authorization: Bearer ${TOKEN}" \
148
- | jq -r '.[0].id')
193
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
149
194
 
150
195
  ROLE_JSON=$(curl -s -X GET \
151
196
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients/${CLIENT_UUID}/roles/${ADMIN_ROLE_NAME}" \
@@ -154,8 +199,7 @@ ROLE_JSON=$(curl -s -X GET \
154
199
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/users/${USER_ID}/role-mappings/clients/${CLIENT_UUID}" \
155
200
  -H "Authorization: Bearer ${TOKEN}" \
156
201
  -H "Content-Type: application/json" \
157
- -d "[${ROLE_JSON}]" \
158
- > /dev/null
202
+ -d "[${ROLE_JSON}]" >/dev/null
159
203
 
160
204
  echo "✅ Admin user & role done."
161
205
 
@@ -216,32 +260,25 @@ UPDATED_JSON=$(jq --arg d "${CLIENT_APP_URL}" '.config.CustomAdminUIDomain = $d'
216
260
  curl -s -X PUT "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/identity-provider/instances/tide" \
217
261
  -H "Authorization: Bearer ${TOKEN}" \
218
262
  -H "Content-Type: application/json" \
219
- -d "${UPDATED_JSON}" \
220
- > /dev/null
263
+ -d "${UPDATED_JSON}" >/dev/null
221
264
 
222
265
  curl -s -X POST "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/sign-idp-settings" \
223
- -H "Authorization: Bearer ${TOKEN}" \
224
- > /dev/null
266
+ -H "Authorization: Bearer ${TOKEN}" >/dev/null
225
267
 
226
268
  echo "✅ CustomAdminUIDomain updated + signed."
227
269
 
228
-
229
270
  # ─────────────────────────────────────────────────────────────────────────────
230
- # Step 7: fetch adapter config + cleanup
271
+ # Step 7: fetch adapter config
231
272
  # ─────────────────────────────────────────────────────────────────────────────
232
273
  TOKEN="$(get_admin_token)"
233
274
  echo "📥 Fetching adapter config…"
234
275
  CLIENT_UUID=$(curl -s -X GET \
235
276
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/clients?clientId=${CLIENT_NAME}" \
236
- -H "Authorization: Bearer ${TOKEN}" \
237
- | jq -r '.[0].id')
277
+ -H "Authorization: Bearer ${TOKEN}" | jq -r '.[0].id')
238
278
 
239
279
  curl -s -X GET \
240
280
  "${TIDECLOAK_LOCAL_URL}/admin/realms/${REALM_NAME}/vendorResources/get-installations-provider?clientId=${CLIENT_UUID}&providerId=keycloak-oidc-keycloak-json" \
241
- -H "Authorization: Bearer ${TOKEN}" \
242
- > "${ADAPTER_OUTPUT_PATH}"
281
+ -H "Authorization: Bearer ${TOKEN}" > "${ADAPTER_OUTPUT_PATH}"
243
282
 
244
283
  echo "✅ Adapter config saved to ${ADAPTER_OUTPUT_PATH}"
245
- rm -f "${PROJECT_ROOT}/.realm_name" "${TMP_REALM_JSON}"
246
-
247
284
  echo "🎉 All done!"
@@ -9,12 +9,13 @@
9
9
  "init": "bash init/tcinit.sh"
10
10
  },
11
11
  "dependencies": {
12
- "next": "14.x",
13
- "react": "18.x",
14
- "react-dom": "18.x",
15
- "@tidecloak/nextjs": "^0.12.16"
12
+ "@tidecloak/nextjs": "^0.12.27",
13
+ "eslint-config-next": "^16.0.1",
14
+ "next": "^16.0.1",
15
+ "react": "^19.2.0",
16
+ "react-dom": "^19.2.0"
16
17
  },
17
- "devDependencies": {
18
+ "devDependencies": {
18
19
  "@types/node": "24.0.13",
19
20
  "@types/react": "19.1.8",
20
21
  "typescript": "5.8.3"
@@ -9,12 +9,13 @@
9
9
  "init": "bash init/tcinit.sh"
10
10
  },
11
11
  "dependencies": {
12
- "next": "14.x",
13
- "react": "18.x",
14
- "react-dom": "18.x",
15
- "@tidecloak/nextjs": "^0.9.12"
12
+ "@tidecloak/nextjs": "^0.9.12",
13
+ "eslint-config-next": "^16.0.1",
14
+ "next": "^16.0.1",
15
+ "react": "^19.2.0",
16
+ "react-dom": "^19.2.0"
16
17
  },
17
- "devDependencies": {
18
+ "devDependencies": {
18
19
  "@types/node": "24.0.13",
19
20
  "@types/react": "19.1.8",
20
21
  "typescript": "5.8.3"