@rodyssey/cli 0.1.7 → 0.1.9

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.
Files changed (2) hide show
  1. package/dist/cli.js +91 -31
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2071,7 +2071,7 @@ var {
2071
2071
  // package.json
2072
2072
  var package_default = {
2073
2073
  name: "@rodyssey/cli",
2074
- version: "0.1.7",
2074
+ version: "0.1.9",
2075
2075
  description: "Scaffold new projects from airconcepts templates",
2076
2076
  repository: {
2077
2077
  type: "git",
@@ -2211,7 +2211,7 @@ function storeSession(session) {
2211
2211
  function resolveSessionToken(env) {
2212
2212
  const token = process.env.CMS_TOKEN || getStoredSession(env)?.token;
2213
2213
  if (!token) {
2214
- throw new Error(`No CMS auth token found for [${env}]. Run \`ro app auth login --env ${env}\` first.`);
2214
+ throw new Error(`No CMS auth token found for [${env}]. Run \`ro auth login --env ${env}\` first.`);
2215
2215
  }
2216
2216
  return token;
2217
2217
  }
@@ -2312,7 +2312,7 @@ async function me(options) {
2312
2312
  const storedSession = getStoredSession(options.env);
2313
2313
  if (!options.remote) {
2314
2314
  if (!storedSession) {
2315
- throw new Error(`No local CMS session found for [${options.env}]. Run \`ro app auth login --env ${options.env}\` first.`);
2315
+ throw new Error(`No local CMS session found for [${options.env}]. Run \`ro auth login --env ${options.env}\` first.`);
2316
2316
  }
2317
2317
  return {
2318
2318
  env: storedSession.env,
@@ -2377,12 +2377,13 @@ function replaceInFiles(dir, filenames, search, replace) {
2377
2377
  } catch {}
2378
2378
  }
2379
2379
  }
2380
- function loadEnv(envName) {
2380
+ function loadEnv(envName, options = {}) {
2381
2381
  const files = [];
2382
2382
  if (envName) {
2383
2383
  files.push(`.env.${envName}`);
2384
2384
  }
2385
2385
  files.push(".env");
2386
+ const loaded = {};
2386
2387
  for (const file of files) {
2387
2388
  if (!existsSync2(file))
2388
2389
  continue;
@@ -2400,11 +2401,16 @@ function loadEnv(envName) {
2400
2401
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2401
2402
  value = value.slice(1, -1);
2402
2403
  }
2403
- if (process.env[key] === undefined) {
2404
- process.env[key] = value;
2404
+ if (loaded[key] === undefined) {
2405
+ loaded[key] = value;
2405
2406
  }
2406
2407
  }
2407
2408
  }
2409
+ for (const [key, value] of Object.entries(loaded)) {
2410
+ if (options.override || process.env[key] === undefined) {
2411
+ process.env[key] = value;
2412
+ }
2413
+ }
2408
2414
  }
2409
2415
 
2410
2416
  // src/create.ts
@@ -4142,7 +4148,59 @@ function isAffirmative(answer) {
4142
4148
  const trimmed = answer.trim().toLowerCase();
4143
4149
  return trimmed === "" || trimmed === "y" || trimmed === "yes";
4144
4150
  }
4151
+ function isExplicitYes(answer) {
4152
+ const trimmed = answer.trim().toLowerCase();
4153
+ return trimmed === "y" || trimmed === "yes";
4154
+ }
4155
+ function assertDeployOptions(options) {
4156
+ if (options.deploy && options.skipDeploy) {
4157
+ console.error("❌ Error: Use either --deploy or --skip-deploy, not both.");
4158
+ process.exit(1);
4159
+ }
4160
+ }
4161
+ async function maybeDeployProduction(options, webappId, deployToken) {
4162
+ const deployRequested = options.deploy === true;
4163
+ const deploySkipped = options.skipDeploy === true;
4164
+ if (deploySkipped) {
4165
+ console.log(`
4166
+ ↷ Skipping production deploy.`);
4167
+ console.log(`Deploy later with:
4168
+ `);
4169
+ console.log(` ro app deploy -e production
4170
+ `);
4171
+ return;
4172
+ }
4173
+ let shouldDeploy = deployRequested;
4174
+ if (!shouldDeploy) {
4175
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
4176
+ console.log(`
4177
+ ✨ Promotion complete! Deploy to production with:
4178
+ `);
4179
+ console.log(` ro app deploy -e production
4180
+ `);
4181
+ return;
4182
+ }
4183
+ const answer = await prompt(`
4184
+ Deploy to production now? (y/N): `);
4185
+ shouldDeploy = isExplicitYes(answer);
4186
+ }
4187
+ if (!shouldDeploy) {
4188
+ console.log(`
4189
+ ✨ Promotion complete! Deploy to production with:
4190
+ `);
4191
+ console.log(` ro app deploy -e production
4192
+ `);
4193
+ return;
4194
+ }
4195
+ console.log(`
4196
+ \uD83D\uDE80 Deploying promoted webapp to production...`);
4197
+ loadEnv(PROD_ENV, { override: true });
4198
+ process.env.WEBAPP_ID = webappId;
4199
+ process.env.DEPLOY_TOKEN = deployToken;
4200
+ await deploy(PROD_ENV);
4201
+ }
4145
4202
  async function promote(options) {
4203
+ assertDeployOptions(options);
4146
4204
  loadEnv();
4147
4205
  const webappId = process.env.WEBAPP_ID;
4148
4206
  if (!webappId) {
@@ -4231,11 +4289,7 @@ ${JSON.stringify(payload, null, 2)}`);
4231
4289
  });
4232
4290
  console.log(`✅ Wrote WEBAPP_ID and DEPLOY_TOKEN to ${PROD_ENV_FILE}`);
4233
4291
  console.log(`\uD83D\uDCCD Webapp ID: ${webappId}`);
4234
- console.log(`
4235
- ✨ Promotion complete! Deploy to production with:
4236
- `);
4237
- console.log(` ro app deploy -e production
4238
- `);
4292
+ await maybeDeployProduction(options, webappId, deployToken);
4239
4293
  }
4240
4294
 
4241
4295
  // src/upgrade-template.ts
@@ -4593,6 +4647,28 @@ function addConfigTargetOptions(command) {
4593
4647
  function addConfigSetOptions(command) {
4594
4648
  return addConfigTargetOptions(command).option("--title <title>", "Webapp title (pass the literal 'null' to clear)").option("--description <description>", "Webapp description (pass the literal 'null' to clear)").option("--cover-img <url>", "Cover image URL (pass the literal 'null' to clear)").option("--localization <json-or-file>", "Localization JSON object, path to a JSON file, or 'null' to clear").option("--details <json-or-file>", "Partial WebappDetails JSON or path to a JSON file. Sent as a delta — only include keys you want to change. Do NOT echo a full GET response here, or empty defaults like 'tags: []' will clobber real data.").option("--dry-run", "Print the request payload without sending it");
4595
4649
  }
4650
+ function addAuthCommands(parent) {
4651
+ const auth = parent.command("auth").description("Authenticate with the CMS");
4652
+ auth.command("login").description("Log in to the CMS using a browser callback").option("-e, --env <environment>", "CMS environment (local | development | staging | production)", "development").option("--cms-url <url>", "CMS base URL. Defaults to the selected environment").option("--login-url <url>", "Full browser login URL. Defaults to <cms-url>/auth/cli-login").option("--token-url <url>", "Full token exchange URL. Defaults to <cms-url>/api/auth/cli-token").option("--callback-port <port>", "Local callback port. Defaults to a random free port", parseInt).option("--timeout <seconds>", "Seconds to wait for the browser callback", parseInt, 300).option("--no-open", "Print the login URL without opening a browser").action(async (options) => {
4653
+ const session = await login({
4654
+ env: options.env,
4655
+ cmsUrl: options.cmsUrl,
4656
+ loginUrl: options.loginUrl,
4657
+ tokenUrl: options.tokenUrl,
4658
+ callbackPort: options.callbackPort,
4659
+ open: options.open,
4660
+ timeoutMs: (options.timeout ?? 300) * 1000
4661
+ });
4662
+ console.log(`✅ Logged in to CMS [${session.env}]`);
4663
+ console.log(`\uD83D\uDCCD CMS URL: ${session.cmsUrl}`);
4664
+ });
4665
+ auth.command("me").description("Show the locally stored CMS login session").option("-e, --env <environment>", "CMS environment (local | development | staging | production)", "development").option("--remote", "Call the CMS /me endpoint instead of only reading the local session").option("--cms-url <url>", "CMS base URL for --remote. Defaults to the selected environment or stored session").option("--me-url <url>", "Full me endpoint URL for --remote. Defaults to <cms-url>/api/auth/me").action(async (options) => {
4666
+ const currentUser = await me(options);
4667
+ console.log(JSON.stringify(currentUser, null, 2));
4668
+ });
4669
+ return auth;
4670
+ }
4671
+ addAuthCommands(program);
4596
4672
  app.command("create").argument("<project-name>", "Name of the project to create").option("-t, --template <template>", "Template to use (webapp | webapp-fullstack)").option("--auto", "Create a CMS webapp and write WEBAPP_ID/DEPLOY_TOKEN to .env").option("-e, --env <environment>", "CMS environment for --auto (local | development | staging | production)", "development").option("--cms-url <url>", "CMS base URL for --auto. Defaults to the selected environment").option("--create-url <url>", "Full CMS create endpoint for --auto. Defaults to <cms-url>/api/cli/webapps/create").description("Create a new project from a template").action(async (projectName, options) => {
4597
4673
  let templateName;
4598
4674
  if (options.template) {
@@ -4612,13 +4688,15 @@ app.command("create").argument("<project-name>", "Name of the project to create"
4612
4688
  createUrl: options.createUrl
4613
4689
  });
4614
4690
  });
4615
- app.command("promote").description("Promote the current webapp to production (creates a prod record with the same WEBAPP_ID)").option("--details <json-or-file>", "Full WebappDetails JSON object or path to a JSON file. Skips the source-pull and confirmation prompts when provided.").option("-y, --yes", "Auto-accept pulling the latest details from development").option("--cms-url <url>", "Production CMS base URL. Defaults to the production environment").option("--promote-url <url>", "Full CMS promote endpoint. Defaults to <cms-url>/api/cli/webapps/promote").option("--from <env>", "Source environment to pull details from (testing override). Defaults to development", "development").action(async (options) => {
4691
+ app.command("promote").description("Promote the current webapp to production (creates a prod record with the same WEBAPP_ID)").option("--details <json-or-file>", "Full WebappDetails JSON object or path to a JSON file. Skips the source-pull and confirmation prompts when provided.").option("-y, --yes", "Auto-accept pulling the latest details from development").option("--cms-url <url>", "Production CMS base URL. Defaults to the production environment").option("--promote-url <url>", "Full CMS promote endpoint. Defaults to <cms-url>/api/cli/webapps/promote").option("--from <env>", "Source environment to pull details from (testing override). Defaults to development", "development").option("--deploy", "Deploy to production immediately after promotion").option("--skip-deploy", "Do not ask to deploy after promotion").action(async (options) => {
4616
4692
  await promote({
4617
4693
  details: options.details,
4618
4694
  yes: options.yes,
4619
4695
  cmsUrl: options.cmsUrl,
4620
4696
  promoteUrl: options.promoteUrl,
4621
- from: options.from
4697
+ from: options.from,
4698
+ deploy: options.deploy,
4699
+ skipDeploy: options.skipDeploy
4622
4700
  });
4623
4701
  });
4624
4702
  app.command("update-game-sdk").description("Download and update the GameSDK library, types, and documentation").action(async () => {
@@ -4627,24 +4705,6 @@ app.command("update-game-sdk").description("Download and update the GameSDK libr
4627
4705
  app.command("deploy").description("Build and deploy the webapp to the server").option("-e, --env <environment>", "Target environment (local | development | staging | production)", "development").option("--host <host>", "Override the deploy host").option("--port <port>", "Override the deploy port", parseInt).action(async (options) => {
4628
4706
  await deploy(options.env, { host: options.host, port: options.port });
4629
4707
  });
4630
- var auth = app.command("auth").description("Authenticate with the CMS");
4631
- auth.command("login").description("Log in to the CMS using a browser callback").option("-e, --env <environment>", "CMS environment (local | development | staging | production)", "development").option("--cms-url <url>", "CMS base URL. Defaults to the selected environment").option("--login-url <url>", "Full browser login URL. Defaults to <cms-url>/auth/cli-login").option("--token-url <url>", "Full token exchange URL. Defaults to <cms-url>/api/auth/cli-token").option("--callback-port <port>", "Local callback port. Defaults to a random free port", parseInt).option("--timeout <seconds>", "Seconds to wait for the browser callback", parseInt, 300).option("--no-open", "Print the login URL without opening a browser").action(async (options) => {
4632
- const session = await login({
4633
- env: options.env,
4634
- cmsUrl: options.cmsUrl,
4635
- loginUrl: options.loginUrl,
4636
- tokenUrl: options.tokenUrl,
4637
- callbackPort: options.callbackPort,
4638
- open: options.open,
4639
- timeoutMs: (options.timeout ?? 300) * 1000
4640
- });
4641
- console.log(`✅ Logged in to CMS [${session.env}]`);
4642
- console.log(`\uD83D\uDCCD CMS URL: ${session.cmsUrl}`);
4643
- });
4644
- auth.command("me").description("Show the locally stored CMS login session").option("-e, --env <environment>", "CMS environment (local | development | staging | production)", "development").option("--remote", "Call the CMS /me endpoint instead of only reading the local session").option("--cms-url <url>", "CMS base URL for --remote. Defaults to the selected environment or stored session").option("--me-url <url>", "Full me endpoint URL for --remote. Defaults to <cms-url>/api/auth/me").action(async (options) => {
4645
- const currentUser = await me(options);
4646
- console.log(JSON.stringify(currentUser, null, 2));
4647
- });
4648
4708
  var config = app.command("config").description("Manage webapp metadata config");
4649
4709
  addConfigTargetOptions(config.command("get").description("Pull the current webapp metadata config from the CMS").option("--out <file>", "Write the config JSON to a file")).action(async (options) => {
4650
4710
  await getWebappConfig(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rodyssey/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Scaffold new projects from airconcepts templates",
5
5
  "repository": {
6
6
  "type": "git",