@ones-open/cli 0.0.11 → 0.0.12

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 (56) hide show
  1. package/dist/index.cjs +632 -91
  2. package/dist/index.js +633 -92
  3. package/dist/types/actions/app/resolve.d.ts +10 -0
  4. package/dist/types/actions/app/resolve.d.ts.map +1 -0
  5. package/dist/types/actions/dev/index.d.ts.map +1 -1
  6. package/dist/types/actions/disable/index.d.ts.map +1 -1
  7. package/dist/types/actions/disable/normalize.d.ts.map +1 -1
  8. package/dist/types/actions/enable/index.d.ts.map +1 -1
  9. package/dist/types/actions/enable/normalize.d.ts.map +1 -1
  10. package/dist/types/actions/index.d.ts +2 -0
  11. package/dist/types/actions/index.d.ts.map +1 -1
  12. package/dist/types/actions/install/index.d.ts.map +1 -1
  13. package/dist/types/actions/install/install.d.ts +2 -1
  14. package/dist/types/actions/install/install.d.ts.map +1 -1
  15. package/dist/types/actions/install/normalize.d.ts.map +1 -1
  16. package/dist/types/actions/logs/index.d.ts +4 -0
  17. package/dist/types/actions/logs/index.d.ts.map +1 -0
  18. package/dist/types/actions/logs/normalize.d.ts +11 -0
  19. package/dist/types/actions/logs/normalize.d.ts.map +1 -0
  20. package/dist/types/actions/specs-fetch/index.d.ts +4 -0
  21. package/dist/types/actions/specs-fetch/index.d.ts.map +1 -0
  22. package/dist/types/actions/specs-fetch/normalize.d.ts +6 -0
  23. package/dist/types/actions/specs-fetch/normalize.d.ts.map +1 -0
  24. package/dist/types/actions/uninstall/index.d.ts.map +1 -1
  25. package/dist/types/actions/uninstall/normalize.d.ts.map +1 -1
  26. package/dist/types/cli/index.d.ts.map +1 -1
  27. package/dist/types/command/app/index.d.ts.map +1 -1
  28. package/dist/types/command/disable/index.d.ts +1 -1
  29. package/dist/types/command/disable/index.d.ts.map +1 -1
  30. package/dist/types/command/enable/index.d.ts +1 -1
  31. package/dist/types/command/enable/index.d.ts.map +1 -1
  32. package/dist/types/command/index.d.ts +3 -0
  33. package/dist/types/command/index.d.ts.map +1 -1
  34. package/dist/types/command/install/index.d.ts +1 -1
  35. package/dist/types/command/install/index.d.ts.map +1 -1
  36. package/dist/types/command/logs/index.d.ts +10 -0
  37. package/dist/types/command/logs/index.d.ts.map +1 -0
  38. package/dist/types/command/specs/index.d.ts +4 -0
  39. package/dist/types/command/specs/index.d.ts.map +1 -0
  40. package/dist/types/command/specs-fetch/index.d.ts +13 -0
  41. package/dist/types/command/specs-fetch/index.d.ts.map +1 -0
  42. package/dist/types/command/uninstall/index.d.ts +1 -1
  43. package/dist/types/command/uninstall/index.d.ts.map +1 -1
  44. package/dist/types/common/error/enums.d.ts +5 -1
  45. package/dist/types/common/error/enums.d.ts.map +1 -1
  46. package/dist/types/common/locales/en/index.d.ts +18 -0
  47. package/dist/types/common/locales/en/index.d.ts.map +1 -1
  48. package/dist/types/common/package/utils.d.ts +1 -0
  49. package/dist/types/common/package/utils.d.ts.map +1 -1
  50. package/dist/types/common/request/consts.d.ts +1 -0
  51. package/dist/types/common/request/consts.d.ts.map +1 -1
  52. package/dist/types/common/request/fetch.d.ts +2 -1
  53. package/dist/types/common/request/fetch.d.ts.map +1 -1
  54. package/dist/types/common/request/types.d.ts +20 -7
  55. package/dist/types/common/request/types.d.ts.map +1 -1
  56. package/package.json +3 -3
package/dist/index.cjs CHANGED
@@ -12,6 +12,7 @@ const lodashEs = require("lodash-es");
12
12
  const process$1 = require("node:process");
13
13
  const node_url = require("node:url");
14
14
  const cosmiconfig = require("cosmiconfig");
15
+ const node_net = require("node:net");
15
16
  const getPort = require("get-port");
16
17
  const envPaths = require("env-paths");
17
18
  const zod = require("zod");
@@ -23,6 +24,9 @@ const http = require("node:http");
23
24
  const open = require("open");
24
25
  const uuid = require("uuid");
25
26
  const PKCEChallenge = require("pkce-challenge");
27
+ const node_crypto = require("node:crypto");
28
+ const promises = require("node:stream/promises");
29
+ const node_os = require("node:os");
26
30
  var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
27
31
  const en = {
28
32
  "desc.ones": "ONES CLI/{env}",
@@ -40,10 +44,21 @@ const en = {
40
44
  "desc.logout": "Log out of your ONES account",
41
45
  "desc.whoami": "Display the account information of the logged in user",
42
46
  "desc.app": "Manage app installations",
47
+ "desc.specs": "Manage ONES app specs resources to build your ONES App",
48
+ "desc.specs.fetch": "Fetch ONES app specs (download, checksum verify, and extract by default)",
49
+ "desc.specs.fetch.baseUrl": "Specify the base URL for specs resources",
50
+ "desc.specs.fetch.dir": "Specify the base directory (specs saved to <dir>/.ones/ones-app-specs)",
51
+ "desc.specs.fetch.noExtract": "Download only, do not extract archive automatically",
52
+ "desc.specs.fetch.json": "Output result in JSON format",
53
+ "desc.specs.fetch.force": "Force fetch even when local checksum is already up to date",
43
54
  "desc.install": "Install your ONES App",
44
55
  "desc.enable": "Enable your ONES App",
45
56
  "desc.disable": "Disable your ONES App",
46
57
  "desc.uninstall": "Uninstall your ONES App",
58
+ "desc.app.appId": "Specify app id",
59
+ "desc.logs": "View runtime logs for your ONES App",
60
+ "desc.logs.fromOpkxJson": "Read app id from local opkx.json when app id is not provided",
61
+ "desc.logs.tail": "Specify latest log lines to fetch (default 100)",
47
62
  "desc.legacy": "Legacy command",
48
63
  "desc.legacy.create": "Create a new ONES plugin",
49
64
  "desc.legacy.create.projectPath": "Specify the project path",
@@ -61,7 +76,14 @@ const en = {
61
76
  "error.store.permission": 'Permission denied, please check the file permission with "{filePath}"',
62
77
  "error.hostedToken.requestFailed": "Failed to request hosted token",
63
78
  "error.hostedToken.empty": "Hosted token is empty",
64
- "error.legacy.create.missingProjectPath": "Project path is required"
79
+ "error.legacy.create.missingProjectPath": "Project path is required",
80
+ "error.specs.fetch.incorrectBaseURL": "Incorrect specs base URL",
81
+ "error.specs.fetch.fetchChecksumFailed": 'Failed to fetch checksum file from "{url}"',
82
+ "error.specs.fetch.incorrectChecksum": 'Invalid checksum content. Please provide a correct base URL that serves "ones-app-specs.sha256" in format "<sha256> <zip-file>". Received: "{preview}"',
83
+ "error.specs.fetch.downloadFailed": 'Failed to download specs archive from "{url}"',
84
+ "error.specs.fetch.extractFailed": 'Failed to extract archive "{file}": {reason}',
85
+ "error.specs.fetch.cleanupFailed": 'Failed to cleanup archive "{file}": {reason}',
86
+ "error.specs.fetch.verifyChecksumFailed": 'SHA256 verification failed, expected "{expected}" but got "{actual}"'
65
87
  };
66
88
  const map = {
67
89
  en
@@ -108,6 +130,10 @@ var ErrorCode = ((ErrorCode2) => {
108
130
  ErrorCode2["HOSTED_TOKEN_EMPTY"] = "E14";
109
131
  ErrorCode2["INCORRECT_DEV_COMMAND"] = "E15";
110
132
  ErrorCode2["INCORRECT_BUILD_COMMAND"] = "E16";
133
+ ErrorCode2["INCORRECT_SPECS_BASE_URL"] = "E17";
134
+ ErrorCode2["INCORRECT_SPECS_CHECKSUM"] = "E18";
135
+ ErrorCode2["SPECS_FETCH_FAILED"] = "E19";
136
+ ErrorCode2["SPECS_CHECKSUM_MISMATCH"] = "E20";
111
137
  return ErrorCode2;
112
138
  })(ErrorCode || {});
113
139
  const getPackageJSONPath = () => {
@@ -161,6 +187,18 @@ const getAppManifestJSON = () => {
161
187
  return createOnesApp.throwError(ErrorCode.APP_MANIFEST_JSON_PARSE_ERROR, `${i18n.t("error.schema.app.manifest.parseError")}: ${details}`);
162
188
  }
163
189
  };
190
+ const tryGetAppManifestJSON = function() {
191
+ let path = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getAppManifestJSONPath();
192
+ try {
193
+ const string = node_fs.readFileSync(path, {
194
+ encoding: "utf8"
195
+ });
196
+ const json = JSON.parse(string);
197
+ return createOnesApp.AppManifestJSONSchema.parse(json);
198
+ } catch (error) {
199
+ return null;
200
+ }
201
+ };
164
202
  const validateAppManifestJSON = () => {
165
203
  const appManifestJSON = getAppManifestJSON();
166
204
  try {
@@ -212,7 +250,7 @@ const getAppRcJSON = async () => {
212
250
  };
213
251
  const isOPKXFilename = /\.opkx$/;
214
252
  const defaultOutputPath = "";
215
- const normalize$a = async (options) => {
253
+ const normalize$c = async (options) => {
216
254
  var _options$output, _options$command;
217
255
  let output = node_path.resolve(process$1.cwd(), (_options$output = options.output) !== null && _options$output !== void 0 ? _options$output : defaultOutputPath);
218
256
  const command = (_options$command = options.command) !== null && _options$command !== void 0 ? _options$command : "";
@@ -231,7 +269,7 @@ const normalize$a = async (options) => {
231
269
  };
232
270
  const {
233
271
  existsSync,
234
- ensureDirSync
272
+ ensureDirSync: ensureDirSync$1
235
273
  } = fse;
236
274
  const build = async function() {
237
275
  var _appRcJSON$dev, _defaultAppRcJSON$dev, _appRcJSON$build$comm, _appRcJSON$build, _currentCommand$, _appRcJSON$build$comp, _appRcJSON$build2;
@@ -241,7 +279,7 @@ const build = async function() {
241
279
  const {
242
280
  options
243
281
  } = createOnesApp.getCommandOptions(args, buildCommandArguments);
244
- const normalizedOptions = await normalize$a(options);
282
+ const normalizedOptions = await normalize$c(options);
245
283
  const appManifestJSON = getAppManifestJSON();
246
284
  const appRcJSON = await getAppRcJSON();
247
285
  const correctCommand = normalizedOptions.command || ((_appRcJSON$dev = appRcJSON.dev) === null || _appRcJSON$dev === void 0 || (_appRcJSON$dev = _appRcJSON$dev.command) === null || _appRcJSON$dev === void 0 ? void 0 : _appRcJSON$dev[0]) || ((_defaultAppRcJSON$dev = defaultAppRcJSON.dev) === null || _defaultAppRcJSON$dev === void 0 || (_defaultAppRcJSON$dev = _defaultAppRcJSON$dev.command) === null || _defaultAppRcJSON$dev === void 0 ? void 0 : _defaultAppRcJSON$dev[0]) || "";
@@ -289,7 +327,7 @@ const build = async function() {
289
327
  const outputPath = normalizedOptions.output;
290
328
  const outputDir = node_path.dirname(outputPath);
291
329
  const outputFilename = node_path.basename(outputPath);
292
- ensureDirSync(outputDir);
330
+ ensureDirSync$1(outputDir);
293
331
  const outputStream = node_fs.createWriteStream(outputPath);
294
332
  const files = (_appRcJSON$build$comp = (_appRcJSON$build2 = appRcJSON.build) === null || _appRcJSON$build2 === void 0 || (_appRcJSON$build2 = _appRcJSON$build2.compress) === null || _appRcJSON$build2 === void 0 ? void 0 : _appRcJSON$build2.files) !== null && _appRcJSON$build$comp !== void 0 ? _appRcJSON$build$comp : [];
295
333
  const archive = archiver("zip", {
@@ -463,6 +501,7 @@ const API = {
463
501
  APP_ENABLE: "/platform/api/app/:installation_id/enable",
464
502
  APP_DISABLE: "/platform/api/app/:installation_id/disable",
465
503
  OAUTH_TOKEN: "/identity/oauth/token",
504
+ APP_RUNTIME_LOGS: "/platform/runtime_manager/app/runtime/logs",
466
505
  REFRESH_TOKEN: "/identity/oauth/token"
467
506
  };
468
507
  const REQUEST_TIMEOUT = 1e4;
@@ -653,12 +692,36 @@ const fetchHostedAbilityStorageDevDeclare = async (appID, data) => {
653
692
  data
654
693
  }).catch(handleError);
655
694
  };
656
- const fetchAppInstall = async (data) => {
657
- var _appList$data$0$insta, _appList$data;
658
- const appID = getAppManifestJSON().app.id;
695
+ const getAppInstallation = async (appID) => {
696
+ var _appList$data$, _appList$data, _appData$installation, _appData$app_env;
659
697
  const appList = await fetchAppList(appID);
660
- const installationID = (_appList$data$0$insta = (_appList$data = appList.data) === null || _appList$data === void 0 || (_appList$data = _appList$data[0]) === null || _appList$data === void 0 ? void 0 : _appList$data.installation_id) !== null && _appList$data$0$insta !== void 0 ? _appList$data$0$insta : "";
698
+ const appData = (_appList$data$ = (_appList$data = appList.data) === null || _appList$data === void 0 ? void 0 : _appList$data[0]) !== null && _appList$data$ !== void 0 ? _appList$data$ : {};
699
+ return {
700
+ installationID: (_appData$installation = appData.installation_id) !== null && _appData$installation !== void 0 ? _appData$installation : "",
701
+ appEnv: (_appData$app_env = appData.app_env) !== null && _appData$app_env !== void 0 ? _appData$app_env : "development"
702
+ };
703
+ };
704
+ const consoleProductionNotAllowedMessage = (operation) => {
705
+ console.log(`Cannot run "${operation}" in "production" environment`);
706
+ process.exit(1);
707
+ };
708
+ const getDisplayAppEnv = (appEnv) => {
709
+ return appEnv === "production" ? "production" : "development";
710
+ };
711
+ const consoleAppEnvMessage = (operation, appEnv) => {
712
+ console.log(`Operating "${operation}" in "${appEnv}" environment`);
713
+ };
714
+ const fetchAppInstall = async (appID, data) => {
715
+ const {
716
+ installationID,
717
+ appEnv
718
+ } = await getAppInstallation(appID);
661
719
  if (installationID) {
720
+ if (appEnv === "production") {
721
+ consoleProductionNotAllowedMessage("install");
722
+ }
723
+ const displayAppEnv = getDisplayAppEnv(appEnv);
724
+ consoleAppEnvMessage("install", displayAppEnv);
662
725
  return await fetchAppBase({
663
726
  url: API.APP_UPGRADE,
664
727
  method: "POST",
@@ -668,18 +731,24 @@ const fetchAppInstall = async (data) => {
668
731
  data
669
732
  }).catch(handleError);
670
733
  }
734
+ consoleAppEnvMessage("install", "development");
671
735
  return await fetchAppBase({
672
736
  url: API.APP_INSTALL,
673
737
  method: "POST",
674
738
  data
675
739
  }).catch(handleError);
676
740
  };
677
- const fetchAppUninstall = async () => {
678
- var _appList$data$0$insta2, _appList$data2;
679
- const appID = getAppManifestJSON().app.id;
680
- const appList = await fetchAppList(appID);
681
- const installationID = (_appList$data$0$insta2 = (_appList$data2 = appList.data) === null || _appList$data2 === void 0 || (_appList$data2 = _appList$data2[0]) === null || _appList$data2 === void 0 ? void 0 : _appList$data2.installation_id) !== null && _appList$data$0$insta2 !== void 0 ? _appList$data$0$insta2 : "";
741
+ const fetchAppUninstall = async (appID) => {
742
+ const {
743
+ installationID,
744
+ appEnv
745
+ } = await getAppInstallation(appID);
682
746
  if (installationID) {
747
+ if (appEnv === "production") {
748
+ consoleProductionNotAllowedMessage("uninstall");
749
+ }
750
+ const displayAppEnv = getDisplayAppEnv(appEnv);
751
+ consoleAppEnvMessage("uninstall", displayAppEnv);
683
752
  return await fetchAppBase({
684
753
  url: API.APP_UNINSTALL,
685
754
  method: "POST",
@@ -691,12 +760,14 @@ const fetchAppUninstall = async () => {
691
760
  consoleAppNotInstalledMessage();
692
761
  process.exit(1);
693
762
  };
694
- const fetchAppEnable = async () => {
695
- var _appList$data$0$insta3, _appList$data3;
696
- const appID = getAppManifestJSON().app.id;
697
- const appList = await fetchAppList(appID);
698
- const installationID = (_appList$data$0$insta3 = (_appList$data3 = appList.data) === null || _appList$data3 === void 0 || (_appList$data3 = _appList$data3[0]) === null || _appList$data3 === void 0 ? void 0 : _appList$data3.installation_id) !== null && _appList$data$0$insta3 !== void 0 ? _appList$data$0$insta3 : "";
763
+ const fetchAppEnable = async (appID) => {
764
+ const {
765
+ installationID,
766
+ appEnv
767
+ } = await getAppInstallation(appID);
699
768
  if (installationID) {
769
+ const displayAppEnv = getDisplayAppEnv(appEnv);
770
+ consoleAppEnvMessage("enable", displayAppEnv);
700
771
  return await fetchAppBase({
701
772
  url: API.APP_ENABLE,
702
773
  method: "POST",
@@ -708,12 +779,14 @@ const fetchAppEnable = async () => {
708
779
  consoleAppNotInstalledMessage();
709
780
  process.exit(1);
710
781
  };
711
- const fetchAppDisable = async () => {
712
- var _appList$data$0$insta4, _appList$data4;
713
- const appID = getAppManifestJSON().app.id;
714
- const appList = await fetchAppList(appID);
715
- const installationID = (_appList$data$0$insta4 = (_appList$data4 = appList.data) === null || _appList$data4 === void 0 || (_appList$data4 = _appList$data4[0]) === null || _appList$data4 === void 0 ? void 0 : _appList$data4.installation_id) !== null && _appList$data$0$insta4 !== void 0 ? _appList$data$0$insta4 : "";
782
+ const fetchAppDisable = async (appID) => {
783
+ const {
784
+ installationID,
785
+ appEnv
786
+ } = await getAppInstallation(appID);
716
787
  if (installationID) {
788
+ const displayAppEnv = getDisplayAppEnv(appEnv);
789
+ consoleAppEnvMessage("disable", displayAppEnv);
717
790
  return await fetchAppBase({
718
791
  url: API.APP_DISABLE,
719
792
  method: "POST",
@@ -725,6 +798,13 @@ const fetchAppDisable = async () => {
725
798
  consoleAppNotInstalledMessage();
726
799
  process.exit(1);
727
800
  };
801
+ const fetchAppRuntimeLogs = async (data) => {
802
+ return await fetchAppBase({
803
+ url: API.APP_RUNTIME_LOGS,
804
+ method: "POST",
805
+ data
806
+ }).catch(handleError);
807
+ };
728
808
  const checkTokenInfo = async () => {
729
809
  let boolean = true;
730
810
  const regionURL = await getRegionURL().catch(() => "");
@@ -741,8 +821,28 @@ const checkTokenInfo = async () => {
741
821
  }
742
822
  return boolean;
743
823
  };
824
+ const resolveAppInfo = (input) => {
825
+ var _input$appID;
826
+ const appIDFromArgument = (_input$appID = input.appID) !== null && _input$appID !== void 0 ? _input$appID : "";
827
+ if (appIDFromArgument) {
828
+ return {
829
+ appID: appIDFromArgument,
830
+ appName: appIDFromArgument
831
+ };
832
+ }
833
+ const appManifestPath = input.opkxPath ? node_path.resolve(process$1.cwd(), input.opkxPath) : getAppManifestJSONPath();
834
+ const appManifestJSON = tryGetAppManifestJSON(appManifestPath);
835
+ if (appManifestJSON) {
836
+ return {
837
+ appID: appManifestJSON.app.id,
838
+ appName: appManifestJSON.app.name
839
+ };
840
+ }
841
+ console.log('Cannot read local "opkx.json". Please ensure "opkx.json" exists in the current directory, or provide an app ID.');
842
+ process.exit(1);
843
+ };
744
844
  const isPortNumber = /^[1-9]\d{0,4}$/;
745
- const normalize$9 = async (options) => {
845
+ const normalize$b = async (options) => {
746
846
  var _options$clearStorage;
747
847
  const portInput = options.port;
748
848
  if (portInput)
@@ -1106,7 +1206,7 @@ const tunnel = async function() {
1106
1206
  const {
1107
1207
  options
1108
1208
  } = createOnesApp.getCommandOptions(args, tunnelCommandArguments);
1109
- const normalizedOptions = await normalize$9(options);
1209
+ const normalizedOptions = await normalize$b(options);
1110
1210
  const port = Number(normalizedOptions.port);
1111
1211
  const cancelWaiting = startWaiting();
1112
1212
  await invokeTunnel(port, {
@@ -1118,9 +1218,12 @@ const tunnel = async function() {
1118
1218
  const tunnelUrl = await buildTunnelUrl();
1119
1219
  console.log(`Relay endpoint: ${tunnelUrl}`);
1120
1220
  };
1121
- const normalize$8 = async (options) => {
1221
+ const normalize$a = async (options) => {
1222
+ var _options$appID;
1122
1223
  lodashEs.noop(options);
1123
- return {};
1224
+ return {
1225
+ appID: (_options$appID = options.appID) !== null && _options$appID !== void 0 ? _options$appID : ""
1226
+ };
1124
1227
  };
1125
1228
  const displayAppDetail = async (installationID) => {
1126
1229
  var _tokenInfo$org$uuid, _tokenInfo$org, _tokenInfo$teams$0$uu, _tokenInfo$teams, _tokenInfo$org$visibi, _tokenInfo$org2;
@@ -1138,14 +1241,10 @@ const displayAppDetail = async (installationID) => {
1138
1241
  console.log(`See App detail: ${url}`);
1139
1242
  }
1140
1243
  };
1141
- const invokeInstall = async (manifestUrl) => {
1142
- const {
1143
- app
1144
- } = getAppManifestJSON();
1145
- const appName = app.name;
1146
- const appID = app.id;
1244
+ const invokeInstall = async (manifestUrl, appInfo) => {
1245
+ const appID = appInfo.appID;
1147
1246
  const cancelWaiting = startWaiting();
1148
- const result = await fetchAppInstall({
1247
+ const result = await fetchAppInstall(appID, {
1149
1248
  manifest_url: manifestUrl,
1150
1249
  options: {
1151
1250
  enable: true
@@ -1154,7 +1253,7 @@ const invokeInstall = async (manifestUrl) => {
1154
1253
  cancelWaiting();
1155
1254
  if (result.code === "OK") {
1156
1255
  var _appList$data$0$insta, _appList$data;
1157
- console.log(`App "${appName}" installed successfully!`);
1256
+ console.log(`App "${appID}" installed successfully!`);
1158
1257
  const appList = await fetchAppList(appID);
1159
1258
  const installationID = (_appList$data$0$insta = (_appList$data = appList.data) === null || _appList$data === void 0 || (_appList$data = _appList$data[0]) === null || _appList$data === void 0 ? void 0 : _appList$data.installation_id) !== null && _appList$data$0$insta !== void 0 ? _appList$data$0$insta : "";
1160
1259
  if (installationID) {
@@ -1162,7 +1261,7 @@ const invokeInstall = async (manifestUrl) => {
1162
1261
  }
1163
1262
  return true;
1164
1263
  } else {
1165
- console.log(`App "${appName}" installed failed!`);
1264
+ console.log(`App "${appID}" installed failed!`);
1166
1265
  console.error(JSON.stringify(result, null, 2));
1167
1266
  }
1168
1267
  return false;
@@ -1202,19 +1301,19 @@ const install = async function() {
1202
1301
  const {
1203
1302
  options
1204
1303
  } = createOnesApp.getCommandOptions(args, installCommandArguments);
1205
- const normalizedOptions = await normalize$8(options);
1304
+ const normalizedOptions = await normalize$a(options);
1206
1305
  lodashEs.noop(normalizedOptions);
1207
- const {
1208
- app
1209
- } = getAppManifestJSON();
1210
- const appName = app.name;
1306
+ const appInfo = resolveAppInfo({
1307
+ appID: options.appID
1308
+ });
1309
+ const appID = appInfo.appID;
1211
1310
  const manifestUrl = await getManifestUrl();
1212
1311
  if (!manifestUrl) {
1213
- console.log(`App "${appName}" server not available!`);
1312
+ console.log(`App "${appID}" server not available!`);
1214
1313
  console.log('Use "ones dev" command or "ones tunnel" command to start the server first');
1215
1314
  process.exit(1);
1216
1315
  }
1217
- await invokeInstall(manifestUrl);
1316
+ await invokeInstall(manifestUrl, appInfo);
1218
1317
  };
1219
1318
  var InstallOptions = /* @__PURE__ */ ((InstallOptions2) => {
1220
1319
  InstallOptions2["AUTO"] = "auto";
@@ -1229,7 +1328,7 @@ var DevCommandScripts = /* @__PURE__ */ ((DevCommandScripts2) => {
1229
1328
  return DevCommandScripts2;
1230
1329
  })(DevCommandScripts || {});
1231
1330
  const defaultInstall = InstallOptions.AUTO;
1232
- const normalize$7 = async (options) => {
1331
+ const normalize$9 = async (options) => {
1233
1332
  var _options$install, _options$command, _options$clearStorage;
1234
1333
  let install2 = (_options$install = options.install) !== null && _options$install !== void 0 ? _options$install : defaultInstall;
1235
1334
  const command = (_options$command = options.command) !== null && _options$command !== void 0 ? _options$command : "";
@@ -1251,6 +1350,47 @@ const normalize$7 = async (options) => {
1251
1350
  };
1252
1351
  };
1253
1352
  const IDLE_MS = 2e3;
1353
+ const WAIT_PORT_TIMEOUT_MS = 12e4;
1354
+ const WAIT_PORT_INTERVAL_MS = 500;
1355
+ const WAIT_PORT_CONNECT_TIMEOUT_MS = 1e3;
1356
+ const sleep$1 = (ms) => {
1357
+ return new Promise((resolve) => {
1358
+ setTimeout(resolve, ms);
1359
+ });
1360
+ };
1361
+ const canConnectPort = (port) => {
1362
+ return new Promise((resolve) => {
1363
+ let settled = false;
1364
+ const socket = node_net.createConnection({
1365
+ host: "127.0.0.1",
1366
+ port
1367
+ });
1368
+ const done = (result) => {
1369
+ if (settled)
1370
+ return;
1371
+ settled = true;
1372
+ socket.removeAllListeners();
1373
+ socket.destroy();
1374
+ resolve(result);
1375
+ };
1376
+ socket.setTimeout(WAIT_PORT_CONNECT_TIMEOUT_MS);
1377
+ socket.on("connect", () => done(true));
1378
+ socket.on("timeout", () => done(false));
1379
+ socket.on("error", () => done(false));
1380
+ });
1381
+ };
1382
+ const waitForPortReady = async function(port) {
1383
+ let timeoutMs = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : WAIT_PORT_TIMEOUT_MS;
1384
+ const startedAt = Date.now();
1385
+ while (Date.now() - startedAt < timeoutMs) {
1386
+ const connected = await canConnectPort(port);
1387
+ if (connected) {
1388
+ return true;
1389
+ }
1390
+ await sleep$1(WAIT_PORT_INTERVAL_MS);
1391
+ }
1392
+ return false;
1393
+ };
1254
1394
  const dev = async function() {
1255
1395
  var _appRcJSON$dev, _defaultAppRcJSON$dev, _appRcJSON$dev$comman, _appRcJSON$dev2, _currentCommand$;
1256
1396
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -1259,7 +1399,7 @@ const dev = async function() {
1259
1399
  const {
1260
1400
  options
1261
1401
  } = createOnesApp.getCommandOptions(args, devCommandArguments);
1262
- const normalizedOptions = await normalize$7(options);
1402
+ const normalizedOptions = await normalize$9(options);
1263
1403
  const appRcJSON = await getAppRcJSON();
1264
1404
  const correctCommand = normalizedOptions.command || ((_appRcJSON$dev = appRcJSON.dev) === null || _appRcJSON$dev === void 0 || (_appRcJSON$dev = _appRcJSON$dev.command) === null || _appRcJSON$dev === void 0 ? void 0 : _appRcJSON$dev[0]) || ((_defaultAppRcJSON$dev = defaultAppRcJSON.dev) === null || _defaultAppRcJSON$dev === void 0 || (_defaultAppRcJSON$dev = _defaultAppRcJSON$dev.command) === null || _defaultAppRcJSON$dev === void 0 ? void 0 : _defaultAppRcJSON$dev[0]) || "";
1265
1405
  if (!correctCommand) {
@@ -1293,6 +1433,10 @@ const dev = async function() {
1293
1433
  app
1294
1434
  } = appManifestJSON;
1295
1435
  const appID = app.id;
1436
+ const appInfo = {
1437
+ appID: app.id,
1438
+ appName: app.name
1439
+ };
1296
1440
  const config2 = getConfig();
1297
1441
  const ONES_HOSTED_PORT = await getPort({
1298
1442
  port: config2.defaultPort.hosted
@@ -1349,7 +1493,7 @@ const dev = async function() {
1349
1493
  if (enableTunnel) {
1350
1494
  switch (normalizedOptions.install) {
1351
1495
  case InstallOptions.TRUE:
1352
- await invokeInstall(manifestUrl);
1496
+ await invokeInstall(manifestUrl, appInfo);
1353
1497
  break;
1354
1498
  case InstallOptions.AUTO:
1355
1499
  {
@@ -1359,7 +1503,7 @@ const dev = async function() {
1359
1503
  if (installationID) {
1360
1504
  await displayAppDetail(installationID);
1361
1505
  } else {
1362
- await invokeInstall(manifestUrl);
1506
+ await invokeInstall(manifestUrl, appInfo);
1363
1507
  }
1364
1508
  }
1365
1509
  break;
@@ -1378,6 +1522,28 @@ const dev = async function() {
1378
1522
  const createReadyStatusPipes = (onReady2) => {
1379
1523
  let readyTimer = null;
1380
1524
  let summaryPrinted = false;
1525
+ let readyInProgress = false;
1526
+ const printReady = async () => {
1527
+ if (summaryPrinted || readyInProgress) {
1528
+ return;
1529
+ }
1530
+ readyInProgress = true;
1531
+ try {
1532
+ if (templateCommand) {
1533
+ const ready = await waitForPortReady(ONES_HOSTED_PORT);
1534
+ if (!ready) {
1535
+ console.error(`Timed out waiting for local app server to listen on port ${ONES_HOSTED_PORT}.`);
1536
+ return;
1537
+ }
1538
+ }
1539
+ if (!summaryPrinted) {
1540
+ summaryPrinted = true;
1541
+ await onReady2();
1542
+ }
1543
+ } finally {
1544
+ readyInProgress = false;
1545
+ }
1546
+ };
1381
1547
  const scheduleReady = () => {
1382
1548
  if (summaryPrinted)
1383
1549
  return;
@@ -1385,10 +1551,9 @@ const dev = async function() {
1385
1551
  clearTimeout(readyTimer);
1386
1552
  readyTimer = setTimeout(() => {
1387
1553
  readyTimer = null;
1388
- if (!summaryPrinted) {
1389
- summaryPrinted = true;
1390
- onReady2();
1391
- }
1554
+ printReady().catch((error) => {
1555
+ console.error(error);
1556
+ });
1392
1557
  }, IDLE_MS);
1393
1558
  };
1394
1559
  const pipe2 = (stream, isStderr) => {
@@ -1460,7 +1625,7 @@ const sleep = (number) => {
1460
1625
  };
1461
1626
  const isURL = /^https?:\/\//;
1462
1627
  const HostBlackList = ["ones.cn", "www.ones.cn", "ones.com", "www.ones.com"];
1463
- const normalize$6 = async (options) => {
1628
+ const normalize$8 = async (options) => {
1464
1629
  const baseURLInput = options.baseURL;
1465
1630
  if (baseURLInput)
1466
1631
  ;
@@ -1498,7 +1663,7 @@ const login = async function() {
1498
1663
  const {
1499
1664
  options
1500
1665
  } = createOnesApp.getCommandOptions(args, loginCommandArguments);
1501
- const normalizedOptions = await normalize$6(options);
1666
+ const normalizedOptions = await normalize$8(options);
1502
1667
  const {
1503
1668
  code_verifier,
1504
1669
  code_challenge
@@ -1651,7 +1816,7 @@ const login = async function() {
1651
1816
  return createOnesApp.throwError(ErrorCode.INCORRECT_BASE_URL, i18n.t("error.login.incorrectBaseURL"));
1652
1817
  }
1653
1818
  };
1654
- const normalize$5 = async (options) => {
1819
+ const normalize$7 = async (options) => {
1655
1820
  lodashEs.noop(options);
1656
1821
  return {};
1657
1822
  };
@@ -1662,12 +1827,12 @@ const logout = async function() {
1662
1827
  const {
1663
1828
  options
1664
1829
  } = createOnesApp.getCommandOptions(args, logoutCommandArguments);
1665
- const normalizedOptions = await normalize$5(options);
1830
+ const normalizedOptions = await normalize$7(options);
1666
1831
  lodashEs.noop(normalizedOptions);
1667
1832
  await setStore({});
1668
1833
  console.log("Logged out successfully!");
1669
1834
  };
1670
- const normalize$4 = async (options) => {
1835
+ const normalize$6 = async (options) => {
1671
1836
  lodashEs.noop(options);
1672
1837
  return {};
1673
1838
  };
@@ -1679,7 +1844,7 @@ const whoami = async function() {
1679
1844
  const {
1680
1845
  options
1681
1846
  } = createOnesApp.getCommandOptions(args, whoamiCommandArguments);
1682
- const normalizedOptions = await normalize$4(options);
1847
+ const normalizedOptions = await normalize$6(options);
1683
1848
  lodashEs.noop(normalizedOptions);
1684
1849
  const baseURL = await getBaseURL();
1685
1850
  const cancelWaiting = startWaiting();
@@ -1695,9 +1860,12 @@ const whoami = async function() {
1695
1860
  consoleUnauthorizedMessage();
1696
1861
  }
1697
1862
  };
1698
- const normalize$3 = async (options) => {
1863
+ const normalize$5 = async (options) => {
1864
+ var _options$appID;
1699
1865
  lodashEs.noop(options);
1700
- return {};
1866
+ return {
1867
+ appID: (_options$appID = options.appID) !== null && _options$appID !== void 0 ? _options$appID : ""
1868
+ };
1701
1869
  };
1702
1870
  const enable = async function() {
1703
1871
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -1706,22 +1874,28 @@ const enable = async function() {
1706
1874
  const {
1707
1875
  options
1708
1876
  } = createOnesApp.getCommandOptions(args, enableCommandArguments);
1709
- const normalizedOptions = await normalize$3(options);
1877
+ const normalizedOptions = await normalize$5(options);
1710
1878
  lodashEs.noop(normalizedOptions);
1711
- const appName = getAppManifestJSON().app.name;
1879
+ const appInfo = resolveAppInfo({
1880
+ appID: options.appID
1881
+ });
1882
+ const appID = appInfo.appID;
1712
1883
  const cancelWaiting = startWaiting();
1713
- const result = await fetchAppEnable();
1884
+ const result = await fetchAppEnable(appID);
1714
1885
  cancelWaiting();
1715
1886
  if (result.code === "OK") {
1716
- console.log(`App "${appName}" enabled successfully!`);
1887
+ console.log(`App "${appID}" enabled successfully!`);
1717
1888
  } else {
1718
- console.log(`App "${appName}" enabled failed!`);
1889
+ console.log(`App "${appID}" enabled failed!`);
1719
1890
  console.error(JSON.stringify(result, null, 2));
1720
1891
  }
1721
1892
  };
1722
- const normalize$2 = async (options) => {
1893
+ const normalize$4 = async (options) => {
1894
+ var _options$appID;
1723
1895
  lodashEs.noop(options);
1724
- return {};
1896
+ return {
1897
+ appID: (_options$appID = options.appID) !== null && _options$appID !== void 0 ? _options$appID : ""
1898
+ };
1725
1899
  };
1726
1900
  const disable = async function() {
1727
1901
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -1730,22 +1904,28 @@ const disable = async function() {
1730
1904
  const {
1731
1905
  options
1732
1906
  } = createOnesApp.getCommandOptions(args, disableCommandArguments);
1733
- const normalizedOptions = await normalize$2(options);
1907
+ const normalizedOptions = await normalize$4(options);
1734
1908
  lodashEs.noop(normalizedOptions);
1735
- const appName = getAppManifestJSON().app.name;
1909
+ const appInfo = resolveAppInfo({
1910
+ appID: options.appID
1911
+ });
1912
+ const appID = appInfo.appID;
1736
1913
  const cancelWaiting = startWaiting();
1737
- const result = await fetchAppDisable();
1914
+ const result = await fetchAppDisable(appID);
1738
1915
  cancelWaiting();
1739
1916
  if (result.code === "OK") {
1740
- console.log(`App "${appName}" disabled successfully!`);
1917
+ console.log(`App "${appID}" disabled successfully!`);
1741
1918
  } else {
1742
- console.log(`App "${appName}" disabled failed!`);
1919
+ console.log(`App "${appID}" disabled failed!`);
1743
1920
  console.error(JSON.stringify(result, null, 2));
1744
1921
  }
1745
1922
  };
1746
- const normalize$1 = async (options) => {
1923
+ const normalize$3 = async (options) => {
1924
+ var _options$appID;
1747
1925
  lodashEs.noop(options);
1748
- return {};
1926
+ return {
1927
+ appID: (_options$appID = options.appID) !== null && _options$appID !== void 0 ? _options$appID : ""
1928
+ };
1749
1929
  };
1750
1930
  const uninstall = async function() {
1751
1931
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -1754,18 +1934,97 @@ const uninstall = async function() {
1754
1934
  const {
1755
1935
  options
1756
1936
  } = createOnesApp.getCommandOptions(args, uninstallCommandArguments);
1757
- const normalizedOptions = await normalize$1(options);
1937
+ const normalizedOptions = await normalize$3(options);
1758
1938
  lodashEs.noop(normalizedOptions);
1759
- const appName = getAppManifestJSON().app.name;
1939
+ const appInfo = resolveAppInfo({
1940
+ appID: options.appID
1941
+ });
1942
+ const appID = appInfo.appID;
1760
1943
  const cancelWaiting = startWaiting();
1761
- const result = await fetchAppUninstall();
1944
+ const result = await fetchAppUninstall(appID);
1762
1945
  cancelWaiting();
1763
1946
  if (result.code === "OK") {
1764
- console.log(`App "${appName}" uninstalled successfully!`);
1947
+ console.log(`App "${appID}" uninstalled successfully!`);
1765
1948
  } else {
1766
- console.log(`App "${appName}" uninstalled failed!`);
1949
+ console.log(`App "${appID}" uninstalled failed!`);
1950
+ console.error(JSON.stringify(result, null, 2));
1951
+ }
1952
+ };
1953
+ const defaultTail = 100;
1954
+ const normalize$2 = async (options) => {
1955
+ var _options$appID, _options$fromOpkxJson, _options$tail;
1956
+ const appID = (_options$appID = options.appID) !== null && _options$appID !== void 0 ? _options$appID : "";
1957
+ const fromOpkxJSON = (_options$fromOpkxJson = options.fromOpkxJson) !== null && _options$fromOpkxJson !== void 0 ? _options$fromOpkxJson : false;
1958
+ if (!appID && !fromOpkxJSON) {
1959
+ console.log('App id is required, use "ones app logs <app-id>" or "--from-opkx-json"');
1960
+ process.exit(1);
1961
+ }
1962
+ const appInfo = appID ? resolveAppInfo({
1963
+ appID
1964
+ }) : resolveAppInfo({});
1965
+ const tailString = (_options$tail = options.tail) !== null && _options$tail !== void 0 ? _options$tail : `${defaultTail}`;
1966
+ const tail = Number(tailString);
1967
+ if (!Number.isInteger(tail) || tail <= 0) {
1968
+ console.log("Tail should be a positive integer");
1969
+ process.exit(1);
1970
+ }
1971
+ return {
1972
+ appID: appInfo.appID,
1973
+ appName: appInfo.appName,
1974
+ tail
1975
+ };
1976
+ };
1977
+ const displayLogs = (data) => {
1978
+ if (Array.isArray(data)) {
1979
+ data.forEach((line) => {
1980
+ if (typeof line === "string") {
1981
+ console.log(line);
1982
+ } else {
1983
+ console.log(JSON.stringify(line, null, 2));
1984
+ }
1985
+ });
1986
+ return;
1987
+ }
1988
+ if (typeof data === "string") {
1989
+ console.log(data);
1990
+ return;
1991
+ }
1992
+ console.log(JSON.stringify(data !== null && data !== void 0 ? data : {}, null, 2));
1993
+ };
1994
+ const logs = async function() {
1995
+ var _appList$data;
1996
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1997
+ args[_key] = arguments[_key];
1998
+ }
1999
+ const {
2000
+ options
2001
+ } = createOnesApp.getCommandOptions(args, logsCommandArguments);
2002
+ const normalizedOptions = await normalize$2(options);
2003
+ const {
2004
+ appID,
2005
+ tail
2006
+ } = normalizedOptions;
2007
+ const cancelWaiting = startWaiting();
2008
+ const appList = await fetchAppList(appID);
2009
+ const productionInstallation = (_appList$data = appList.data) === null || _appList$data === void 0 ? void 0 : _appList$data.find((item) => {
2010
+ return item.installation_id && item.app_env === "production";
2011
+ });
2012
+ if (!productionInstallation) {
2013
+ cancelWaiting();
2014
+ console.log(`App "${appID}" is not installed in production environment`);
2015
+ process.exit(1);
2016
+ }
2017
+ const result = await fetchAppRuntimeLogs({
2018
+ app_id: appID,
2019
+ tail
2020
+ });
2021
+ cancelWaiting();
2022
+ if (result.code && result.code !== "OK") {
2023
+ console.log(`App "${appID}" fetch logs failed!`);
1767
2024
  console.error(JSON.stringify(result, null, 2));
2025
+ return;
1768
2026
  }
2027
+ displayLogs(result.data);
1769
2028
  };
1770
2029
  const getTemplatePath = () => {
1771
2030
  const __dirname = node_path.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("index.cjs", document.baseURI).href));
@@ -1774,7 +2033,7 @@ const getTemplatePath = () => {
1774
2033
  const getTemplateLegacy = () => {
1775
2034
  return "legacy";
1776
2035
  };
1777
- const normalize = async (options) => {
2036
+ const normalize$1 = async (options) => {
1778
2037
  const projectPathInput = options.projectPath;
1779
2038
  if (projectPathInput)
1780
2039
  ;
@@ -1797,7 +2056,7 @@ const legacy = async function() {
1797
2056
  const {
1798
2057
  options
1799
2058
  } = createOnesApp.getCommandOptions(args, legacyCommandArguments);
1800
- const normalizedOptions = await normalize(options);
2059
+ const normalizedOptions = await normalize$1(options);
1801
2060
  const {
1802
2061
  projectPath
1803
2062
  } = normalizedOptions;
@@ -1812,6 +2071,274 @@ const legacy = async function() {
1812
2071
  });
1813
2072
  console.log("Plugin created successfully!");
1814
2073
  };
2074
+ const defaultBaseURL = "https://open.ones.cn/";
2075
+ const defaultDir = "~/.ones/ones-app-specs";
2076
+ const expandHomeDirectory = (dir) => {
2077
+ if (dir === "~") {
2078
+ return node_os.homedir();
2079
+ }
2080
+ if (dir.startsWith("~/")) {
2081
+ return node_path.resolve(node_os.homedir(), dir.slice(2));
2082
+ }
2083
+ return dir;
2084
+ };
2085
+ const normalizeBaseURL = (baseURLInput) => {
2086
+ let url;
2087
+ try {
2088
+ url = new URL(baseURLInput);
2089
+ } catch (error) {
2090
+ return createOnesApp.throwError(ErrorCode.INCORRECT_SPECS_BASE_URL, i18n.t("error.specs.fetch.incorrectBaseURL"));
2091
+ }
2092
+ if (url.protocol === "http:" || url.protocol === "https:")
2093
+ ;
2094
+ else {
2095
+ return createOnesApp.throwError(ErrorCode.INCORRECT_SPECS_BASE_URL, i18n.t("error.specs.fetch.incorrectBaseURL"));
2096
+ }
2097
+ url.search = "";
2098
+ url.hash = "";
2099
+ if (!url.pathname.endsWith("/")) {
2100
+ url.pathname = `${url.pathname}/`;
2101
+ }
2102
+ return url.toString();
2103
+ };
2104
+ const normalize = async (options) => {
2105
+ var _options$baseUrl, _options$extract, _context, _options$json, _options$force;
2106
+ const baseUrl = normalizeBaseURL((_options$baseUrl = options.baseUrl) !== null && _options$baseUrl !== void 0 ? _options$baseUrl : defaultBaseURL);
2107
+ const dir = options.dir ? node_path.resolve(process$1.cwd(), expandHomeDirectory(options.dir), ".ones", "ones-app-specs") : node_path.resolve(process$1.cwd(), expandHomeDirectory(defaultDir));
2108
+ const extractString = `${(_options$extract = options.extract) !== null && _options$extract !== void 0 ? _options$extract : "true"}`.toLowerCase();
2109
+ const extract = _includesInstanceProperty(_context = ["false", "0", "no"]).call(_context, extractString) ? false : true;
2110
+ const json = (_options$json = options.json) !== null && _options$json !== void 0 ? _options$json : false;
2111
+ const force = (_options$force = options.force) !== null && _options$force !== void 0 ? _options$force : false;
2112
+ return {
2113
+ baseUrl,
2114
+ dir,
2115
+ extract,
2116
+ json,
2117
+ force
2118
+ };
2119
+ };
2120
+ const {
2121
+ ensureDirSync,
2122
+ writeFile,
2123
+ remove,
2124
+ pathExists,
2125
+ readFile
2126
+ } = fse;
2127
+ const CHECKSUM_FILENAME = "ones-app-specs.sha256";
2128
+ const DEFAULT_ARCHIVE_FILENAME = "ones-app-specs.zip";
2129
+ const DOWNLOAD_TIMEOUT = 6e4;
2130
+ const getShellSafePath = (value) => {
2131
+ return `'${value.replace(/'/g, `'\\''`)}'`;
2132
+ };
2133
+ const getExtractErrorOutput = (result) => {
2134
+ var _result$error;
2135
+ const output = [result.stderr, result.stdout].map((item) => typeof item === "string" ? item.trim() : "").filter(Boolean).join("\n");
2136
+ if ((_result$error = result.error) !== null && _result$error !== void 0 && _result$error.message) {
2137
+ return result.error.message;
2138
+ }
2139
+ return output || "unknown error";
2140
+ };
2141
+ const extractArchive = (archivePath, dir) => {
2142
+ if (process.platform === "win32") {
2143
+ const powershellEscape = (value) => value.replace(/'/g, "''");
2144
+ const command = `Expand-Archive -LiteralPath '${powershellEscape(archivePath)}' -DestinationPath '${powershellEscape(dir)}' -Force`;
2145
+ const result2 = node_child_process.spawnSync("powershell", ["-NoProfile", "-NonInteractive", "-Command", command], {
2146
+ encoding: "utf8"
2147
+ });
2148
+ if (result2.status === 0 && !result2.error) {
2149
+ return;
2150
+ }
2151
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.extractFailed", {
2152
+ file: archivePath,
2153
+ reason: getExtractErrorOutput(result2)
2154
+ }));
2155
+ }
2156
+ const result = node_child_process.spawnSync("unzip", ["-oq", archivePath, "-d", dir], {
2157
+ encoding: "utf8"
2158
+ });
2159
+ if (result.status === 0 && !result.error) {
2160
+ return;
2161
+ }
2162
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.extractFailed", {
2163
+ file: archivePath,
2164
+ reason: getExtractErrorOutput(result)
2165
+ }));
2166
+ };
2167
+ const parseChecksumValue = (text) => {
2168
+ var _match$;
2169
+ const firstLine = text.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
2170
+ if (!firstLine) {
2171
+ return null;
2172
+ }
2173
+ const match = firstLine.match(/^([a-fA-F0-9]{64})(?:\s+\*?(.+))?$/);
2174
+ if (!match) {
2175
+ return null;
2176
+ }
2177
+ const checksum = match[1].toLowerCase();
2178
+ const archiveFilenameInput = ((_match$ = match[2]) !== null && _match$ !== void 0 ? _match$ : DEFAULT_ARCHIVE_FILENAME).trim();
2179
+ const archiveFilename = node_path.basename(archiveFilenameInput);
2180
+ if (!archiveFilename || archiveFilename !== archiveFilenameInput) {
2181
+ return null;
2182
+ }
2183
+ return {
2184
+ checksum,
2185
+ archiveFilename
2186
+ };
2187
+ };
2188
+ const parseChecksum = (text) => {
2189
+ var _text$split$find$trim, _text$split$find;
2190
+ const parsed = parseChecksumValue(text);
2191
+ if (parsed) {
2192
+ return parsed;
2193
+ }
2194
+ const firstLine = (_text$split$find$trim = (_text$split$find = text.split(/\r?\n/).find(Boolean)) === null || _text$split$find === void 0 ? void 0 : _text$split$find.trim()) !== null && _text$split$find$trim !== void 0 ? _text$split$find$trim : "";
2195
+ const preview = firstLine.slice(0, 120) || "<empty>";
2196
+ return createOnesApp.throwError(ErrorCode.INCORRECT_SPECS_CHECKSUM, i18n.t("error.specs.fetch.incorrectChecksum", {
2197
+ preview
2198
+ }));
2199
+ };
2200
+ const getSHA256 = async (filePath) => {
2201
+ const hash = node_crypto.createHash("sha256");
2202
+ const stream = node_fs.createReadStream(filePath);
2203
+ for await (const chunk of stream) {
2204
+ hash.update(chunk);
2205
+ }
2206
+ return hash.digest("hex");
2207
+ };
2208
+ const specsFetch = async function() {
2209
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
2210
+ args[_key] = arguments[_key];
2211
+ }
2212
+ const {
2213
+ options
2214
+ } = createOnesApp.getCommandOptions(args, specsFetchCommandArguments);
2215
+ const normalizedOptions = await normalize(options);
2216
+ const baseURL = normalizedOptions.baseUrl;
2217
+ const dir = normalizedOptions.dir;
2218
+ const onesDir = node_path.dirname(dir);
2219
+ const shouldExtract = normalizedOptions.extract;
2220
+ const useJSONOutput = normalizedOptions.json;
2221
+ const forceFetch = normalizedOptions.force;
2222
+ ensureDirSync(dir);
2223
+ const checksumURL = new URL(CHECKSUM_FILENAME, baseURL).toString();
2224
+ const checksumText = await axios.get(checksumURL, {
2225
+ responseType: "text",
2226
+ timeout: REQUEST_TIMEOUT
2227
+ }).then((response2) => {
2228
+ var _response2$data;
2229
+ return `${(_response2$data = response2.data) !== null && _response2$data !== void 0 ? _response2$data : ""}`;
2230
+ }).catch(() => {
2231
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.fetchChecksumFailed", {
2232
+ url: checksumURL
2233
+ }));
2234
+ });
2235
+ const parsedChecksum = parseChecksum(checksumText);
2236
+ const archiveURL = new URL(parsedChecksum.archiveFilename, baseURL).toString();
2237
+ const archivePath = node_path.join(dir, parsedChecksum.archiveFilename);
2238
+ const checksumPath = node_path.join(dir, CHECKSUM_FILENAME);
2239
+ const localChecksum = await pathExists(checksumPath).then(async (exists) => {
2240
+ if (!exists) {
2241
+ return null;
2242
+ }
2243
+ const content = await readFile(checksumPath, "utf8");
2244
+ return parseChecksumValue(content);
2245
+ }).catch(() => null);
2246
+ if (!forceFetch && (localChecksum === null || localChecksum === void 0 ? void 0 : localChecksum.checksum) === parsedChecksum.checksum) {
2247
+ if (useJSONOutput) {
2248
+ console.log(JSON.stringify({
2249
+ status: "up_to_date",
2250
+ base_url: baseURL,
2251
+ download_dir: dir,
2252
+ specs_dir: dir,
2253
+ checksum_url: checksumURL,
2254
+ sha256: parsedChecksum.checksum,
2255
+ force: false,
2256
+ message: "Local ones-app-specs is already up to date."
2257
+ }, null, 2));
2258
+ return;
2259
+ }
2260
+ console.log("Local ones-app-specs is already up to date.");
2261
+ console.log(`SHA256: ${parsedChecksum.checksum}`);
2262
+ console.log(`Specs directory: ${dir}`);
2263
+ return;
2264
+ }
2265
+ const response = await axios({
2266
+ url: archiveURL,
2267
+ method: "GET",
2268
+ responseType: "stream",
2269
+ timeout: DOWNLOAD_TIMEOUT
2270
+ }).catch(() => {
2271
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.downloadFailed", {
2272
+ url: archiveURL
2273
+ }));
2274
+ });
2275
+ await promises.pipeline(response.data, node_fs.createWriteStream(archivePath)).catch(async () => {
2276
+ await remove(archivePath).catch(() => void 0);
2277
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.downloadFailed", {
2278
+ url: archiveURL
2279
+ }));
2280
+ });
2281
+ const actualChecksum = await getSHA256(archivePath);
2282
+ if (actualChecksum === parsedChecksum.checksum)
2283
+ ;
2284
+ else {
2285
+ await remove(archivePath).catch(() => void 0);
2286
+ return createOnesApp.throwError(ErrorCode.SPECS_CHECKSUM_MISMATCH, i18n.t("error.specs.fetch.verifyChecksumFailed", {
2287
+ expected: parsedChecksum.checksum,
2288
+ actual: actualChecksum
2289
+ }));
2290
+ }
2291
+ const verifyCommand = `sha256sum -c ${getShellSafePath(checksumPath)}`;
2292
+ if (shouldExtract) {
2293
+ try {
2294
+ ensureDirSync(onesDir);
2295
+ extractArchive(archivePath, onesDir);
2296
+ await writeFile(checksumPath, `${parsedChecksum.checksum} ${parsedChecksum.archiveFilename}
2297
+ `, "utf8");
2298
+ await remove(archivePath).catch(() => void 0);
2299
+ } catch (error) {
2300
+ return createOnesApp.throwError(ErrorCode.SPECS_FETCH_FAILED, i18n.t("error.specs.fetch.cleanupFailed", {
2301
+ file: archivePath,
2302
+ reason: `${error}`
2303
+ }));
2304
+ }
2305
+ } else {
2306
+ await writeFile(checksumPath, `${parsedChecksum.checksum} ${parsedChecksum.archiveFilename}
2307
+ `, "utf8");
2308
+ }
2309
+ if (useJSONOutput) {
2310
+ console.log(JSON.stringify({
2311
+ status: "success",
2312
+ base_url: baseURL,
2313
+ download_dir: dir,
2314
+ specs_dir: dir,
2315
+ checksum_url: checksumURL,
2316
+ archive_url: archiveURL,
2317
+ archive_path: archivePath,
2318
+ checksum_path: checksumPath,
2319
+ sha256: actualChecksum,
2320
+ force: forceFetch,
2321
+ extract: shouldExtract,
2322
+ archive_removed: shouldExtract,
2323
+ verify_command: shouldExtract ? null : verifyCommand
2324
+ }, null, 2));
2325
+ return;
2326
+ }
2327
+ console.log("ONES specs fetched successfully!");
2328
+ console.log(`SHA256: ${actualChecksum}`);
2329
+ console.log(`Specs directory: ${dir}`);
2330
+ console.log(`Base URL: ${baseURL}`);
2331
+ console.log(`Checksum URL: ${checksumURL}`);
2332
+ console.log(`Archive URL: ${archiveURL}`);
2333
+ console.log(`Archive path: ${archivePath}`);
2334
+ if (shouldExtract) {
2335
+ console.log("Archive extracted successfully!");
2336
+ console.log("Archive cleanup: enabled (source zip removed)");
2337
+ } else {
2338
+ console.log("Archive extraction: skipped");
2339
+ console.log(`Verify command: ${verifyCommand}`);
2340
+ }
2341
+ };
1815
2342
  const buildCommandArguments = [];
1816
2343
  const $build = new commander.Command("build").description(i18n.t("desc.build")).option("-o, --output [file-path]", i18n.t("desc.build.output")).option("-c, --command [string]", i18n.t("desc.build.command")).action(build);
1817
2344
  createOnesApp.addCommandUsage($build);
@@ -1836,26 +2363,40 @@ const whoamiCommandArguments = [];
1836
2363
  const $whoami = new commander.Command("whoami").description(i18n.t("desc.whoami")).action(whoami);
1837
2364
  createOnesApp.addCommandUsage($whoami);
1838
2365
  createOnesApp.addCommandOutput($whoami);
1839
- const installCommandArguments = [];
1840
- const $install = new commander.Command("install").description(i18n.t("desc.install")).action(install);
2366
+ const installCommandArguments = ["appID"];
2367
+ const $install = new commander.Command("install").description(i18n.t("desc.install")).argument("[app-id]", i18n.t("desc.app.appId")).action(install);
1841
2368
  createOnesApp.addCommandUsage($install);
1842
2369
  createOnesApp.addCommandOutput($install);
1843
- const enableCommandArguments = [];
1844
- const $enable = new commander.Command("enable").description(i18n.t("desc.enable")).action(enable);
2370
+ const enableCommandArguments = ["appID"];
2371
+ const $enable = new commander.Command("enable").description(i18n.t("desc.enable")).argument("[app-id]", i18n.t("desc.app.appId")).action(enable);
1845
2372
  createOnesApp.addCommandUsage($enable);
1846
2373
  createOnesApp.addCommandOutput($enable);
1847
- const disableCommandArguments = [];
1848
- const $disable = new commander.Command("disable").description(i18n.t("desc.disable")).action(disable);
2374
+ const disableCommandArguments = ["appID"];
2375
+ const $disable = new commander.Command("disable").description(i18n.t("desc.disable")).argument("[app-id]", i18n.t("desc.app.appId")).action(disable);
1849
2376
  createOnesApp.addCommandUsage($disable);
1850
2377
  createOnesApp.addCommandOutput($disable);
1851
- const uninstallCommandArguments = [];
1852
- const $uninstall = new commander.Command("uninstall").description(i18n.t("desc.uninstall")).action(uninstall);
2378
+ const uninstallCommandArguments = ["appID"];
2379
+ const $uninstall = new commander.Command("uninstall").description(i18n.t("desc.uninstall")).argument("[app-id]", i18n.t("desc.app.appId")).action(uninstall);
1853
2380
  createOnesApp.addCommandUsage($uninstall);
1854
2381
  createOnesApp.addCommandOutput($uninstall);
2382
+ const logsCommandArguments = ["appID"];
2383
+ const $logs = new commander.Command("logs").description(i18n.t("desc.logs")).argument("[app-id]", i18n.t("desc.app.appId")).option("--from-opkx-json", i18n.t("desc.logs.fromOpkxJson")).option("-t, --tail [number]", i18n.t("desc.logs.tail")).action(logs);
2384
+ createOnesApp.addCommandUsage($logs);
2385
+ createOnesApp.addCommandOutput($logs);
1855
2386
  const $app = new commander.Command("app").description(i18n.t("desc.app"));
1856
- $app.addCommand($install).addCommand($enable).addCommand($disable).addCommand($uninstall);
2387
+ $app.addCommand($install).addCommand($enable).addCommand($disable).addCommand($uninstall).addCommand($logs);
1857
2388
  createOnesApp.addCommandUsage($app);
1858
2389
  createOnesApp.addCommandOutput($app);
2390
+ const specsFetchCommandArguments = [];
2391
+ const $fetch = new commander.Command("fetch").description(i18n.t("desc.specs.fetch")).option("-u, --base-url <url>", i18n.t("desc.specs.fetch.baseUrl")).option("-d, --dir <directory>", i18n.t("desc.specs.fetch.dir")).option("--no-extract", i18n.t("desc.specs.fetch.noExtract")).option("--json", i18n.t("desc.specs.fetch.json")).option("--force", i18n.t("desc.specs.fetch.force")).action(specsFetch);
2392
+ $fetch.addHelpText("after", ["", "Examples:", " ones specs fetch", " ones specs fetch --json", " ones specs fetch --no-extract", " ones specs fetch --force", " ones specs fetch --base-url http://open-preview.myones.net/ --dir /path/to/project"].join("\n"));
2393
+ createOnesApp.addCommandUsage($fetch);
2394
+ createOnesApp.addCommandOutput($fetch);
2395
+ const $specs = new commander.Command("specs").description(i18n.t("desc.specs"));
2396
+ $specs.addCommand($fetch);
2397
+ $specs.addHelpText("after", ["", "Examples:", " ones specs fetch", " ones specs fetch --json", " ones specs fetch --no-extract", " ones specs fetch --force", " ones specs fetch --base-url https://docs.ones.com/developer/ --dir /path/to/project"].join("\n"));
2398
+ createOnesApp.addCommandUsage($specs);
2399
+ createOnesApp.addCommandOutput($specs);
1859
2400
  const legacyCommandArguments = ["projectPath"];
1860
2401
  const $create = new commander.Command("create").description(i18n.t("desc.legacy.create")).argument("<project-path>", i18n.t("desc.legacy.create.projectPath")).action(legacy);
1861
2402
  createOnesApp.addCommandUsage($create);
@@ -1869,7 +2410,7 @@ const version = `${getPackageJSON().version}`;
1869
2410
  const env = `${version} Node/${process.version}`;
1870
2411
  ones.description(i18n.t("desc.ones", {
1871
2412
  env
1872
- })).addCommand(createOnesApp.$create).addCommand($build).addCommand($dev).addCommand($tunnel).addCommand($app).addCommand($login).addCommand($logout).addCommand($whoami).addCommand($legacy).configureHelp({
2413
+ })).addCommand(createOnesApp.$create).addCommand($build).addCommand($dev).addCommand($tunnel).addCommand($app).addCommand($login).addCommand($logout).addCommand($whoami).addCommand($specs).addCommand($legacy).configureHelp({
1873
2414
  visibleCommands: (cmd) => {
1874
2415
  const blackList = ["legacy"];
1875
2416
  return cmd.commands.filter((command) => !_includesInstanceProperty(blackList).call(blackList, command.name()));