@signageos/cli 2.8.0 → 3.0.0-rc.0

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 (52) hide show
  1. package/README.md +0 -6
  2. package/dist/Applet/Build/appletBuildCommand.js +2 -0
  3. package/dist/Applet/Generate/appletGenerateCommand.js +51 -59
  4. package/dist/Applet/Start/appletStartCommand.js +3 -1
  5. package/dist/Applet/Test/Upload/appletTestRunCommand.js +11 -6
  6. package/dist/Applet/Test/Upload/appletTestUploadCommand.js +7 -4
  7. package/dist/Applet/Upload/appletUploadCommand.d.ts +15 -1
  8. package/dist/Applet/Upload/appletUploadCommand.js +82 -13
  9. package/dist/Applet/Upload/appletUploadCommandHelper.js +3 -3
  10. package/dist/Applet/Upload/appletUploadFacade.js +124 -52
  11. package/dist/Applet/Upload/appletUploadFacadeHelper.d.ts +1 -1
  12. package/dist/Applet/Upload/appletUploadFacadeHelper.js +4 -3
  13. package/dist/Applet/appletErrors.d.ts +3 -0
  14. package/dist/Applet/appletErrors.js +8 -1
  15. package/dist/Applet/appletFacade.js +13 -2
  16. package/dist/Applet/appletValidation.d.ts +17 -0
  17. package/dist/Applet/appletValidation.js +62 -0
  18. package/dist/Auth/loginCommand.js +30 -4
  19. package/dist/Command/commandProcessor.js +5 -0
  20. package/dist/Command/globalArgs.d.ts +21 -0
  21. package/dist/Command/globalArgs.js +30 -0
  22. package/dist/CommandLine/progressBarFactory.js +51 -10
  23. package/dist/CustomScript/Upload/customScriptUploadCommand.js +2 -2
  24. package/dist/Device/Content/setContentCommand.js +2 -2
  25. package/dist/Device/deviceFacade.js +10 -1
  26. package/dist/Emulator/emulatorFacade.js +9 -2
  27. package/dist/Organization/organizationFacade.d.ts +1 -1
  28. package/dist/Organization/organizationFacade.js +50 -13
  29. package/dist/Plugin/Upload/pluginUploadCommand.js +2 -1
  30. package/dist/RunControl/runControlHelper.d.ts +7 -1
  31. package/dist/RunControl/runControlHelper.js +19 -1
  32. package/dist/Runner/Upload/runnerUploadCommand.js +2 -1
  33. package/dist/Timing/List/timingListCommand.js +1 -3
  34. package/dist/helper/paginationHelper.d.ts +7 -0
  35. package/dist/helper/paginationHelper.js +32 -0
  36. package/dist/helper.d.ts +18 -1
  37. package/dist/helper.js +31 -23
  38. package/dist/index.js +1 -2
  39. package/dist/parameters.d.ts +0 -1
  40. package/dist/parameters.js +3 -6
  41. package/docs/applet/generate/index.md +1 -1
  42. package/docs/applet/upload/index.md +15 -1
  43. package/package.json +12 -11
  44. package/.env +0 -3
  45. package/dist/Firmware/Upload/firmwareUploadCommand.d.ts +0 -90
  46. package/dist/Firmware/Upload/firmwareUploadCommand.js +0 -210
  47. package/dist/Firmware/Upload/firmwareUploadFacade.d.ts +0 -10
  48. package/dist/Firmware/Upload/firmwareUploadFacade.js +0 -90
  49. package/dist/Firmware/Upload/firmwareUploadHelper.d.ts +0 -1
  50. package/dist/Firmware/Upload/firmwareUploadHelper.js +0 -48
  51. package/dist/Firmware/firmwareCommand.d.ts +0 -76
  52. package/dist/Firmware/firmwareCommand.js +0 -42
package/README.md CHANGED
@@ -45,12 +45,6 @@ sos autocomplete uninstall
45
45
  This will remove the completion script and the source line from your shell configuration file.
46
46
 
47
47
 
48
- ## Test
49
- ```bash
50
- cp .env.amy .env
51
- npm test
52
- ```
53
-
54
48
  ## API reference
55
49
  ### General
56
50
  | Argument | Description | Default value |
@@ -21,6 +21,7 @@ const dist_1 = require("@signageos/sdk/dist");
21
21
  const appletFacade_1 = require("../appletFacade");
22
22
  const log_1 = require("@signageos/sdk/dist/Console/log");
23
23
  const debug_1 = __importDefault(require("debug"));
24
+ const appletValidation_1 = require("../appletValidation");
24
25
  const Debug = (0, debug_1.default)('@signageos/cli:Applet:Build:appletBuildCommand');
25
26
  exports.OPTION_LIST = [organizationFacade_1.NO_DEFAULT_ORGANIZATION_OPTION, organizationFacade_1.ORGANIZATION_UID_OPTION, appletFacade_1.APPLET_UID_OPTION];
26
27
  /**
@@ -56,6 +57,7 @@ exports.appletBuild = (0, commandDefinition_1.createCommandDefinition)({
56
57
  run(options) {
57
58
  return __awaiter(this, void 0, void 0, function* () {
58
59
  const currentDirectory = process.cwd();
60
+ yield (0, appletValidation_1.validateAppletDirectory)(currentDirectory);
59
61
  const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options);
60
62
  const organization = yield (0, organizationFacade_1.getOrganization)(organizationUid);
61
63
  const restApi = yield (0, helper_1.createOrganizationRestApi)(organization);
@@ -47,9 +47,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
47
47
  Object.defineProperty(exports, "__esModule", { value: true });
48
48
  exports.appletGenerate = void 0;
49
49
  const fs = __importStar(require("fs-extra"));
50
- const child_process = __importStar(require("child_process"));
50
+ const child_process = __importStar(require("node:child_process"));
51
51
  const chalk_1 = __importDefault(require("chalk"));
52
- const path = __importStar(require("path"));
52
+ const path = __importStar(require("node:path"));
53
53
  const prompts_1 = __importDefault(require("prompts"));
54
54
  const log_1 = require("@signageos/sdk/dist/Console/log");
55
55
  const git_1 = require("../../Lib/git");
@@ -80,7 +80,7 @@ var Packager;
80
80
  const NAME_REGEXP = /^\w(\w|\d|-)*\w$/;
81
81
  let PACKAGER_EXECUTABLE = 'npm';
82
82
  const OPTION_LIST = [
83
- { name: 'name', type: String, description: `Applet name. Match RegExp: /^\\w(\\w|\\d|-)*\\w$/` },
83
+ { name: 'name', type: String, description: String.raw `Applet name. Match RegExp: /^\w(\w|\d|-)*\w$/` },
84
84
  { name: 'applet-version', type: String, description: 'Applet initial version. Use semantic version', defaultValue: '0.0.0' },
85
85
  { name: 'target-dir', type: String, description: 'Directory where will be the applet generated to' },
86
86
  { name: 'git', type: String, description: 'Init applet as git repository "no" (default) or "yes"' },
@@ -122,7 +122,7 @@ const RUNSCRIPTS = {
122
122
  webpack: {
123
123
  start: 'webpack serve --mode development',
124
124
  build: 'webpack --mode production',
125
- connect: 'echo "Deprecated command \\"npm run connect\\". Use \\"npm run watch\\" instead." && npm run watch',
125
+ connect: String.raw `echo "Deprecated command \"npm run connect\". Use \"npm run watch\" instead." && npm run watch`,
126
126
  watch: 'webpack --watch',
127
127
  },
128
128
  rspack: {
@@ -180,9 +180,9 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
180
180
  return __awaiter(this, void 0, void 0, function* () {
181
181
  const currentDirectory = process.cwd();
182
182
  // Detect if the command has been called with optional parameters
183
- const excludedKeys = ['command', 'applet-version'];
183
+ const excludedKeys = new Set(['command', 'applet-version']);
184
184
  const argumentsFound = Object.entries(options)
185
- .filter(([key]) => !excludedKeys.includes(key))
185
+ .filter(([key]) => !excludedKeys.has(key))
186
186
  .map(([key, value]) => ({ [key]: value })).length > 0;
187
187
  console.info('sOS CLI started with params:', options);
188
188
  // Create file index
@@ -303,8 +303,8 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
303
303
  RUNSCRIPTS.common = {
304
304
  prepare: 'pnpm run clean && pnpm run build',
305
305
  upload: 'sos applet upload',
306
- clean: 'pnpx rimraf dist',
307
- escheck: 'pnpx es-check@9.4.0 --module es5 "./dist/**/*.js"',
306
+ clean: 'npx rimraf dist',
307
+ escheck: 'pnpm es-check --module es5 "./dist/**/*.js"',
308
308
  postbuild: 'pnpm run escheck',
309
309
  };
310
310
  break;
@@ -339,8 +339,7 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
339
339
  generateFiles.push({
340
340
  path: path.join(appletRootDirectory, 'src', 'index.ts'),
341
341
  content: createIndexTs(),
342
- });
343
- generateFiles.push({
342
+ }, {
344
343
  path: path.join(appletRootDirectory, 'tsconfig.json'),
345
344
  content: createTsConfig(),
346
345
  });
@@ -359,12 +358,10 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
359
358
  }
360
359
  // Create styles
361
360
  // TODO sass support
362
- {
363
- generateFiles.push({
364
- path: path.join(appletRootDirectory, 'src', 'index.css'),
365
- content: createIndexCss(),
366
- });
367
- }
361
+ generateFiles.push({
362
+ path: path.join(appletRootDirectory, 'src', 'index.css'),
363
+ content: createIndexCss(),
364
+ });
368
365
  // Create custom npm registry config
369
366
  if (typeof options['npm-registry'] === 'string') {
370
367
  generateFiles.push({
@@ -379,12 +376,10 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
379
376
  generateFiles.push({
380
377
  path: path.join(appletRootDirectory, 'package.json'),
381
378
  content: JSON.stringify(yield createPackageConfig(appletName, String(options['applet-version']), bundler, language), undefined, 2) + '\n',
382
- });
383
- generateFiles.push({
379
+ }, {
384
380
  path: path.join(appletRootDirectory, 'CHANGELOG.md'),
385
381
  content: createChangelogFile(),
386
- });
387
- generateFiles.push({
382
+ }, {
388
383
  path: path.join(appletRootDirectory, 'README.md'),
389
384
  content: createReadmeFile(),
390
385
  });
@@ -408,12 +403,10 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
408
403
  generateFiles.push({
409
404
  path: path.join(appletRootDirectory, 'public', 'index.html'),
410
405
  content: createIndexHtml(appletName),
411
- });
412
- generateFiles.push({
406
+ }, {
413
407
  path: path.join(appletRootDirectory, '.sosignore'),
414
408
  content: 'node_modules/\n',
415
- });
416
- generateFiles.push({
409
+ }, {
417
410
  path: path.join(appletRootDirectory, 'sos.config.local.json'),
418
411
  content: '{}\n',
419
412
  });
@@ -421,7 +414,7 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
421
414
  if (git === GitOptions.Yes && gitFound) {
422
415
  generateFiles.push({
423
416
  path: path.join(appletRootDirectory, '.gitignore'),
424
- content: 'node_modules/\n./dist\nsos.config.local.json',
417
+ content: 'node_modules/\n/dist/\nsos.config.local.json',
425
418
  });
426
419
  yield (0, git_1.initGitRepository)(appletRootDirectory, true).catch((error) => {
427
420
  console.error(`Git repository initialization failed: ${error}`);
@@ -439,29 +432,18 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
439
432
  if (packagerFound) {
440
433
  // Install dependencies
441
434
  process.chdir(appletRootDirectory);
442
- // Ensure the default .npmrc file will be loaded from project root
443
- // Yarn 2+ uses .yarnrc.yml, but we can use this flag to override user's .npmrc
444
- const packagerPrefix = ''; // 'NPM_CONFIG_USERCONFIG=/dev/null';
445
- // Apply packager specific options
446
- let configFlag = '';
447
- switch (packager) {
448
- case Packager.Yarn:
449
- // Prevent Yarn from automatically detecting yarnrc and npmrc files
450
- configFlag = '--no-default-rc';
451
- break;
452
- case Packager.Bun:
453
- // Prevent Bun from failing on issues related to lockfile permissions
454
- configFlag = '--frozen-lockfile';
455
- break;
456
- default:
457
- // Other packagers (npm, pnpm) currently do not require any special config
458
- }
459
435
  const installCommand = packager === Packager.Yarn ? 'add' : 'install';
460
436
  // Log the command being executed
461
- console.info(`Installing dependencies: ${packagerPrefix} ${PACKAGER_EXECUTABLE} ${installCommand} ${configFlag} --save-dev ${mergedDeps.join(' ')}`);
462
- const child = child_process.spawn(PACKAGER_EXECUTABLE, [packagerPrefix, installCommand, configFlag, '--save-dev', ...mergedDeps], {
437
+ console.info(`Installing dependencies: ${PACKAGER_EXECUTABLE} ${installCommand} --save-dev ${mergedDeps.join(' ')}`);
438
+ // Override registry env so the spawned process doesn't inherit a private
439
+ // registry from the parent project's .npmrc or global config.
440
+ // npm_config_registry is recognised by npm, bun and pnpm.
441
+ const registryUrl = typeof options['npm-registry'] === 'string' ? options['npm-registry'] : 'https://registry.npmjs.org/';
442
+ const spawnEnv = Object.assign(Object.assign({}, process.env), { npm_config_registry: registryUrl });
443
+ const child = child_process.spawn(PACKAGER_EXECUTABLE, [installCommand, '--save-dev', ...mergedDeps], {
463
444
  stdio: 'pipe', // Use 'pipe' to capture stdout and stderr
464
445
  shell: true,
446
+ env: spawnEnv,
465
447
  });
466
448
  // Capture and log stdout
467
449
  child.stdout.on('data', (data) => {
@@ -471,23 +453,33 @@ exports.appletGenerate = (0, commandDefinition_1.createCommandDefinition)({
471
453
  child.stderr.on('data', (data) => {
472
454
  console.error(`${data.toString()}`);
473
455
  });
474
- // Handle errors
475
- child.on('error', (error) => {
476
- console.error(`Error executing command: ${error.message}`);
477
- });
478
- // Handle process exit
479
- child.on('close', (code) => {
480
- if (code === 0) {
481
- (0, log_1.log)('info', `\nApplet ${chalk_1.default.green(appletName)} created!`);
482
- (0, log_1.log)('info', `\nContinue with ${chalk_1.default.green(`cd ${appletRootDirectoryName}`)} and ${chalk_1.default.green(`${PACKAGER_EXECUTABLE} start`)}`);
483
- }
484
- else {
485
- console.error(`Command exited with code ${code}`);
486
- }
456
+ // Wait for the install process to finish before returning
457
+ yield new Promise((resolve, reject) => {
458
+ child.on('error', (error) => {
459
+ console.error(`Error executing command: ${error.message}`);
460
+ reject(error);
461
+ });
462
+ child.on('close', (code) => {
463
+ if (code === 0) {
464
+ (0, log_1.log)('info', `\nApplet ${chalk_1.default.green(appletName)} created!`);
465
+ const cdCommand = chalk_1.default.green(`cd ${appletRootDirectoryName}`);
466
+ const startCommand = chalk_1.default.green(`${PACKAGER_EXECUTABLE} start`);
467
+ (0, log_1.log)('info', `\nContinue with ${cdCommand} and ${startCommand}`);
468
+ resolve();
469
+ }
470
+ else {
471
+ console.error(`Command exited with code ${code}`);
472
+ resolve(); // Don't reject — let the CLI exit gracefully
473
+ }
474
+ });
487
475
  });
488
476
  }
489
477
  else {
490
- (0, log_1.log)('info', `${chalk_1.default.red(`Please first install ${PACKAGER_EXECUTABLE} globally.`)}\nContinue with ${chalk_1.default.green(`cd ${appletRootDirectoryName}`)}, ${chalk_1.default.green(`${PACKAGER_EXECUTABLE} install`)} and ${chalk_1.default.green(`${PACKAGER_EXECUTABLE} start`)}`);
478
+ const installMessage = chalk_1.default.red(`Please first install ${PACKAGER_EXECUTABLE} globally.`);
479
+ const cdMessage = chalk_1.default.green(`cd ${appletRootDirectoryName}`);
480
+ const installCmd = chalk_1.default.green(`${PACKAGER_EXECUTABLE} install`);
481
+ const startCmd = chalk_1.default.green(`${PACKAGER_EXECUTABLE} start`);
482
+ (0, log_1.log)('info', `${installMessage}\nContinue with ${cdMessage}, ${installCmd} and ${startCmd}`);
491
483
  (0, log_1.log)('info', `\nApplet ${chalk_1.default.white(appletName)} created!`);
492
484
  }
493
485
  });
@@ -530,7 +522,7 @@ const createPackageConfig = (name, version, bundler, language) => __awaiter(void
530
522
  const createWebpackConfig = () => importFileAsString('./Templates/webpack.config.js.template');
531
523
  const createRspackConfig = () => importFileAsString('./Templates/rspack.config.mjs.template');
532
524
  const createIndexHtml = (title) => {
533
- return importFileAsString('./Templates/index.html.template').replace(/\$\{title\}/g, title);
525
+ return importFileAsString('./Templates/index.html.template').replaceAll('${title}', title);
534
526
  };
535
527
  const createIndexCss = () => importFileAsString('./Templates/index.css.template');
536
528
  const createIndexJs = () => importFileAsString('./Templates/index.js.template');
@@ -24,6 +24,7 @@ const wait_1 = __importDefault(require("../../Timer/wait"));
24
24
  const appletServerHelper_1 = require("../appletServerHelper");
25
25
  const log_1 = require("@signageos/sdk/dist/Console/log");
26
26
  const parameters_1 = require("../../parameters");
27
+ const appletValidation_1 = require("../appletValidation");
27
28
  const DEFAULT_PORT = 8090;
28
29
  const PORT_OPTION = {
29
30
  name: 'port',
@@ -96,8 +97,9 @@ exports.appletStart = (0, commandDefinition_1.createCommandDefinition)({
96
97
  var _a, _b;
97
98
  const currentDirectory = process.cwd();
98
99
  const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options);
99
- const entryFileAbsolutePath = yield (0, appletUploadCommandHelper_1.getAppletEntryFileAbsolutePath)(currentDirectory, options);
100
100
  const appletPath = yield (0, appletUploadCommandHelper_1.getAppletDirectoryAbsolutePath)(currentDirectory, options);
101
+ yield (0, appletValidation_1.validateAppletDirectory)(appletPath);
102
+ const entryFileAbsolutePath = yield (0, appletUploadCommandHelper_1.getAppletEntryFileAbsolutePath)(currentDirectory, options);
101
103
  const entryFileRelativePath = (0, appletUploadCommandHelper_1.getAppletEntryFileRelativePath)(entryFileAbsolutePath, appletPath);
102
104
  const emulatorUid = yield (0, emulatorFacade_1.loadEmulatorOrCreateNewAndReturnUid)(organizationUid);
103
105
  const dev = (0, dist_1.createDevelopment)({
@@ -21,9 +21,11 @@ const appletFacade_1 = require("../../appletFacade");
21
21
  const progressBarFactory_1 = require("../../../CommandLine/progressBarFactory");
22
22
  const deviceFacade_1 = require("../../../Device/deviceFacade");
23
23
  const appletTestRunFacade_1 = require("./appletTestRunFacade");
24
+ const paginationHelper_1 = require("../../../helper/paginationHelper");
24
25
  const wait_1 = __importDefault(require("../../../Timer/wait"));
25
26
  const commandDefinition_1 = require("../../../Command/commandDefinition");
26
27
  const log_1 = require("@signageos/sdk/dist/Console/log");
28
+ const appletValidation_1 = require("../../appletValidation");
27
29
  const OPTION_LIST = [
28
30
  organizationFacade_1.NO_DEFAULT_ORGANIZATION_OPTION,
29
31
  deviceFacade_1.DEVICE_UID_OPTION,
@@ -75,7 +77,8 @@ exports.appletTestRun = (0, commandDefinition_1.createCommandDefinition)({
75
77
  const skipConfirmation = !!options.yes;
76
78
  let tests = options.test;
77
79
  const currentDirectory = process.cwd();
78
- const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options);
80
+ yield (0, appletValidation_1.validateAppletDirectory)(currentDirectory);
81
+ const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options, skipConfirmation);
79
82
  const organization = yield (0, organizationFacade_1.getOrganization)(organizationUid);
80
83
  const restApi = yield (0, helper_1.createOrganizationRestApi)(organization);
81
84
  const deviceUid = yield (0, deviceFacade_1.getDeviceUid)(restApi, options);
@@ -84,12 +87,14 @@ exports.appletTestRun = (0, commandDefinition_1.createCommandDefinition)({
84
87
  const appletUid = yield (0, appletFacade_1.getAppletUid)(restApi, options);
85
88
  const applet = yield restApi.applet.get(appletUid);
86
89
  const appletVersion = yield restApi.applet.version.get(appletUid, version);
87
- const testSuites = yield restApi.applet.tests.list(applet.uid, appletVersion.version);
90
+ const testSuites = yield (0, paginationHelper_1.getAllPages)(yield restApi.applet.tests.list(applet.uid, appletVersion.version));
88
91
  if (!tests || tests.length === 0) {
89
92
  tests = testSuites.map((testSuite) => testSuite.identifier);
90
93
  }
91
- (0, appletTestRunFacade_1.validateTestIdentifiers)(tests, testSuites);
92
- printRunTests(tests);
94
+ // At this point tests should be defined, but TypeScript doesn't know that
95
+ const testsToRun = tests || [];
96
+ (0, appletTestRunFacade_1.validateTestIdentifiers)(testsToRun, testSuites);
97
+ printRunTests(testsToRun);
93
98
  if (!skipConfirmation) {
94
99
  const response = yield (0, prompts_1.default)({
95
100
  type: 'confirm',
@@ -104,10 +109,10 @@ exports.appletTestRun = (0, commandDefinition_1.createCommandDefinition)({
104
109
  const progressBar = (0, progressBarFactory_1.createProgressBar)();
105
110
  try {
106
111
  progressBar.init({
107
- size: tests.length,
112
+ size: testsToRun.length,
108
113
  name: RUNNING_TEST_TITLE,
109
114
  });
110
- yield restApi.device.appletTest.run(device.uid, applet.uid, appletVersion.version, tests);
115
+ yield restApi.device.appletTest.run(device.uid, applet.uid, appletVersion.version, testsToRun);
111
116
  let deviceAppletTest;
112
117
  do {
113
118
  yield (0, wait_1.default)(1e3);
@@ -21,8 +21,10 @@ const appletTestUploadFacade_1 = require("./appletTestUploadFacade");
21
21
  const appletFacade_1 = require("../../appletFacade");
22
22
  const progressBarFactory_1 = require("../../../CommandLine/progressBarFactory");
23
23
  const packageConfig_1 = require("@signageos/sdk/dist/FileSystem/packageConfig");
24
+ const paginationHelper_1 = require("../../../helper/paginationHelper");
24
25
  const commandDefinition_1 = require("../../../Command/commandDefinition");
25
26
  const log_1 = require("@signageos/sdk/dist/Console/log");
27
+ const appletValidation_1 = require("../../appletValidation");
26
28
  const OPTION_LIST = [
27
29
  organizationFacade_1.NO_DEFAULT_ORGANIZATION_OPTION,
28
30
  organizationFacade_1.ORGANIZATION_UID_OPTION,
@@ -79,7 +81,8 @@ exports.appletTestUpload = (0, commandDefinition_1.createCommandDefinition)({
79
81
  const isVerbose = !!options.verbose;
80
82
  const skipConfirmation = !!options.yes;
81
83
  const currentDirectory = process.cwd();
82
- const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options);
84
+ yield (0, appletValidation_1.validateAppletDirectory)(currentDirectory);
85
+ const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options, skipConfirmation);
83
86
  const organization = yield (0, organizationFacade_1.getOrganization)(organizationUid);
84
87
  const restApi = yield (0, helper_1.createOrganizationRestApi)(organization);
85
88
  const version = yield (0, appletFacade_1.getAppletVersion)(currentDirectory);
@@ -95,7 +98,7 @@ exports.appletTestUpload = (0, commandDefinition_1.createCommandDefinition)({
95
98
  if (isVerbose) {
96
99
  printMatchedFiles(testFiles);
97
100
  }
98
- const testSuites = yield restApi.applet.tests.list(applet.uid, appletVersion.version);
101
+ const testSuites = yield (0, paginationHelper_1.getAllPages)(yield restApi.applet.tests.list(applet.uid, appletVersion.version));
99
102
  const testSuitesMap = {};
100
103
  for (const testSuite of testSuites) {
101
104
  testSuitesMap[testSuite.identifier] = testSuite;
@@ -151,8 +154,8 @@ exports.appletTestUpload = (0, commandDefinition_1.createCommandDefinition)({
151
154
  },
152
155
  });
153
156
  function displaySuccessMessage(appletName, appletVersion) {
154
- (0, log_1.log)('info', `Applet ${chalk_1.default.green(appletName)} version ${chalk_1.default.green(appletVersion)} tests has been uploaded.`);
155
- (0, log_1.log)('info', `To run the tests, use command ${chalk_1.default.blue(`sos applet test run`)}`);
157
+ (0, log_1.log)('info', `\nApplet ${chalk_1.default.green(appletName)} version ${chalk_1.default.green(appletVersion)} tests has been uploaded.`);
158
+ (0, log_1.log)('info', `To run the tests, use command ${chalk_1.default.green(`sos applet test run`)}`);
156
159
  }
157
160
  function printMatchedFiles(testFiles) {
158
161
  if (testFiles.length > 0) {
@@ -56,14 +56,28 @@ export declare const OPTION_LIST: readonly [{
56
56
  * # Upload with organization override
57
57
  * sos applet upload --organization-uid abc123def456
58
58
  *
59
- * # Skip confirmation prompts
59
+ * # Skip confirmation prompts (auto-selects if only 1 org available)
60
60
  * sos applet upload --yes
61
61
  *
62
+ * # CI/CD: Non-interactive upload with specific organization
63
+ * sos applet upload --yes --organization-uid abc123def456
64
+ *
62
65
  * # Verbose output with detailed file information
63
66
  * sos applet upload --verbose
64
67
  *
65
68
  * # Update package.json with new applet UID
66
69
  * sos applet upload --update-package-config
70
+ *
71
+ * # Complete CI/CD example
72
+ * sos applet upload --yes --organization-uid abc123def456 --update-package-config
73
+ * ```
74
+ *
75
+ * **Note for CI/CD and --yes flag:**
76
+ * When using `--yes` with multiple organizations:
77
+ * - If you have only 1 organization: it will be auto-selected
78
+ * - If you have multiple organizations: you MUST specify `--organization-uid`
79
+ * - Alternative: Set a default organization with `sos organization set-default`
80
+ *
67
81
  * ```
68
82
  *
69
83
  * @throws {Error} When package.json is missing or invalid
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -15,8 +48,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
48
  exports.appletUpload = exports.OPTION_LIST = void 0;
16
49
  const chalk_1 = __importDefault(require("chalk"));
17
50
  const prompts_1 = __importDefault(require("prompts"));
51
+ const path = __importStar(require("path"));
52
+ const fs = __importStar(require("fs-extra"));
18
53
  const helper_1 = require("../../helper");
19
- const parameters_1 = require("../../parameters");
20
54
  const organizationFacade_1 = require("../../Organization/organizationFacade");
21
55
  const appletFacade_1 = require("../appletFacade");
22
56
  const appletUploadFacade_1 = require("./appletUploadFacade");
@@ -30,6 +64,7 @@ const log_1 = require("@signageos/sdk/dist/Console/log");
30
64
  const sdk_1 = require("@signageos/sdk");
31
65
  const GatewayError_1 = __importDefault(require("@signageos/sdk/dist/RestApi/Error/GatewayError"));
32
66
  const NotFoundError_1 = __importDefault(require("@signageos/sdk/dist/RestApi/Error/NotFoundError"));
67
+ const appletValidation_1 = require("../appletValidation");
33
68
  exports.OPTION_LIST = [
34
69
  appletUploadCommandHelper_1.APPLET_PATH_OPTION,
35
70
  appletUploadCommandHelper_1.ENTRY_FILE_PATH_OPTION,
@@ -77,14 +112,28 @@ exports.OPTION_LIST = [
77
112
  * # Upload with organization override
78
113
  * sos applet upload --organization-uid abc123def456
79
114
  *
80
- * # Skip confirmation prompts
115
+ * # Skip confirmation prompts (auto-selects if only 1 org available)
81
116
  * sos applet upload --yes
82
117
  *
118
+ * # CI/CD: Non-interactive upload with specific organization
119
+ * sos applet upload --yes --organization-uid abc123def456
120
+ *
83
121
  * # Verbose output with detailed file information
84
122
  * sos applet upload --verbose
85
123
  *
86
124
  * # Update package.json with new applet UID
87
125
  * sos applet upload --update-package-config
126
+ *
127
+ * # Complete CI/CD example
128
+ * sos applet upload --yes --organization-uid abc123def456 --update-package-config
129
+ * ```
130
+ *
131
+ * **Note for CI/CD and --yes flag:**
132
+ * When using `--yes` with multiple organizations:
133
+ * - If you have only 1 organization: it will be auto-selected
134
+ * - If you have multiple organizations: you MUST specify `--organization-uid`
135
+ * - Alternative: Set a default organization with `sos organization set-default`
136
+ *
88
137
  * ```
89
138
  *
90
139
  * @throws {Error} When package.json is missing or invalid
@@ -103,25 +152,44 @@ exports.appletUpload = (0, commandDefinition_1.createCommandDefinition)({
103
152
  run(options) {
104
153
  return __awaiter(this, void 0, void 0, function* () {
105
154
  const currentDirectory = process.cwd();
106
- const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options);
155
+ const skipPrompts = options.yes;
156
+ const organizationUid = yield (0, organizationFacade_1.getOrganizationUidOrDefaultOrSelect)(options, skipPrompts);
107
157
  const organization = yield (0, organizationFacade_1.getOrganization)(organizationUid);
108
158
  const restApi = yield (0, helper_1.createOrganizationRestApi)(organization);
109
- const { name: appletName, version: appletVersion, frontAppletVersion } = yield (0, appletFacade_1.getApplet)(currentDirectory);
110
159
  const appletPathOption = options['applet-path'];
111
160
  const appletEntryOption = options['entry-file-path'];
112
161
  const updatePackageConfig = options['update-package-config'];
113
162
  let appletBinaryFilePath = undefined;
114
163
  let appletDirectoryPath = undefined;
115
164
  let appletEntryFilePath = undefined;
116
- const isSingleFileApplet = !!(appletPathOption && !appletEntryOption);
165
+ // Determine if this is a single file applet by checking if applet-path points to a file
166
+ let isSingleFileApplet = false;
167
+ if (appletPathOption) {
168
+ const appletPath = path.isAbsolute(appletPathOption) ? appletPathOption : path.join(currentDirectory, appletPathOption);
169
+ if (yield fs.pathExists(appletPath)) {
170
+ const stats = yield fs.stat(appletPath);
171
+ isSingleFileApplet = stats.isFile();
172
+ }
173
+ else {
174
+ // If path doesn't exist, fall back to the original logic
175
+ isSingleFileApplet = !appletEntryOption;
176
+ }
177
+ }
117
178
  if (isSingleFileApplet) {
118
179
  displaySingleFileAppletDeprecationNote();
119
180
  appletBinaryFilePath = yield (0, appletUploadCommandHelper_1.getAppletBinaryFileAbsolutePath)(currentDirectory, options);
120
181
  }
121
182
  else {
122
183
  appletDirectoryPath = yield (0, appletUploadCommandHelper_1.getAppletDirectoryAbsolutePath)(currentDirectory, options);
123
- appletEntryFilePath = yield (0, appletUploadCommandHelper_1.getAppletEntryFileAbsolutePath)(currentDirectory, options);
184
+ // For multi-file applets, use the applet directory as the base for resolving the entry file
185
+ appletEntryFilePath = yield (0, appletUploadCommandHelper_1.getAppletEntryFileAbsolutePath)(appletDirectoryPath, options);
124
186
  }
187
+ // Validate that the applet directory contains a valid applet
188
+ // For multi-file applets, validate the resolved applet directory
189
+ // For single-file applets (deprecated), validate the current directory
190
+ const directoryToValidate = appletDirectoryPath !== null && appletDirectoryPath !== void 0 ? appletDirectoryPath : currentDirectory;
191
+ yield (0, appletValidation_1.validateAppletDirectory)(directoryToValidate);
192
+ const { name: appletName, version: appletVersion, frontAppletVersion } = yield (0, appletFacade_1.getApplet)(directoryToValidate);
125
193
  let overrideAppletVersionConfirmed = false;
126
194
  let createNewAppletVersionConfirmed = false;
127
195
  let appletUid;
@@ -138,7 +206,10 @@ exports.appletUpload = (0, commandDefinition_1.createCommandDefinition)({
138
206
  }
139
207
  finally {
140
208
  if (updatePackageConfig) {
141
- yield (0, packageConfig_1.saveToPackage)(currentDirectory, { sos: { appletUid } });
209
+ // For multi-file applets, save to the applet directory's package.json
210
+ // For single-file applets, save to the current directory's package.json
211
+ const packageConfigDirectory = isSingleFileApplet ? currentDirectory : appletDirectoryPath || currentDirectory;
212
+ yield (0, packageConfig_1.saveToPackage)(packageConfigDirectory, { sos: { appletUid } });
142
213
  }
143
214
  }
144
215
  const applet = yield restApi.applet.get(appletUid);
@@ -233,7 +304,7 @@ exports.appletUpload = (0, commandDefinition_1.createCommandDefinition)({
233
304
  progressBar: progressBar,
234
305
  });
235
306
  }
236
- displaySuccessMessage(applet.uid, applet.name, appletVersion, parameters_1.parameters.boxHost);
307
+ displaySuccessMessage(applet.uid, applet.name, appletVersion);
237
308
  }
238
309
  else if (createNewAppletVersionConfirmed) {
239
310
  if (isSingleFileApplet) {
@@ -262,7 +333,7 @@ exports.appletUpload = (0, commandDefinition_1.createCommandDefinition)({
262
333
  progressBar,
263
334
  });
264
335
  }
265
- displaySuccessMessage(applet.uid, applet.name, appletVersion, parameters_1.parameters.boxHost);
336
+ displaySuccessMessage(applet.uid, applet.name, appletVersion);
266
337
  }
267
338
  }
268
339
  catch (error) {
@@ -274,10 +345,8 @@ exports.appletUpload = (0, commandDefinition_1.createCommandDefinition)({
274
345
  });
275
346
  },
276
347
  });
277
- function displaySuccessMessage(appletUid, appletName, appletVersion, boxHost) {
278
- (0, log_1.log)('info', `Applet ${chalk_1.default.green(appletName)} version ${chalk_1.default.green(appletVersion)} has been uploaded.`);
279
- const appletBoxUri = `https://${boxHost}/applet/${appletUid}/${appletVersion}/build`;
280
- (0, log_1.log)('info', `To build specific applications (Tizen, WebOS, SSSP, BrightSign, RPi, Android etc.) go to ${chalk_1.default.blue(appletBoxUri)}`);
348
+ function displaySuccessMessage(appletUid, appletName, appletVersion) {
349
+ (0, log_1.log)('info', `\nApplet ${chalk_1.default.green(appletName)} version ${chalk_1.default.green(appletVersion)} (${chalk_1.default.blue(appletUid)}) uploaded successfully.`);
281
350
  }
282
351
  function displaySingleFileAppletDeprecationNote() {
283
352
  (0, log_1.log)('warning', `${chalk_1.default.red(`Applets with only applet-path file are ${chalk_1.default.bold(`deprecated`)}.`)} Please find more information at our website.`);
@@ -82,7 +82,7 @@ function getAppletDirectoryAbsolutePath(currentDirectory, options) {
82
82
  if (appletDirectoryPath.length > 1 && (appletDirectoryPath.endsWith('/') || appletDirectoryPath.endsWith('\\'))) {
83
83
  appletDirectoryPath = appletDirectoryPath.slice(0, -1);
84
84
  }
85
- (0, log_1.log)('info', `\nUse applet project directory path: ${appletDirectoryPath}`);
85
+ (0, log_1.log)('info', chalk_1.default.white(`Use applet project directory path: ${appletDirectoryPath}`) + '\n');
86
86
  const appletDirectoryPathExists = yield fs.pathExists(appletDirectoryPath);
87
87
  if (!appletDirectoryPathExists) {
88
88
  throw new Error(`Applet project directory not found: ${appletDirectoryPath}`);
@@ -105,7 +105,7 @@ function getAppletBinaryFileAbsolutePath(currentDirectory, options) {
105
105
  }
106
106
  // Normalize the path for cross-platform compatibility
107
107
  appletBinaryFilePath = path.normalize(appletBinaryFilePath);
108
- (0, log_1.log)('info', `\nUse applet binary file: ${appletBinaryFilePath}`);
108
+ (0, log_1.log)('info', chalk_1.default.white(`Use applet binary file: ${appletBinaryFilePath}` + '\n'));
109
109
  const appletBinaryFilePathExists = yield fs.pathExists(appletBinaryFilePath);
110
110
  if (!appletBinaryFilePathExists) {
111
111
  throw new Error(`Applet binary file not found: ${appletBinaryFilePath}`);
@@ -132,7 +132,7 @@ function getAppletEntryFileAbsolutePath(currentDirectory, options) {
132
132
  }
133
133
  // Normalize the path for cross-platform compatibility
134
134
  appletEntryFilePath = path.normalize(appletEntryFilePath);
135
- (0, log_1.log)('info', `\nUse applet entry file: ${appletEntryFilePath}`);
135
+ (0, log_1.log)('info', chalk_1.default.white(`Use applet entry file: ${appletEntryFilePath}`) + '\n');
136
136
  const appletEntryFilePathExists = yield fs.pathExists(appletEntryFilePath);
137
137
  if (!appletEntryFilePathExists) {
138
138
  throw new Error(`Applet entry file not found: ${appletEntryFilePath}\nDid you forget to build your applet by ${chalk_1.default.green('sos applet build')}?`);