unoverse 0.1.29 → 0.1.30

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/lib/create.mjs CHANGED
@@ -214,6 +214,22 @@ export async function create(nameArg) {
214
214
  }
215
215
 
216
216
  if (choice === "2") {
217
+ // ALREADY A UNIVERSE? Then this is a re-run, not a conflict. The first create
218
+ // scaffolds the files; if setup was interrupted (Ctrl-C at any question), running
219
+ // create again used to refuse with "this folder is not empty" — which reads as
220
+ // broken when the folder holds exactly what create itself put there. A universe is
221
+ // recognized by its compose file; resume setup instead.
222
+ const target = nameArg || ".";
223
+ if (existsSync(`${target}/docker-compose.yml`)) {
224
+ console.log(`\n ${dim(`${target === "." ? "This folder" : `./${target}`} is already a universe. Picking setup back up.`)}\n`);
225
+ rl.close();
226
+ const here2 = dirname(fileURLToPath(import.meta.url));
227
+ const vend = resolve(here2, "../operator/operator.sh");
228
+ const op = existsSync(vend) ? vend : resolve(here2, "../../../scripts/operator.sh");
229
+ const r2 = spawnSync("bash", [op, "init"], { stdio: "inherit", cwd: target });
230
+ process.exit(r2.status ?? 0);
231
+ }
232
+
217
233
  // TARGET FIRST, credential second. This used to ask for the registry token, make a
218
234
  // network round-trip to validate it, and only then discover the folder was not
219
235
  // empty. Never ask for a credential you are about to throw away.
@@ -77,22 +77,19 @@ cmd_init() {
77
77
  echo ""
78
78
  fi
79
79
 
80
- # Check for existing .env
81
- if [ -f "$ROOT/.env" ]; then
82
- echo ""
83
- read -r -p " .env already exists. Overwrite? [y/N] " REPLY
84
- echo ""
85
- if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then
86
- info "Keeping existing .env"
87
- cmd_login
88
- cmd_pull
89
- return
90
- fi
91
- fi
80
+ # RE-RUNNING EDITS. There is no "overwrite? [y/N]" gate any more: every existing value
81
+ # becomes its question's default, so Enter keeps a setting and typing replaces it.
82
+ # Walking through changes only what you change — which makes this the way to change
83
+ # one env var, not a destructive restart.
84
+ _env_cur() { grep "^$1=" "$ROOT/.env" 2>/dev/null | head -1 | cut -d= -f2-; }
92
85
 
93
86
  echo ""
94
87
  echo -e " ${BOLD}Configure your environment:${NC}"
95
- echo -e " ${DIM}(Press Enter to use defaults)${NC}"
88
+ if [ -f "$ROOT/.env" ]; then
89
+ echo -e " ${DIM}(Existing .env found. Enter keeps each current value)${NC}"
90
+ else
91
+ echo -e " ${DIM}(Press Enter to use defaults)${NC}"
92
+ fi
96
93
  echo ""
97
94
 
98
95
  # DOCR Token. `unoverse create` has already asked for this and VALIDATED it against
@@ -102,8 +99,15 @@ cmd_init() {
102
99
  DOCR_TOKEN="$UNOVERSE_DOCR_TOKEN"
103
100
  ok "Registry token carried over from create"
104
101
  else
102
+ local cur_token
103
+ cur_token=$(_env_cur DOCR_TOKEN)
105
104
  while true; do
106
- read -p " DOCR Token (from your Unoverse admin): " DOCR_TOKEN || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
105
+ if [ -n "$cur_token" ]; then
106
+ read -p " DOCR Token [keep current]: " DOCR_TOKEN || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
107
+ DOCR_TOKEN="${DOCR_TOKEN:-$cur_token}"
108
+ else
109
+ read -p " DOCR Token (from your Unoverse admin): " DOCR_TOKEN || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
110
+ fi
107
111
  if [[ "$DOCR_TOKEN" == dop_v1_* ]]; then
108
112
  break
109
113
  fi
@@ -114,7 +118,8 @@ cmd_init() {
114
118
  # A DEFAULT, because "from your admin" is meaningless when you are the admin. The
115
119
  # platform ships no database (docker-compose has no postgres), so this points at one
116
120
  # you run. Enter takes the conventional local one.
117
- DB_DEFAULT="postgres://postgres:postgres@localhost:5432/unoverse"
121
+ DB_DEFAULT=$(_env_cur DATABASE_URL)
122
+ DB_DEFAULT="${DB_DEFAULT:-postgres://postgres:postgres@localhost:5432/unoverse}"
118
123
  while true; do
119
124
  read -p " DATABASE_URL [${DB_DEFAULT}]: " DATABASE_URL || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
120
125
  DATABASE_URL="${DATABASE_URL:-$DB_DEFAULT}"
@@ -139,17 +144,27 @@ cmd_init() {
139
144
  fi
140
145
  fi
141
146
 
142
- # Redis
143
- read -p " REDIS_HOST [host.docker.internal]: " REDIS_HOST
144
- REDIS_HOST="${REDIS_HOST:-host.docker.internal}"
147
+ # Redis, current values as defaults
148
+ local rd
149
+ rd=$(_env_cur REDIS_HOST); rd="${rd:-host.docker.internal}"
150
+ read -p " REDIS_HOST [$rd]: " REDIS_HOST
151
+ REDIS_HOST="${REDIS_HOST:-$rd}"
145
152
 
146
- read -p " REDIS_PORT [6379]: " REDIS_PORT
147
- REDIS_PORT="${REDIS_PORT:-6379}"
153
+ rd=$(_env_cur REDIS_PORT); rd="${rd:-6379}"
154
+ read -p " REDIS_PORT [$rd]: " REDIS_PORT
155
+ REDIS_PORT="${REDIS_PORT:-$rd}"
148
156
 
149
- read -p " REDIS_PASSWORD (blank for none): " REDIS_PASSWORD
157
+ rd=$(_env_cur REDIS_PASSWORD)
158
+ if [ -n "$rd" ]; then
159
+ read -p " REDIS_PASSWORD [keep current]: " REDIS_PASSWORD
160
+ REDIS_PASSWORD="${REDIS_PASSWORD:-$rd}"
161
+ else
162
+ read -p " REDIS_PASSWORD (blank for none): " REDIS_PASSWORD
163
+ fi
150
164
 
151
- read -p " REDIS_TLS [false]: " REDIS_TLS
152
- REDIS_TLS="${REDIS_TLS:-false}"
165
+ rd=$(_env_cur REDIS_TLS); rd="${rd:-false}"
166
+ read -p " REDIS_TLS [$rd]: " REDIS_TLS
167
+ REDIS_TLS="${REDIS_TLS:-$rd}"
153
168
 
154
169
  # Auth (required — from admin)
155
170
  # ASK BEFORE DEMANDING. A developer trying the platform locally has no identity
@@ -160,13 +175,28 @@ cmd_init() {
160
175
  # rather than trusting this wizard: authConfig.ts refuses to start with auth off when
161
176
  # NODE_ENV=production. So answering "no" here cannot produce an unprotected deployment.
162
177
  echo ""
163
- read -r -p " Do you have an identity provider (Auth0/OIDC) to connect? [y/N] " HAS_IDP
178
+ local cur_auth idp_prompt
179
+ cur_auth=$(_env_cur AUTH_ENABLED)
180
+ idp_prompt="[y/N]"
181
+ [ "$cur_auth" = "true" ] && idp_prompt="[Y/n]"
182
+ read -r -p " Do you have an identity provider (Auth0/OIDC) to connect? $idp_prompt " HAS_IDP
164
183
  echo ""
184
+ if [ -z "$HAS_IDP" ] && [ "$cur_auth" = "true" ]; then HAS_IDP=y; fi
165
185
 
166
186
  if [[ "$HAS_IDP" =~ ^[Yy]$ ]]; then
167
187
  AUTH_ENABLED=true
188
+ local cur_iss cur_cid cur_aud
189
+ cur_iss=$(_env_cur AUTH_ISSUER)
190
+ cur_cid=$(_env_cur AUTH_CLIENT_ID)
191
+ cur_aud=$(_env_cur AUTH_AUDIENCE)
192
+
168
193
  while true; do
169
- read -p " AUTH_ISSUER (e.g. https://your-tenant.auth0.com): " AUTH_ISSUER || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
194
+ if [ -n "$cur_iss" ]; then
195
+ read -p " AUTH_ISSUER [$cur_iss]: " AUTH_ISSUER || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
196
+ AUTH_ISSUER="${AUTH_ISSUER:-$cur_iss}"
197
+ else
198
+ read -p " AUTH_ISSUER (e.g. https://your-tenant.auth0.com): " AUTH_ISSUER || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
199
+ fi
170
200
  if [ -n "$AUTH_ISSUER" ] && [[ "$AUTH_ISSUER" == https://* ]]; then
171
201
  break
172
202
  fi
@@ -174,15 +204,21 @@ cmd_init() {
174
204
  done
175
205
 
176
206
  while true; do
177
- read -p " AUTH_CLIENT_ID: " AUTH_CLIENT_ID || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
207
+ if [ -n "$cur_cid" ]; then
208
+ read -p " AUTH_CLIENT_ID [$cur_cid]: " AUTH_CLIENT_ID || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
209
+ AUTH_CLIENT_ID="${AUTH_CLIENT_ID:-$cur_cid}"
210
+ else
211
+ read -p " AUTH_CLIENT_ID: " AUTH_CLIENT_ID || { fail "no input (end of stream). Run unoverse init interactively"; exit 1; }
212
+ fi
178
213
  if [ -n "$AUTH_CLIENT_ID" ] && [[ "$AUTH_CLIENT_ID" != *"your-"* ]]; then
179
214
  break
180
215
  fi
181
216
  fail "AUTH_CLIENT_ID is required"
182
217
  done
183
218
 
184
- read -p " AUTH_AUDIENCE [gravity-api]: " AUTH_AUDIENCE
185
- AUTH_AUDIENCE="${AUTH_AUDIENCE:-gravity-api}"
219
+ cur_aud="${cur_aud:-gravity-api}"
220
+ read -p " AUTH_AUDIENCE [$cur_aud]: " AUTH_AUDIENCE
221
+ AUTH_AUDIENCE="${AUTH_AUDIENCE:-$cur_aud}"
186
222
  else
187
223
  AUTH_ENABLED=false
188
224
  AUTH_ISSUER=""
@@ -207,7 +243,14 @@ cmd_init() {
207
243
  ok "Redis namespace: ${BOLD}${REDIS_NAMESPACE}${NC}"
208
244
 
209
245
  # OpenAI (for Memory Server)
210
- read -p " OPENAI_API_KEY (for Memory Server, blank to skip): " OPENAI_API_KEY
246
+ local cur_oai
247
+ cur_oai=$(_env_cur OPENAI_API_KEY)
248
+ if [ -n "$cur_oai" ]; then
249
+ read -p " OPENAI_API_KEY [keep current]: " OPENAI_API_KEY
250
+ OPENAI_API_KEY="${OPENAI_API_KEY:-$cur_oai}"
251
+ else
252
+ read -p " OPENAI_API_KEY (for Memory Server, blank to skip): " OPENAI_API_KEY
253
+ fi
211
254
 
212
255
  # Write .env
213
256
  cat > "$ROOT/.env" << ENVEOF
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unoverse",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "The Unoverse front door — create a Studio project, a universe, or a client app, and launch Studio.",
5
5
  "license": "SEE LICENSE IN README.md",
6
6
  "type": "module",