1
0

rebrand.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #!/usr/bin/env node
  2. /**
  3. * This script is used to rebrand the app to a different UNACMS website.
  4. */
  5. const fs = require("fs").promises;
  6. const path = require("path");
  7. const readline = require("readline");
  8. const { exec } = require("child_process");
  9. const root = process.cwd();
  10. const settingsPath = path.join(root, "constants", "settings.ts");
  11. const appJsonPath = path.join(root, "app.json");
  12. // Helper to ask questions with async/await
  13. function askQuestion(query) {
  14. const rl = readline.createInterface({
  15. input: process.stdin,
  16. output: process.stdout,
  17. });
  18. return new Promise((resolve) => rl.question(query, (ans) => {
  19. rl.close();
  20. resolve(ans);
  21. }));
  22. }
  23. (async () => {
  24. try {
  25. // --------- replace UNA URL
  26. await (async () => {
  27. const answer = await askQuestion("Your UNA site URL: ");
  28. const userInput = answer.trim().replace(/\/$/, "").toLowerCase();
  29. // Simple URL validation (domain or https://...)
  30. const urlPattern = /^(https?:\/\/)?([a-z0-9-]+\.)+[a-z]{2,}(\/[a-zA-Z0-9\-._~:/?#[\]@!$&'()*+,;=]*)?$/i;
  31. if (!userInput || !urlPattern.test(userInput)) {
  32. console.log("❌ Invalid input. Please enter a valid URL.");
  33. return;
  34. }
  35. const newUrl = userInput.startsWith("http") ? userInput : `https://${userInput}`;
  36. let settingsData = await fs.readFile(settingsPath, "utf8");
  37. settingsData = settingsData.replace(
  38. /export const UNA_URL\s*=\s*["'`].*?["'`];/,
  39. `export const UNA_URL = "${newUrl}";`
  40. );
  41. await fs.writeFile(settingsPath, settingsData, "utf8");
  42. console.log(`✅ UNA_URL updated to: ${newUrl}`);
  43. })();
  44. // --------- replace Bundle ID
  45. await (async () => {
  46. const answer1 = await askQuestion("Your app bundle id or package name (for example: com.example.app): ");
  47. const bundleInput = answer1.trim().toLowerCase();
  48. const nameInput = await askQuestion("Your app name: ");
  49. const name = nameInput.trim();
  50. const bundleId = bundleInput.trim();
  51. const bundlePattern = /^([a-zA-Z0-9]+\.)+[a-zA-Z0-9]+$/;
  52. if (!bundlePattern.test(bundleId)) {
  53. console.log("❌ Invalid bundle ID.");
  54. return;
  55. }
  56. const appJsonData = await fs.readFile(appJsonPath, "utf8");
  57. const appJson = JSON.parse(appJsonData);
  58. const scheme = name.toLowerCase.replace(/[^a-z0-9]/g, "");
  59. const slug = name
  60. .toLowerCase()
  61. .replace(/\s+/g, "-") // spaces → hyphens
  62. .replace(/[^a-z0-9-]/g, ""); // remove invalid characters
  63. appJson.expo.name = name;
  64. appJson.expo.slug = slug;
  65. appJson.expo.scheme = scheme;
  66. appJson.expo = appJson.expo || {};
  67. appJson.expo.android = appJson.expo.android || {};
  68. appJson.expo.ios = appJson.expo.ios || {};
  69. appJson.expo.android.package = bundleId;
  70. appJson.expo.ios.bundleIdentifier = bundleId;
  71. await fs.writeFile(appJsonPath, JSON.stringify(appJson, null, 2), "utf8");
  72. console.log(`✅ Bundle ID updated to: ${bundleId}`);
  73. })();
  74. // --------- recreate `ios` and `android` folders
  75. await (async () => {
  76. const answer = await askQuestion("Recreate native app folders (Y or N): ");
  77. const userInput = answer.trim().toLowerCase();
  78. if (userInput != 'y' && userInput != 'n' && userInput != '') {
  79. console.log("❌ Answer Y or N.");
  80. return;
  81. }
  82. if (userInput == 'y' || userInput == '') {
  83. // Delete android and ios folders if they exist
  84. const androidPath = path.join(root, "android");
  85. const iosPath = path.join(root, "ios");
  86. try {
  87. await fs.rm(androidPath, { recursive: true, force: true });
  88. await fs.rm(iosPath, { recursive: true, force: true });
  89. console.log("✅ Old native folders deleted");
  90. } catch (err) {
  91. console.error("❌ Failed to delete native folders:", err);
  92. }
  93. // Recreate native folders using expo prebuild
  94. try {
  95. await new Promise((resolve, reject) => {
  96. console.log("Recreating...");
  97. exec("npx expo prebuild", (err, stdout, stderr) => {
  98. if (err) {
  99. console.error("❌ Failed to run expo prebuild:", err);
  100. reject(err);
  101. } else {
  102. console.log(stdout);
  103. resolve(stdout);
  104. }
  105. });
  106. });
  107. console.log("✅ Native app folders were recreated");
  108. } catch (err) {
  109. console.error("❌ Error during prebuild:", err);
  110. }
  111. }
  112. if (userInput == 'n') {
  113. console.log("⚠️ You chose not to recreate native folders. Some changes may not take effect in native builds.");
  114. }
  115. })();
  116. } catch (err) {
  117. console.error("❌ An error occurred:", err);
  118. const userInput = answer.trim().toLowerCase();
  119. }
  120. })();