@apps-in-toss/cli 0.0.0-dev.1747216176095 → 0.0.0-dev.1752049503789

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 (3) hide show
  1. package/dist/index.cjs +328 -58
  2. package/dist/index.js +327 -57
  3. package/package.json +8 -4
package/dist/index.cjs CHANGED
@@ -192,11 +192,11 @@ var require_common = __commonJS({
192
192
  let enableOverride = null;
193
193
  let namespacesCache;
194
194
  let enabledCache;
195
- function debug3(...args) {
196
- if (!debug3.enabled) {
195
+ function debug5(...args) {
196
+ if (!debug5.enabled) {
197
197
  return;
198
198
  }
199
- const self = debug3;
199
+ const self = debug5;
200
200
  const curr = Number(/* @__PURE__ */ new Date());
201
201
  const ms = curr - (prevTime || curr);
202
202
  self.diff = ms;
@@ -226,12 +226,12 @@ var require_common = __commonJS({
226
226
  const logFn = self.log || createDebug.log;
227
227
  logFn.apply(self, args);
228
228
  }
229
- debug3.namespace = namespace;
230
- debug3.useColors = createDebug.useColors();
231
- debug3.color = createDebug.selectColor(namespace);
232
- debug3.extend = extend;
233
- debug3.destroy = createDebug.destroy;
234
- Object.defineProperty(debug3, "enabled", {
229
+ debug5.namespace = namespace;
230
+ debug5.useColors = createDebug.useColors();
231
+ debug5.color = createDebug.selectColor(namespace);
232
+ debug5.extend = extend;
233
+ debug5.destroy = createDebug.destroy;
234
+ Object.defineProperty(debug5, "enabled", {
235
235
  enumerable: true,
236
236
  configurable: false,
237
237
  get: () => {
@@ -249,9 +249,9 @@ var require_common = __commonJS({
249
249
  }
250
250
  });
251
251
  if (typeof createDebug.init === "function") {
252
- createDebug.init(debug3);
252
+ createDebug.init(debug5);
253
253
  }
254
- return debug3;
254
+ return debug5;
255
255
  }
256
256
  function extend(namespace, delimiter) {
257
257
  const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
@@ -517,7 +517,7 @@ var require_node = __commonJS({
517
517
  var tty = require("tty");
518
518
  var util = require("util");
519
519
  exports2.init = init;
520
- exports2.log = log3;
520
+ exports2.log = log4;
521
521
  exports2.formatArgs = formatArgs;
522
522
  exports2.save = save;
523
523
  exports2.load = load;
@@ -652,7 +652,7 @@ var require_node = __commonJS({
652
652
  }
653
653
  return (/* @__PURE__ */ new Date()).toISOString() + " ";
654
654
  }
655
- function log3(...args) {
655
+ function log4(...args) {
656
656
  return process.stderr.write(util.formatWithOptions(exports2.inspectOpts, ...args) + "\n");
657
657
  }
658
658
  function save(namespaces) {
@@ -665,11 +665,11 @@ var require_node = __commonJS({
665
665
  function load() {
666
666
  return process.env.DEBUG;
667
667
  }
668
- function init(debug3) {
669
- debug3.inspectOpts = {};
668
+ function init(debug5) {
669
+ debug5.inspectOpts = {};
670
670
  const keys = Object.keys(exports2.inspectOpts);
671
671
  for (let i = 0; i < keys.length; i++) {
672
- debug3.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
672
+ debug5.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
673
673
  }
674
674
  }
675
675
  module2.exports = require_common()(exports2);
@@ -703,10 +703,10 @@ var require_picocolors = __commonJS({
703
703
  "../../.yarn/cache/picocolors-npm-1.1.1-b0c45fa35e-e2e3e8170a.zip/node_modules/picocolors/picocolors.js"(exports2, module2) {
704
704
  "use strict";
705
705
  init_cjs_shims();
706
- var p3 = process || {};
707
- var argv = p3.argv || [];
708
- var env = p3.env || {};
709
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p3.platform === "win32" || (p3.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
706
+ var p4 = process || {};
707
+ var argv = p4.argv || [];
708
+ var env = p4.env || {};
709
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p4.platform === "win32" || (p4.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
710
710
  var formatter = (open, close, replace = open) => (input) => {
711
711
  let string = "" + input, index = string.indexOf(close, open.length);
712
712
  return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
@@ -779,7 +779,7 @@ __export(src_exports, {
779
779
  });
780
780
  module.exports = __toCommonJS(src_exports);
781
781
  init_cjs_shims();
782
- var import_clipanion3 = require("clipanion");
782
+ var import_clipanion4 = require("clipanion");
783
783
 
784
784
  // src/DeployCommand.ts
785
785
  init_cjs_shims();
@@ -787,9 +787,9 @@ var import_assert = __toESM(require("assert"), 1);
787
787
  var import_fs2 = __toESM(require("fs"), 1);
788
788
  var import_path = __toESM(require("path"), 1);
789
789
  var p = __toESM(require("@clack/prompts"), 1);
790
- var import_utils = require("@react-native-bedrock/utils");
790
+ var import_utils = require("@granite-js/utils");
791
791
  var import_clipanion = require("clipanion");
792
- var import_debug2 = __toESM(require_src(), 1);
792
+ var import_debug3 = __toESM(require_src(), 1);
793
793
  var import_picocolors = __toESM(require_picocolors(), 1);
794
794
 
795
795
  // src/utils/constants.ts
@@ -800,10 +800,30 @@ var DEFAULT_API_BASE_URL = "https://apps-in-toss.toss.im/console";
800
800
  // src/utils/upload.ts
801
801
  init_cjs_shims();
802
802
  var import_fs = __toESM(require("fs"), 1);
803
+ var import_debug2 = __toESM(require_src(), 1);
804
+
805
+ // src/utils/handleFetchResponse.ts
806
+ init_cjs_shims();
803
807
  var import_debug = __toESM(require_src(), 1);
804
- var debug = (0, import_debug.default)("cli:deploy");
808
+ var debug = (0, import_debug.default)("api");
809
+ async function handleFetchResponse(response) {
810
+ debug(`Response ${response.status} ${response.statusText}`);
811
+ if (!response.ok) {
812
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
813
+ }
814
+ const data = await response.clone().json();
815
+ debug("response", data);
816
+ if (data.resultType !== "SUCCESS") {
817
+ const errorCode = data?.error?.errorCode ?? "-1";
818
+ const errorReason = data?.error.reason ?? "unknown";
819
+ throw new Error(`${errorReason} (Code: ${errorCode})`);
820
+ }
821
+ }
822
+
823
+ // src/utils/upload.ts
824
+ var debug2 = (0, import_debug2.default)("cli:deploy");
805
825
  async function uploadArtifact(config) {
806
- debug("uploadArtifact", config);
826
+ debug2("uploadArtifact", config);
807
827
  const baseUrl = config.baseUrl ?? DEFAULT_API_BASE_URL;
808
828
  const response = await fetch(
809
829
  `${baseUrl}/api-public/v3/appsintossconsole/bundles/${config.appName}/deployments/${config.deploymentId}/upload`,
@@ -817,24 +837,11 @@ async function uploadArtifact(config) {
817
837
  duplex: "half"
818
838
  }
819
839
  );
820
- return handleResponse(response);
821
- }
822
- async function handleResponse(response) {
823
- debug(`Response ${response.status} ${response.statusText}`);
824
- if (!response.ok) {
825
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
826
- }
827
- const data = await response.clone().json();
828
- debug("uploadArtifact response", data);
829
- if (data.resultType !== "SUCCESS") {
830
- const errorCode = data?.error?.errorCode ?? "-1";
831
- const errorReason = data?.error.reason ?? "unknown";
832
- throw new Error(`${errorReason} (Code: ${errorCode})`);
833
- }
840
+ return handleFetchResponse(response);
834
841
  }
835
842
 
836
843
  // src/DeployCommand.ts
837
- var debug2 = (0, import_debug2.default)("cli:deploy");
844
+ var debug3 = (0, import_debug3.default)("cli:deploy");
838
845
  var DeployCommand = class extends import_clipanion.Command {
839
846
  static paths = [["deploy"]];
840
847
  apiKey = import_clipanion.Option.String("--api-key", {
@@ -873,7 +880,7 @@ var DeployCommand = class extends import_clipanion.Command {
873
880
  (0, import_assert.default)(typeof deploymentId2 === "string", "invalid deploymentId");
874
881
  return { appName: appName2, deploymentId: deploymentId2 };
875
882
  }).catch((error) => {
876
- debug2("invalid ait file", error);
883
+ debug3("invalid ait file", error);
877
884
  throw new Error("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 ait \uD30C\uC77C\uC785\uB2C8\uB2E4");
878
885
  });
879
886
  const colorAppName = import_picocolors.default.underline(import_picocolors.default.cyan(appName));
@@ -909,7 +916,7 @@ init_cjs_shims();
909
916
  var import_fs3 = __toESM(require("fs"), 1);
910
917
  var import_path2 = __toESM(require("path"), 1);
911
918
  var p2 = __toESM(require("@clack/prompts"), 1);
912
- var import_utils2 = require("@react-native-bedrock/utils");
919
+ var import_utils2 = require("@granite-js/utils");
913
920
  var import_clipanion2 = require("clipanion");
914
921
 
915
922
  // ../../.yarn/cache/es-toolkit-npm-1.32.0-019fc7c155-56ba965570.zip/node_modules/es-toolkit/dist/index.mjs
@@ -954,9 +961,10 @@ export default defineConfig({
954
961
  });
955
962
  `;
956
963
  var REACT_NATIVE_FRAMEWORK_CONFIG_TEMPLATE = `import { appsInToss } from '@apps-in-toss/framework/plugins';
957
- import { defineConfig } from 'react-native-bedrock/config';
964
+ import { defineConfig } from '@granite-js/react-native/config';
958
965
 
959
966
  export default defineConfig({
967
+ scheme: 'intoss',
960
968
  appName: '%%appName%%',
961
969
  plugins: [
962
970
  appsInToss({
@@ -973,7 +981,7 @@ export default defineConfig({
973
981
  `;
974
982
  var APP_TEMPLATE = `import { AppsInToss } from '@apps-in-toss/framework';
975
983
  import { PropsWithChildren } from 'react';
976
- import { InitialProps } from 'react-native-bedrock';
984
+ import { InitialProps } from '@granite-js/react-native';
977
985
  import { context } from '../require.context';
978
986
 
979
987
  function AppContainer({ children }: PropsWithChildren<InitialProps>) {
@@ -1016,17 +1024,17 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1016
1024
  dev: scripts?.scripts?.dev || scripts?.scripts?.start,
1017
1025
  build: scripts?.scripts?.build
1018
1026
  };
1019
- scripts.scripts.dev = "bedrock dev";
1020
- scripts.scripts.build = "bedrock build";
1027
+ scripts.scripts.dev = "granite dev";
1028
+ scripts.scripts.build = "granite build";
1021
1029
  scripts.scripts.deploy = "ait deploy";
1022
1030
  await import_fs3.default.promises.writeFile(import_path2.default.join(cwd, "package.json"), JSON.stringify(scripts, null, 2), {
1023
1031
  encoding: "utf-8"
1024
1032
  });
1025
1033
  p2.log.step(".gitignore \uD30C\uC77C\uC744 \uC5C5\uB370\uC774\uD2B8\uD558\uB294 \uC911...");
1026
- await import_fs3.default.promises.appendFile(import_path2.default.join(cwd, ".gitignore"), "\n.bedrock\n");
1034
+ await import_fs3.default.promises.appendFile(import_path2.default.join(cwd, ".gitignore"), "\n.granite\n");
1027
1035
  const placeholder = {
1028
- dev: originalScripts.dev === "bedrock dev" ? "" : originalScripts.dev,
1029
- build: originalScripts.build === "bedrock build" ? "" : originalScripts.build
1036
+ dev: originalScripts.dev === "granite dev" ? "" : originalScripts.dev,
1037
+ build: originalScripts.build === "granite build" ? "" : originalScripts.build
1030
1038
  };
1031
1039
  const scriptInputs = skipInput ? placeholder : await p2.group(
1032
1040
  {
@@ -1047,7 +1055,7 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1047
1055
  }
1048
1056
  }
1049
1057
  );
1050
- p2.log.step("bedrock.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1058
+ p2.log.step("granite.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1051
1059
  const webPort = skipInput ? "5173" : await p2.text({
1052
1060
  message: "Enter web port",
1053
1061
  placeholder: "5173",
@@ -1060,19 +1068,19 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1060
1068
  const config = transformTemplate(WEB_FRAMEWORK_CONFIG_TEMPLATE, {
1061
1069
  appName,
1062
1070
  webPort,
1063
- webDevCommand: scriptInputs.dev === "bedrock dev" ? "" : scriptInputs.dev,
1064
- webBuildCommand: scriptInputs.build === "bedrock build" ? "" : scriptInputs.build
1071
+ webDevCommand: scriptInputs.dev === "granite dev" ? "" : scriptInputs.dev,
1072
+ webBuildCommand: scriptInputs.build === "granite build" ? "" : scriptInputs.build
1065
1073
  });
1066
- await import_fs3.default.promises.writeFile(import_path2.default.join(cwd, "bedrock.config.ts"), config, {
1074
+ await import_fs3.default.promises.writeFile(import_path2.default.join(cwd, "granite.config.ts"), config, {
1067
1075
  encoding: "utf-8"
1068
1076
  });
1069
1077
  }
1070
1078
  async function templateReactNative({ appName, cwd }) {
1071
- p2.log.step("bedrock.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1079
+ p2.log.step("granite.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1072
1080
  const config = transformTemplate(REACT_NATIVE_FRAMEWORK_CONFIG_TEMPLATE, {
1073
1081
  appName
1074
1082
  });
1075
- await import_fs3.default.promises.writeFile(import_path2.default.join(cwd, "bedrock.config.ts"), config, {
1083
+ await import_fs3.default.promises.writeFile(import_path2.default.join(cwd, "granite.config.ts"), config, {
1076
1084
  encoding: "utf-8"
1077
1085
  });
1078
1086
  p2.log.step("src/_app.tsx \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
@@ -1098,8 +1106,8 @@ var InitCommand = class extends import_clipanion2.Command {
1098
1106
  },
1099
1107
  {
1100
1108
  value: "react-native",
1101
- label: "React Native \uD504\uB808\uC784\uC6CC\uD06C (Bedrock)",
1102
- hint: "Bedrock \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC571\uC778\uD1A0\uC2A4 React Native\uC6A9 \uAC1C\uBC1C\uD658\uACBD\uC744 \uC138\uD305\uD569\uB2C8\uB2E4."
1109
+ label: "React Native \uD504\uB808\uC784\uC6CC\uD06C (Granite)",
1110
+ hint: "Granite \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC571\uC778\uD1A0\uC2A4 React Native\uC6A9 \uAC1C\uBC1C\uD658\uACBD\uC744 \uC138\uD305\uD569\uB2C8\uB2E4."
1103
1111
  }
1104
1112
  ]
1105
1113
  })
@@ -1151,14 +1159,276 @@ var InitCommand = class extends import_clipanion2.Command {
1151
1159
  }
1152
1160
  };
1153
1161
 
1162
+ // src/integrations/UploadSentrySourcemap/index.ts
1163
+ init_cjs_shims();
1164
+
1165
+ // src/integrations/UploadSentrySourcemap/UploadSentrySourcemap.ts
1166
+ init_cjs_shims();
1167
+ var fs7 = __toESM(require("fs/promises"), 1);
1168
+ var p3 = __toESM(require("@clack/prompts"), 1);
1169
+ var import_clipanion3 = require("clipanion");
1170
+
1171
+ // src/integrations/UploadSentrySourcemap/downloadArtifacts.ts
1172
+ init_cjs_shims();
1173
+ var fs4 = __toESM(require("fs"), 1);
1174
+ var os = __toESM(require("os"), 1);
1175
+ var path3 = __toESM(require("path"), 1);
1176
+ var import_stream = require("stream");
1177
+ var import_util = require("util");
1178
+ var import_debug4 = __toESM(require_src(), 1);
1179
+ var debug4 = (0, import_debug4.default)("integrations:sentry");
1180
+ var streamPipeline = (0, import_util.promisify)(import_stream.pipeline);
1181
+ async function downloadArtifacts(options) {
1182
+ const { appName, deploymentId, apiKey, baseUrl = DEFAULT_API_BASE_URL } = options;
1183
+ const params = new URLSearchParams({
1184
+ appName,
1185
+ deploymentId
1186
+ });
1187
+ const requestUrl = `${baseUrl}/api-public/v3/openapi/bundles/download?${params.toString()}`;
1188
+ debug4("Request URL", { requestUrl });
1189
+ const response = await fetch(`${baseUrl}/api-public/v3/openapi/bundles/download?${params.toString()}`, {
1190
+ method: "GET",
1191
+ headers: {
1192
+ "Content-Type": "application/json",
1193
+ Authorization: `Bearer ${apiKey}`
1194
+ }
1195
+ });
1196
+ if (!response.ok) {
1197
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1198
+ }
1199
+ if (response.body == null) {
1200
+ throw new Error("No response body");
1201
+ }
1202
+ const tmpDir = await createTempDirectory();
1203
+ const tmpFile = `${deploymentId}.zip`;
1204
+ const tmpFilePath = path3.join(tmpDir.path, tmpFile);
1205
+ const fileStream = fs4.createWriteStream(tmpFilePath);
1206
+ await streamPipeline(response.body, fileStream);
1207
+ debug4("Artifacts downloaded", { tmpFilePath });
1208
+ return tmpFilePath;
1209
+ }
1210
+ function createTempDirectory() {
1211
+ const tempDir = path3.join(os.tmpdir(), "apps-in-toss", "sentry-integration");
1212
+ fs4.mkdirSync(tempDir, { recursive: true });
1213
+ debug4("Temp directory created", { tempDir });
1214
+ return {
1215
+ path: tempDir,
1216
+ cleanup: () => {
1217
+ fs4.rmSync(tempDir, { recursive: true, force: true });
1218
+ }
1219
+ };
1220
+ }
1221
+
1222
+ // src/integrations/UploadSentrySourcemap/extractSentryDebugId.ts
1223
+ init_cjs_shims();
1224
+ var import_promises = __toESM(require("fs/promises"), 1);
1225
+ async function extractSentryDebugId(bundlePath) {
1226
+ const bundleContent = await import_promises.default.readFile(bundlePath, "utf-8");
1227
+ return bundleContent.match(/SENTRY_DEBUG_ID=([\w-]+)/)?.[1];
1228
+ }
1229
+
1230
+ // src/integrations/UploadSentrySourcemap/extractSources.ts
1231
+ init_cjs_shims();
1232
+ var fs6 = __toESM(require("fs"), 1);
1233
+ var path4 = __toESM(require("path"), 1);
1234
+ var import_stream2 = require("stream");
1235
+ var import_util2 = require("util");
1236
+ var zlib = __toESM(require("zlib"), 1);
1237
+ var unzipper = __toESM(require("unzipper"), 1);
1238
+ var pipe = (0, import_util2.promisify)(import_stream2.pipeline);
1239
+ async function extractSources(zipPath) {
1240
+ const sources = {
1241
+ android: {
1242
+ packagerBundle: "",
1243
+ packagerSourceMap: "",
1244
+ hermesBundle: "",
1245
+ hermesSourceMap: ""
1246
+ },
1247
+ ios: {
1248
+ packagerBundle: "",
1249
+ packagerSourceMap: "",
1250
+ hermesBundle: "",
1251
+ hermesSourceMap: ""
1252
+ }
1253
+ };
1254
+ await fs6.createReadStream(zipPath).pipe(unzipper.Parse()).on("entry", async (entry) => {
1255
+ const isRoot = !entry.path.includes("/");
1256
+ const fileName = path4.basename(entry.path);
1257
+ const outputPath = path4.join(path4.dirname(zipPath), fileName);
1258
+ if (isRoot) {
1259
+ entry.pipe(fs6.createWriteStream(outputPath));
1260
+ const platform = fileName.includes("android") ? "android" : "ios";
1261
+ if (fileName.endsWith(".js")) {
1262
+ sources[platform].packagerBundle = outputPath;
1263
+ } else if (fileName.endsWith(".hbc.gz")) {
1264
+ sources[platform].hermesBundle = outputPath;
1265
+ } else if (fileName.endsWith(".js.map")) {
1266
+ sources[platform].packagerSourceMap = outputPath;
1267
+ } else if (fileName.endsWith(".hbc.map")) {
1268
+ sources[platform].hermesSourceMap = outputPath;
1269
+ }
1270
+ } else {
1271
+ entry.autodrain();
1272
+ }
1273
+ }).promise();
1274
+ if (Object.values({ ...sources.android, ...sources.ios }).some((source) => source === "")) {
1275
+ throw new Error("invalid artifact");
1276
+ }
1277
+ const [androidHermesBundle, iosHermesBundle] = await Promise.all([
1278
+ decompressGzip(sources.android.hermesBundle),
1279
+ decompressGzip(sources.ios.hermesBundle)
1280
+ ]);
1281
+ sources.android.hermesBundle = androidHermesBundle;
1282
+ sources.ios.hermesBundle = iosHermesBundle;
1283
+ return sources;
1284
+ }
1285
+ async function decompressGzip(gzFile) {
1286
+ const outfile = gzFile.replace(/\.gz$/g, "");
1287
+ await pipe(fs6.createReadStream(gzFile), zlib.createGunzip(), fs6.createWriteStream(outfile));
1288
+ return outfile;
1289
+ }
1290
+
1291
+ // src/integrations/UploadSentrySourcemap/injectSentryDebugId.ts
1292
+ init_cjs_shims();
1293
+ function injectSentryDebugId(rawSourceMap, debugId) {
1294
+ rawSourceMap.debugId = debugId;
1295
+ return rawSourceMap;
1296
+ }
1297
+
1298
+ // src/integrations/UploadSentrySourcemap/mergeSourcemap.ts
1299
+ init_cjs_shims();
1300
+ var import_source_map = require("source-map");
1301
+ async function mergeSourceMaps(packagerSourceMap, hermesSourceMap) {
1302
+ const packagerMapConsumer = await new import_source_map.SourceMapConsumer(packagerSourceMap);
1303
+ const hermesMapConsumer = await new import_source_map.SourceMapConsumer(hermesSourceMap);
1304
+ const generator = import_source_map.SourceMapGenerator.fromSourceMap(hermesMapConsumer);
1305
+ generator.applySourceMap(packagerMapConsumer, hermesMapConsumer.sources[0]);
1306
+ return generator.toJSON();
1307
+ }
1308
+
1309
+ // src/integrations/UploadSentrySourcemap/uploadSourcemap.ts
1310
+ init_cjs_shims();
1311
+ var import_cli = __toESM(require("@sentry/cli"), 1);
1312
+ function uploadSourcemap(bundlePath, sourcemapPath, options) {
1313
+ const client = new import_cli.default(null, options);
1314
+ return client.execute(["sourcemaps", "upload", "--debug-id-reference", bundlePath, sourcemapPath], true);
1315
+ }
1316
+
1317
+ // src/integrations/UploadSentrySourcemap/UploadSentrySourcemap.ts
1318
+ var UploadSentrySourcemap = class extends import_clipanion3.Command {
1319
+ static paths = [["sentry", "upload-sourcemap"]];
1320
+ apiKey = import_clipanion3.Option.String("--api-key", {
1321
+ required: false,
1322
+ description: "\uC778\uC99D API \uD0A4"
1323
+ });
1324
+ appName = import_clipanion3.Option.String("--app-name", {
1325
+ required: false,
1326
+ description: "\uC571 \uC774\uB984"
1327
+ });
1328
+ deploymentId = import_clipanion3.Option.String("--deployment-id", {
1329
+ required: false,
1330
+ description: "\uBC30\uD3EC ID"
1331
+ });
1332
+ sentryAuthToken = import_clipanion3.Option.String("--sentry-auth-token", {
1333
+ required: false,
1334
+ description: "Sentry \uC778\uC99D\uD0A4"
1335
+ });
1336
+ sentryOrg = import_clipanion3.Option.String("--sentry-org", {
1337
+ required: false,
1338
+ description: "Sentry \uC870\uC9C1"
1339
+ });
1340
+ sentryProject = import_clipanion3.Option.String("--sentry-project", {
1341
+ required: false,
1342
+ description: "Sentry \uD504\uB85C\uC81D\uD2B8"
1343
+ });
1344
+ baseUrl = import_clipanion3.Option.String("--base-url", {
1345
+ description: "API Base URL"
1346
+ });
1347
+ async execute() {
1348
+ const { baseUrl } = this;
1349
+ const apiKey = this.apiKey || await this.promptRequiredValue("password", "\uC571\uC778\uD1A0\uC2A4 API \uD0A4\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "API \uD0A4\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1350
+ const appName = this.appName || await this.promptRequiredValue("text", "\uC571 \uC774\uB984\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC571 \uC774\uB984\uC740 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1351
+ const deploymentId = this.deploymentId || await this.promptRequiredValue("text", "\uBC30\uD3EC ID\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uBC30\uD3EC ID\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1352
+ const sentryAuthToken = this.sentryAuthToken || process.env.SENTRY_AUTH_TOKEN || await this.promptRequiredValue("password", "Sentry \uC778\uC99D\uD0A4\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC778\uC99D\uD0A4\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1353
+ const sentryOrg = this.sentryOrg || process.env.SENTRY_ORG || await this.promptRequiredValue("text", "Sentry \uC870\uC9C1\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC870\uC9C1\uC740 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1354
+ const sentryProject = this.sentryProject || process.env.SENTRY_PROJECT || await this.promptRequiredValue("text", "Sentry \uD504\uB85C\uC81D\uD2B8\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uD504\uB85C\uC81D\uD2B8\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1355
+ try {
1356
+ const zipPath = await downloadArtifacts({ apiKey, appName, deploymentId, baseUrl });
1357
+ const sources = await extractSources(zipPath);
1358
+ await p3.tasks([
1359
+ {
1360
+ title: "Android \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC911...",
1361
+ task: async () => {
1362
+ await this.prepareSourceMapForUpload(sources.android);
1363
+ await uploadSourcemap(sources.android.hermesBundle, sources.android.hermesSourceMap, {
1364
+ authToken: sentryAuthToken,
1365
+ org: sentryOrg,
1366
+ project: sentryProject
1367
+ });
1368
+ return "Android \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC";
1369
+ }
1370
+ },
1371
+ {
1372
+ title: "iOS \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC911...",
1373
+ task: async () => {
1374
+ await this.prepareSourceMapForUpload(sources.ios);
1375
+ await uploadSourcemap(sources.ios.hermesBundle, sources.ios.hermesSourceMap, {
1376
+ authToken: sentryAuthToken,
1377
+ org: sentryOrg,
1378
+ project: sentryProject
1379
+ });
1380
+ return "iOS \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC";
1381
+ }
1382
+ }
1383
+ ]);
1384
+ p3.outro("Sentry \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC");
1385
+ } catch (error) {
1386
+ if (error instanceof Error) {
1387
+ p3.log.error(error.message);
1388
+ } else {
1389
+ console.error(error);
1390
+ }
1391
+ process.exit(1);
1392
+ }
1393
+ }
1394
+ async prepareSourceMapForUpload(sources) {
1395
+ const debugId = await extractSentryDebugId(sources.packagerBundle);
1396
+ if (debugId == null) {
1397
+ throw new Error("Sentry Debug ID\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1398
+ }
1399
+ const mergedSourceMap = await mergeSourceMaps(
1400
+ await fs7.readFile(sources.packagerSourceMap, "utf-8"),
1401
+ await fs7.readFile(sources.hermesSourceMap, "utf-8")
1402
+ );
1403
+ const injectedSourceMap = injectSentryDebugId(mergedSourceMap, debugId);
1404
+ await fs7.writeFile(sources.hermesSourceMap, JSON.stringify(injectedSourceMap, null, 2), "utf-8");
1405
+ }
1406
+ async promptRequiredValue(type, message, validateMessage) {
1407
+ const result = await p3[type]({
1408
+ message,
1409
+ validate: (value) => {
1410
+ if (value.length === 0) {
1411
+ return validateMessage;
1412
+ }
1413
+ return;
1414
+ }
1415
+ });
1416
+ if (p3.isCancel(result)) {
1417
+ throw new Error("\uC791\uC5C5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC5B4\uC694.");
1418
+ }
1419
+ return result;
1420
+ }
1421
+ };
1422
+
1154
1423
  // src/index.ts
1155
1424
  function initialize() {
1156
- const cli = new import_clipanion3.Cli({
1425
+ const cli = new import_clipanion4.Cli({
1157
1426
  binaryLabel: "ait",
1158
1427
  binaryName: "ait"
1159
1428
  });
1160
1429
  cli.register(DeployCommand);
1161
1430
  cli.register(InitCommand);
1431
+ cli.register(UploadSentrySourcemap);
1162
1432
  cli.runExit(process.argv.slice(2));
1163
1433
  }
1164
1434
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.js CHANGED
@@ -193,11 +193,11 @@ var require_common = __commonJS({
193
193
  let enableOverride = null;
194
194
  let namespacesCache;
195
195
  let enabledCache;
196
- function debug3(...args) {
197
- if (!debug3.enabled) {
196
+ function debug5(...args) {
197
+ if (!debug5.enabled) {
198
198
  return;
199
199
  }
200
- const self = debug3;
200
+ const self = debug5;
201
201
  const curr = Number(/* @__PURE__ */ new Date());
202
202
  const ms = curr - (prevTime || curr);
203
203
  self.diff = ms;
@@ -227,12 +227,12 @@ var require_common = __commonJS({
227
227
  const logFn = self.log || createDebug.log;
228
228
  logFn.apply(self, args);
229
229
  }
230
- debug3.namespace = namespace;
231
- debug3.useColors = createDebug.useColors();
232
- debug3.color = createDebug.selectColor(namespace);
233
- debug3.extend = extend;
234
- debug3.destroy = createDebug.destroy;
235
- Object.defineProperty(debug3, "enabled", {
230
+ debug5.namespace = namespace;
231
+ debug5.useColors = createDebug.useColors();
232
+ debug5.color = createDebug.selectColor(namespace);
233
+ debug5.extend = extend;
234
+ debug5.destroy = createDebug.destroy;
235
+ Object.defineProperty(debug5, "enabled", {
236
236
  enumerable: true,
237
237
  configurable: false,
238
238
  get: () => {
@@ -250,9 +250,9 @@ var require_common = __commonJS({
250
250
  }
251
251
  });
252
252
  if (typeof createDebug.init === "function") {
253
- createDebug.init(debug3);
253
+ createDebug.init(debug5);
254
254
  }
255
- return debug3;
255
+ return debug5;
256
256
  }
257
257
  function extend(namespace, delimiter) {
258
258
  const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
@@ -518,7 +518,7 @@ var require_node = __commonJS({
518
518
  var tty = __require("tty");
519
519
  var util = __require("util");
520
520
  exports.init = init;
521
- exports.log = log3;
521
+ exports.log = log4;
522
522
  exports.formatArgs = formatArgs;
523
523
  exports.save = save;
524
524
  exports.load = load;
@@ -653,7 +653,7 @@ var require_node = __commonJS({
653
653
  }
654
654
  return (/* @__PURE__ */ new Date()).toISOString() + " ";
655
655
  }
656
- function log3(...args) {
656
+ function log4(...args) {
657
657
  return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + "\n");
658
658
  }
659
659
  function save(namespaces) {
@@ -666,11 +666,11 @@ var require_node = __commonJS({
666
666
  function load() {
667
667
  return process.env.DEBUG;
668
668
  }
669
- function init(debug3) {
670
- debug3.inspectOpts = {};
669
+ function init(debug5) {
670
+ debug5.inspectOpts = {};
671
671
  const keys = Object.keys(exports.inspectOpts);
672
672
  for (let i = 0; i < keys.length; i++) {
673
- debug3.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
673
+ debug5.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
674
674
  }
675
675
  }
676
676
  module.exports = require_common()(exports);
@@ -704,10 +704,10 @@ var require_picocolors = __commonJS({
704
704
  "../../.yarn/cache/picocolors-npm-1.1.1-b0c45fa35e-e2e3e8170a.zip/node_modules/picocolors/picocolors.js"(exports, module) {
705
705
  "use strict";
706
706
  init_esm_shims();
707
- var p3 = process || {};
708
- var argv = p3.argv || [];
709
- var env = p3.env || {};
710
- var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p3.platform === "win32" || (p3.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
707
+ var p4 = process || {};
708
+ var argv = p4.argv || [];
709
+ var env = p4.env || {};
710
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p4.platform === "win32" || (p4.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
711
711
  var formatter = (open, close, replace = open) => (input) => {
712
712
  let string = "" + input, index = string.indexOf(close, open.length);
713
713
  return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
@@ -779,13 +779,13 @@ import { Cli } from "clipanion";
779
779
 
780
780
  // src/DeployCommand.ts
781
781
  init_esm_shims();
782
- var import_debug2 = __toESM(require_src(), 1);
782
+ var import_debug3 = __toESM(require_src(), 1);
783
783
  var import_picocolors = __toESM(require_picocolors(), 1);
784
784
  import assert from "assert";
785
785
  import fs2 from "fs";
786
786
  import path from "path";
787
787
  import * as p from "@clack/prompts";
788
- import { getPackageRoot, readZipContent } from "@react-native-bedrock/utils";
788
+ import { getPackageRoot, readZipContent } from "@granite-js/utils";
789
789
  import { Command, Option } from "clipanion";
790
790
 
791
791
  // src/utils/constants.ts
@@ -795,11 +795,31 @@ var DEFAULT_API_BASE_URL = "https://apps-in-toss.toss.im/console";
795
795
 
796
796
  // src/utils/upload.ts
797
797
  init_esm_shims();
798
- var import_debug = __toESM(require_src(), 1);
798
+ var import_debug2 = __toESM(require_src(), 1);
799
799
  import fs from "fs";
800
- var debug = (0, import_debug.default)("cli:deploy");
800
+
801
+ // src/utils/handleFetchResponse.ts
802
+ init_esm_shims();
803
+ var import_debug = __toESM(require_src(), 1);
804
+ var debug = (0, import_debug.default)("api");
805
+ async function handleFetchResponse(response) {
806
+ debug(`Response ${response.status} ${response.statusText}`);
807
+ if (!response.ok) {
808
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
809
+ }
810
+ const data = await response.clone().json();
811
+ debug("response", data);
812
+ if (data.resultType !== "SUCCESS") {
813
+ const errorCode = data?.error?.errorCode ?? "-1";
814
+ const errorReason = data?.error.reason ?? "unknown";
815
+ throw new Error(`${errorReason} (Code: ${errorCode})`);
816
+ }
817
+ }
818
+
819
+ // src/utils/upload.ts
820
+ var debug2 = (0, import_debug2.default)("cli:deploy");
801
821
  async function uploadArtifact(config) {
802
- debug("uploadArtifact", config);
822
+ debug2("uploadArtifact", config);
803
823
  const baseUrl = config.baseUrl ?? DEFAULT_API_BASE_URL;
804
824
  const response = await fetch(
805
825
  `${baseUrl}/api-public/v3/appsintossconsole/bundles/${config.appName}/deployments/${config.deploymentId}/upload`,
@@ -813,24 +833,11 @@ async function uploadArtifact(config) {
813
833
  duplex: "half"
814
834
  }
815
835
  );
816
- return handleResponse(response);
817
- }
818
- async function handleResponse(response) {
819
- debug(`Response ${response.status} ${response.statusText}`);
820
- if (!response.ok) {
821
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
822
- }
823
- const data = await response.clone().json();
824
- debug("uploadArtifact response", data);
825
- if (data.resultType !== "SUCCESS") {
826
- const errorCode = data?.error?.errorCode ?? "-1";
827
- const errorReason = data?.error.reason ?? "unknown";
828
- throw new Error(`${errorReason} (Code: ${errorCode})`);
829
- }
836
+ return handleFetchResponse(response);
830
837
  }
831
838
 
832
839
  // src/DeployCommand.ts
833
- var debug2 = (0, import_debug2.default)("cli:deploy");
840
+ var debug3 = (0, import_debug3.default)("cli:deploy");
834
841
  var DeployCommand = class extends Command {
835
842
  static paths = [["deploy"]];
836
843
  apiKey = Option.String("--api-key", {
@@ -869,7 +876,7 @@ var DeployCommand = class extends Command {
869
876
  assert(typeof deploymentId2 === "string", "invalid deploymentId");
870
877
  return { appName: appName2, deploymentId: deploymentId2 };
871
878
  }).catch((error) => {
872
- debug2("invalid ait file", error);
879
+ debug3("invalid ait file", error);
873
880
  throw new Error("\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 ait \uD30C\uC77C\uC785\uB2C8\uB2E4");
874
881
  });
875
882
  const colorAppName = import_picocolors.default.underline(import_picocolors.default.cyan(appName));
@@ -905,7 +912,7 @@ init_esm_shims();
905
912
  import fs3 from "fs";
906
913
  import path2 from "path";
907
914
  import * as p2 from "@clack/prompts";
908
- import { getPackageRoot as getPackageRoot2 } from "@react-native-bedrock/utils";
915
+ import { getPackageRoot as getPackageRoot2 } from "@granite-js/utils";
909
916
  import { Command as Command2, Option as Option2 } from "clipanion";
910
917
 
911
918
  // ../../.yarn/cache/es-toolkit-npm-1.32.0-019fc7c155-56ba965570.zip/node_modules/es-toolkit/dist/index.mjs
@@ -950,9 +957,10 @@ export default defineConfig({
950
957
  });
951
958
  `;
952
959
  var REACT_NATIVE_FRAMEWORK_CONFIG_TEMPLATE = `import { appsInToss } from '@apps-in-toss/framework/plugins';
953
- import { defineConfig } from 'react-native-bedrock/config';
960
+ import { defineConfig } from '@granite-js/react-native/config';
954
961
 
955
962
  export default defineConfig({
963
+ scheme: 'intoss',
956
964
  appName: '%%appName%%',
957
965
  plugins: [
958
966
  appsInToss({
@@ -969,7 +977,7 @@ export default defineConfig({
969
977
  `;
970
978
  var APP_TEMPLATE = `import { AppsInToss } from '@apps-in-toss/framework';
971
979
  import { PropsWithChildren } from 'react';
972
- import { InitialProps } from 'react-native-bedrock';
980
+ import { InitialProps } from '@granite-js/react-native';
973
981
  import { context } from '../require.context';
974
982
 
975
983
  function AppContainer({ children }: PropsWithChildren<InitialProps>) {
@@ -1012,17 +1020,17 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1012
1020
  dev: scripts?.scripts?.dev || scripts?.scripts?.start,
1013
1021
  build: scripts?.scripts?.build
1014
1022
  };
1015
- scripts.scripts.dev = "bedrock dev";
1016
- scripts.scripts.build = "bedrock build";
1023
+ scripts.scripts.dev = "granite dev";
1024
+ scripts.scripts.build = "granite build";
1017
1025
  scripts.scripts.deploy = "ait deploy";
1018
1026
  await fs3.promises.writeFile(path2.join(cwd, "package.json"), JSON.stringify(scripts, null, 2), {
1019
1027
  encoding: "utf-8"
1020
1028
  });
1021
1029
  p2.log.step(".gitignore \uD30C\uC77C\uC744 \uC5C5\uB370\uC774\uD2B8\uD558\uB294 \uC911...");
1022
- await fs3.promises.appendFile(path2.join(cwd, ".gitignore"), "\n.bedrock\n");
1030
+ await fs3.promises.appendFile(path2.join(cwd, ".gitignore"), "\n.granite\n");
1023
1031
  const placeholder = {
1024
- dev: originalScripts.dev === "bedrock dev" ? "" : originalScripts.dev,
1025
- build: originalScripts.build === "bedrock build" ? "" : originalScripts.build
1032
+ dev: originalScripts.dev === "granite dev" ? "" : originalScripts.dev,
1033
+ build: originalScripts.build === "granite build" ? "" : originalScripts.build
1026
1034
  };
1027
1035
  const scriptInputs = skipInput ? placeholder : await p2.group(
1028
1036
  {
@@ -1043,7 +1051,7 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1043
1051
  }
1044
1052
  }
1045
1053
  );
1046
- p2.log.step("bedrock.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1054
+ p2.log.step("granite.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1047
1055
  const webPort = skipInput ? "5173" : await p2.text({
1048
1056
  message: "Enter web port",
1049
1057
  placeholder: "5173",
@@ -1056,19 +1064,19 @@ async function templateWebFramework({ appName, cwd, skipInput }) {
1056
1064
  const config = transformTemplate(WEB_FRAMEWORK_CONFIG_TEMPLATE, {
1057
1065
  appName,
1058
1066
  webPort,
1059
- webDevCommand: scriptInputs.dev === "bedrock dev" ? "" : scriptInputs.dev,
1060
- webBuildCommand: scriptInputs.build === "bedrock build" ? "" : scriptInputs.build
1067
+ webDevCommand: scriptInputs.dev === "granite dev" ? "" : scriptInputs.dev,
1068
+ webBuildCommand: scriptInputs.build === "granite build" ? "" : scriptInputs.build
1061
1069
  });
1062
- await fs3.promises.writeFile(path2.join(cwd, "bedrock.config.ts"), config, {
1070
+ await fs3.promises.writeFile(path2.join(cwd, "granite.config.ts"), config, {
1063
1071
  encoding: "utf-8"
1064
1072
  });
1065
1073
  }
1066
1074
  async function templateReactNative({ appName, cwd }) {
1067
- p2.log.step("bedrock.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1075
+ p2.log.step("granite.config.ts \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
1068
1076
  const config = transformTemplate(REACT_NATIVE_FRAMEWORK_CONFIG_TEMPLATE, {
1069
1077
  appName
1070
1078
  });
1071
- await fs3.promises.writeFile(path2.join(cwd, "bedrock.config.ts"), config, {
1079
+ await fs3.promises.writeFile(path2.join(cwd, "granite.config.ts"), config, {
1072
1080
  encoding: "utf-8"
1073
1081
  });
1074
1082
  p2.log.step("src/_app.tsx \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uB294 \uC911...");
@@ -1094,8 +1102,8 @@ var InitCommand = class extends Command2 {
1094
1102
  },
1095
1103
  {
1096
1104
  value: "react-native",
1097
- label: "React Native \uD504\uB808\uC784\uC6CC\uD06C (Bedrock)",
1098
- hint: "Bedrock \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC571\uC778\uD1A0\uC2A4 React Native\uC6A9 \uAC1C\uBC1C\uD658\uACBD\uC744 \uC138\uD305\uD569\uB2C8\uB2E4."
1105
+ label: "React Native \uD504\uB808\uC784\uC6CC\uD06C (Granite)",
1106
+ hint: "Granite \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC571\uC778\uD1A0\uC2A4 React Native\uC6A9 \uAC1C\uBC1C\uD658\uACBD\uC744 \uC138\uD305\uD569\uB2C8\uB2E4."
1099
1107
  }
1100
1108
  ]
1101
1109
  })
@@ -1147,6 +1155,267 @@ var InitCommand = class extends Command2 {
1147
1155
  }
1148
1156
  };
1149
1157
 
1158
+ // src/integrations/UploadSentrySourcemap/index.ts
1159
+ init_esm_shims();
1160
+
1161
+ // src/integrations/UploadSentrySourcemap/UploadSentrySourcemap.ts
1162
+ init_esm_shims();
1163
+ import * as fs7 from "fs/promises";
1164
+ import * as p3 from "@clack/prompts";
1165
+ import { Command as Command3, Option as Option3 } from "clipanion";
1166
+
1167
+ // src/integrations/UploadSentrySourcemap/downloadArtifacts.ts
1168
+ init_esm_shims();
1169
+ var import_debug4 = __toESM(require_src(), 1);
1170
+ import * as fs4 from "fs";
1171
+ import * as os from "os";
1172
+ import * as path3 from "path";
1173
+ import { pipeline } from "stream";
1174
+ import { promisify } from "util";
1175
+ var debug4 = (0, import_debug4.default)("integrations:sentry");
1176
+ var streamPipeline = promisify(pipeline);
1177
+ async function downloadArtifacts(options) {
1178
+ const { appName, deploymentId, apiKey, baseUrl = DEFAULT_API_BASE_URL } = options;
1179
+ const params = new URLSearchParams({
1180
+ appName,
1181
+ deploymentId
1182
+ });
1183
+ const requestUrl = `${baseUrl}/api-public/v3/openapi/bundles/download?${params.toString()}`;
1184
+ debug4("Request URL", { requestUrl });
1185
+ const response = await fetch(`${baseUrl}/api-public/v3/openapi/bundles/download?${params.toString()}`, {
1186
+ method: "GET",
1187
+ headers: {
1188
+ "Content-Type": "application/json",
1189
+ Authorization: `Bearer ${apiKey}`
1190
+ }
1191
+ });
1192
+ if (!response.ok) {
1193
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1194
+ }
1195
+ if (response.body == null) {
1196
+ throw new Error("No response body");
1197
+ }
1198
+ const tmpDir = await createTempDirectory();
1199
+ const tmpFile = `${deploymentId}.zip`;
1200
+ const tmpFilePath = path3.join(tmpDir.path, tmpFile);
1201
+ const fileStream = fs4.createWriteStream(tmpFilePath);
1202
+ await streamPipeline(response.body, fileStream);
1203
+ debug4("Artifacts downloaded", { tmpFilePath });
1204
+ return tmpFilePath;
1205
+ }
1206
+ function createTempDirectory() {
1207
+ const tempDir = path3.join(os.tmpdir(), "apps-in-toss", "sentry-integration");
1208
+ fs4.mkdirSync(tempDir, { recursive: true });
1209
+ debug4("Temp directory created", { tempDir });
1210
+ return {
1211
+ path: tempDir,
1212
+ cleanup: () => {
1213
+ fs4.rmSync(tempDir, { recursive: true, force: true });
1214
+ }
1215
+ };
1216
+ }
1217
+
1218
+ // src/integrations/UploadSentrySourcemap/extractSentryDebugId.ts
1219
+ init_esm_shims();
1220
+ import fs5 from "fs/promises";
1221
+ async function extractSentryDebugId(bundlePath) {
1222
+ const bundleContent = await fs5.readFile(bundlePath, "utf-8");
1223
+ return bundleContent.match(/SENTRY_DEBUG_ID=([\w-]+)/)?.[1];
1224
+ }
1225
+
1226
+ // src/integrations/UploadSentrySourcemap/extractSources.ts
1227
+ init_esm_shims();
1228
+ import * as fs6 from "fs";
1229
+ import * as path4 from "path";
1230
+ import { pipeline as pipeline2 } from "stream";
1231
+ import { promisify as promisify2 } from "util";
1232
+ import * as zlib from "zlib";
1233
+ import * as unzipper from "unzipper";
1234
+ var pipe = promisify2(pipeline2);
1235
+ async function extractSources(zipPath) {
1236
+ const sources = {
1237
+ android: {
1238
+ packagerBundle: "",
1239
+ packagerSourceMap: "",
1240
+ hermesBundle: "",
1241
+ hermesSourceMap: ""
1242
+ },
1243
+ ios: {
1244
+ packagerBundle: "",
1245
+ packagerSourceMap: "",
1246
+ hermesBundle: "",
1247
+ hermesSourceMap: ""
1248
+ }
1249
+ };
1250
+ await fs6.createReadStream(zipPath).pipe(unzipper.Parse()).on("entry", async (entry) => {
1251
+ const isRoot = !entry.path.includes("/");
1252
+ const fileName = path4.basename(entry.path);
1253
+ const outputPath = path4.join(path4.dirname(zipPath), fileName);
1254
+ if (isRoot) {
1255
+ entry.pipe(fs6.createWriteStream(outputPath));
1256
+ const platform = fileName.includes("android") ? "android" : "ios";
1257
+ if (fileName.endsWith(".js")) {
1258
+ sources[platform].packagerBundle = outputPath;
1259
+ } else if (fileName.endsWith(".hbc.gz")) {
1260
+ sources[platform].hermesBundle = outputPath;
1261
+ } else if (fileName.endsWith(".js.map")) {
1262
+ sources[platform].packagerSourceMap = outputPath;
1263
+ } else if (fileName.endsWith(".hbc.map")) {
1264
+ sources[platform].hermesSourceMap = outputPath;
1265
+ }
1266
+ } else {
1267
+ entry.autodrain();
1268
+ }
1269
+ }).promise();
1270
+ if (Object.values({ ...sources.android, ...sources.ios }).some((source) => source === "")) {
1271
+ throw new Error("invalid artifact");
1272
+ }
1273
+ const [androidHermesBundle, iosHermesBundle] = await Promise.all([
1274
+ decompressGzip(sources.android.hermesBundle),
1275
+ decompressGzip(sources.ios.hermesBundle)
1276
+ ]);
1277
+ sources.android.hermesBundle = androidHermesBundle;
1278
+ sources.ios.hermesBundle = iosHermesBundle;
1279
+ return sources;
1280
+ }
1281
+ async function decompressGzip(gzFile) {
1282
+ const outfile = gzFile.replace(/\.gz$/g, "");
1283
+ await pipe(fs6.createReadStream(gzFile), zlib.createGunzip(), fs6.createWriteStream(outfile));
1284
+ return outfile;
1285
+ }
1286
+
1287
+ // src/integrations/UploadSentrySourcemap/injectSentryDebugId.ts
1288
+ init_esm_shims();
1289
+ function injectSentryDebugId(rawSourceMap, debugId) {
1290
+ rawSourceMap.debugId = debugId;
1291
+ return rawSourceMap;
1292
+ }
1293
+
1294
+ // src/integrations/UploadSentrySourcemap/mergeSourcemap.ts
1295
+ init_esm_shims();
1296
+ import { SourceMapConsumer, SourceMapGenerator } from "source-map";
1297
+ async function mergeSourceMaps(packagerSourceMap, hermesSourceMap) {
1298
+ const packagerMapConsumer = await new SourceMapConsumer(packagerSourceMap);
1299
+ const hermesMapConsumer = await new SourceMapConsumer(hermesSourceMap);
1300
+ const generator = SourceMapGenerator.fromSourceMap(hermesMapConsumer);
1301
+ generator.applySourceMap(packagerMapConsumer, hermesMapConsumer.sources[0]);
1302
+ return generator.toJSON();
1303
+ }
1304
+
1305
+ // src/integrations/UploadSentrySourcemap/uploadSourcemap.ts
1306
+ init_esm_shims();
1307
+ import SentryCLI from "@sentry/cli";
1308
+ function uploadSourcemap(bundlePath, sourcemapPath, options) {
1309
+ const client = new SentryCLI(null, options);
1310
+ return client.execute(["sourcemaps", "upload", "--debug-id-reference", bundlePath, sourcemapPath], true);
1311
+ }
1312
+
1313
+ // src/integrations/UploadSentrySourcemap/UploadSentrySourcemap.ts
1314
+ var UploadSentrySourcemap = class extends Command3 {
1315
+ static paths = [["sentry", "upload-sourcemap"]];
1316
+ apiKey = Option3.String("--api-key", {
1317
+ required: false,
1318
+ description: "\uC778\uC99D API \uD0A4"
1319
+ });
1320
+ appName = Option3.String("--app-name", {
1321
+ required: false,
1322
+ description: "\uC571 \uC774\uB984"
1323
+ });
1324
+ deploymentId = Option3.String("--deployment-id", {
1325
+ required: false,
1326
+ description: "\uBC30\uD3EC ID"
1327
+ });
1328
+ sentryAuthToken = Option3.String("--sentry-auth-token", {
1329
+ required: false,
1330
+ description: "Sentry \uC778\uC99D\uD0A4"
1331
+ });
1332
+ sentryOrg = Option3.String("--sentry-org", {
1333
+ required: false,
1334
+ description: "Sentry \uC870\uC9C1"
1335
+ });
1336
+ sentryProject = Option3.String("--sentry-project", {
1337
+ required: false,
1338
+ description: "Sentry \uD504\uB85C\uC81D\uD2B8"
1339
+ });
1340
+ baseUrl = Option3.String("--base-url", {
1341
+ description: "API Base URL"
1342
+ });
1343
+ async execute() {
1344
+ const { baseUrl } = this;
1345
+ const apiKey = this.apiKey || await this.promptRequiredValue("password", "\uC571\uC778\uD1A0\uC2A4 API \uD0A4\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "API \uD0A4\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1346
+ const appName = this.appName || await this.promptRequiredValue("text", "\uC571 \uC774\uB984\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC571 \uC774\uB984\uC740 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1347
+ const deploymentId = this.deploymentId || await this.promptRequiredValue("text", "\uBC30\uD3EC ID\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uBC30\uD3EC ID\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1348
+ const sentryAuthToken = this.sentryAuthToken || process.env.SENTRY_AUTH_TOKEN || await this.promptRequiredValue("password", "Sentry \uC778\uC99D\uD0A4\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC778\uC99D\uD0A4\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1349
+ const sentryOrg = this.sentryOrg || process.env.SENTRY_ORG || await this.promptRequiredValue("text", "Sentry \uC870\uC9C1\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uC870\uC9C1\uC740 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1350
+ const sentryProject = this.sentryProject || process.env.SENTRY_PROJECT || await this.promptRequiredValue("text", "Sentry \uD504\uB85C\uC81D\uD2B8\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694", "\uD504\uB85C\uC81D\uD2B8\uB294 \uD544\uC218 \uC785\uB825 \uD56D\uBAA9\uC785\uB2C8\uB2E4.");
1351
+ try {
1352
+ const zipPath = await downloadArtifacts({ apiKey, appName, deploymentId, baseUrl });
1353
+ const sources = await extractSources(zipPath);
1354
+ await p3.tasks([
1355
+ {
1356
+ title: "Android \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC911...",
1357
+ task: async () => {
1358
+ await this.prepareSourceMapForUpload(sources.android);
1359
+ await uploadSourcemap(sources.android.hermesBundle, sources.android.hermesSourceMap, {
1360
+ authToken: sentryAuthToken,
1361
+ org: sentryOrg,
1362
+ project: sentryProject
1363
+ });
1364
+ return "Android \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC";
1365
+ }
1366
+ },
1367
+ {
1368
+ title: "iOS \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC911...",
1369
+ task: async () => {
1370
+ await this.prepareSourceMapForUpload(sources.ios);
1371
+ await uploadSourcemap(sources.ios.hermesBundle, sources.ios.hermesSourceMap, {
1372
+ authToken: sentryAuthToken,
1373
+ org: sentryOrg,
1374
+ project: sentryProject
1375
+ });
1376
+ return "iOS \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC";
1377
+ }
1378
+ }
1379
+ ]);
1380
+ p3.outro("Sentry \uC18C\uC2A4\uB9F5 \uC5C5\uB85C\uB4DC \uC644\uB8CC");
1381
+ } catch (error) {
1382
+ if (error instanceof Error) {
1383
+ p3.log.error(error.message);
1384
+ } else {
1385
+ console.error(error);
1386
+ }
1387
+ process.exit(1);
1388
+ }
1389
+ }
1390
+ async prepareSourceMapForUpload(sources) {
1391
+ const debugId = await extractSentryDebugId(sources.packagerBundle);
1392
+ if (debugId == null) {
1393
+ throw new Error("Sentry Debug ID\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
1394
+ }
1395
+ const mergedSourceMap = await mergeSourceMaps(
1396
+ await fs7.readFile(sources.packagerSourceMap, "utf-8"),
1397
+ await fs7.readFile(sources.hermesSourceMap, "utf-8")
1398
+ );
1399
+ const injectedSourceMap = injectSentryDebugId(mergedSourceMap, debugId);
1400
+ await fs7.writeFile(sources.hermesSourceMap, JSON.stringify(injectedSourceMap, null, 2), "utf-8");
1401
+ }
1402
+ async promptRequiredValue(type, message, validateMessage) {
1403
+ const result = await p3[type]({
1404
+ message,
1405
+ validate: (value) => {
1406
+ if (value.length === 0) {
1407
+ return validateMessage;
1408
+ }
1409
+ return;
1410
+ }
1411
+ });
1412
+ if (p3.isCancel(result)) {
1413
+ throw new Error("\uC791\uC5C5\uC774 \uCDE8\uC18C\uB418\uC5C8\uC5B4\uC694.");
1414
+ }
1415
+ return result;
1416
+ }
1417
+ };
1418
+
1150
1419
  // src/index.ts
1151
1420
  function initialize() {
1152
1421
  const cli = new Cli({
@@ -1155,6 +1424,7 @@ function initialize() {
1155
1424
  });
1156
1425
  cli.register(DeployCommand);
1157
1426
  cli.register(InitCommand);
1427
+ cli.register(UploadSentrySourcemap);
1158
1428
  cli.runExit(process.argv.slice(2));
1159
1429
  }
1160
1430
  export {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/cli",
3
3
  "type": "module",
4
- "version": "0.0.0-dev.1747216176095",
4
+ "version": "0.0.0-dev.1752049503789",
5
5
  "description": "CLI for Apps In Toss",
6
6
  "scripts": {
7
7
  "prepack": "yarn build",
@@ -26,6 +26,7 @@
26
26
  "devDependencies": {
27
27
  "@types/debug": "^4",
28
28
  "@types/node": "^22.10.2",
29
+ "@types/unzipper": "^0",
29
30
  "debug": "^4.4.0",
30
31
  "es-toolkit": "^1.32.0",
31
32
  "eslint": "^9.7.0",
@@ -36,11 +37,14 @@
36
37
  },
37
38
  "dependencies": {
38
39
  "@clack/prompts": "^0.10.0",
39
- "@react-native-bedrock/utils": "0.0.0-dev.1747215740094",
40
- "clipanion": "^4.0.0-rc.4"
40
+ "@granite-js/utils": "0.1.5",
41
+ "@sentry/cli": "^2.46.0",
42
+ "clipanion": "^4.0.0-rc.4",
43
+ "source-map": "^0.8.0-beta.0",
44
+ "unzipper": "^0.12.3"
41
45
  },
42
46
  "publishConfig": {
43
47
  "access": "public"
44
48
  },
45
- "gitHead": "b9097d25120bc711f8c90351a5c6d0346d41f7fa"
49
+ "gitHead": "8269e1336952bd7229eba87bc82ae1a077ac874a"
46
50
  }