aranea-sdk-cli 0.3.8 → 0.3.10

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.
@@ -353,10 +353,15 @@ exports.knowledgeCommand
353
353
  .option('--token <token>', '認証トークン')
354
354
  .option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
355
355
  .option('-y, --yes', '確認をスキップ')
356
+ .option('--force', 'Force operation on production (required for production)')
356
357
  .action(async (options) => {
357
358
  try {
358
359
  const env = (0, config_1.resolveEnvironment)(options.endpoint);
359
360
  (0, config_1.checkStagingAvailability)(env, 'knowledge delete --id <id>');
361
+ // Require --force for production
362
+ if (!(0, config_1.requireProductionConfirmation)(env, 'knowledge delete --id <id>', options.force)) {
363
+ process.exit(1);
364
+ }
360
365
  (0, config_1.warnIfProduction)(env, 'knowledge delete');
361
366
  console.log(chalk_1.default.bold(`\n=== Knowledge Delete (${env}) ===\n`));
362
367
  const token = options.token || await getAuthToken();
@@ -692,10 +692,15 @@ exports.schemaCommand
692
692
  .option('-e, --endpoint <env>', 'Environment (staging|production)', 'staging')
693
693
  .option('-d, --dry-run', 'Show what would be promoted without actually promoting')
694
694
  .option('-y, --confirm', 'Skip confirmation prompt')
695
+ .option('--force', 'Force operation on production (required for production)')
695
696
  .action(async (options) => {
696
697
  const env = (0, config_1.resolveEnvironment)(options.endpoint);
697
698
  // Check staging availability
698
699
  (0, config_1.checkStagingAvailability)(env, 'schema promote --type <type>');
700
+ // Require --force for production
701
+ if (!options.dryRun && !(0, config_1.requireProductionConfirmation)(env, 'schema promote --type <type>', options.force)) {
702
+ process.exit(1);
703
+ }
699
704
  const apiBase = getSchemaApiBase(env);
700
705
  // Always warn for promote
701
706
  console.log(chalk_1.default.yellow(`\nPromoting schema to PRODUCTION state in ${env} environment\n`));
@@ -880,6 +885,8 @@ exports.schemaCommand
880
885
  console.log(chalk_1.default.gray(` Promote: aranea-sdk schema promote --type ${schema.type} --endpoint ${env}`));
881
886
  }
882
887
  console.log(chalk_1.default.gray(` Get full schema: aranea-sdk schema get --type ${schema.type} --endpoint ${env} --json`));
888
+ console.log(chalk_1.default.gray(` History: aranea-sdk schema history --type ${schema.type} --endpoint ${env}`));
889
+ console.log(chalk_1.default.gray(` Rollback: aranea-sdk schema rollback --type ${schema.type} --version <v> --endpoint ${env}`));
883
890
  console.log('');
884
891
  }
885
892
  catch (error) {
@@ -893,3 +900,198 @@ exports.schemaCommand
893
900
  process.exit(1);
894
901
  }
895
902
  });
903
+ // schema history - show version history
904
+ exports.schemaCommand
905
+ .command('history')
906
+ .description('Show schema version history')
907
+ .requiredOption('-t, --type <type>', 'Type name')
908
+ .option('-e, --endpoint <env>', 'Environment (staging|production)', 'staging')
909
+ .option('-l, --limit <limit>', 'Number of versions to show', '10')
910
+ .action(async (options) => {
911
+ const env = (0, config_1.resolveEnvironment)(options.endpoint);
912
+ // Check staging availability
913
+ (0, config_1.checkStagingAvailability)(env, 'schema history --type <type>');
914
+ const apiBase = getSchemaApiBase(env);
915
+ const spinner = (0, ora_1.default)(`Fetching history for ${options.type} from ${env}...`).start();
916
+ try {
917
+ const response = await axios_1.default.get(`${apiBase}`, {
918
+ params: {
919
+ action: 'history',
920
+ type: options.type,
921
+ limit: options.limit,
922
+ },
923
+ });
924
+ spinner.stop();
925
+ if (!response.data.ok) {
926
+ console.log(chalk_1.default.red(`\nFailed to get history: ${response.data.error}`));
927
+ process.exit(1);
928
+ }
929
+ console.log(chalk_1.default.bold(`\n=== Schema History: ${options.type} (${env}) ===\n`));
930
+ const history = response.data.history || [];
931
+ if (history.length === 0) {
932
+ console.log(chalk_1.default.yellow('No version history found.'));
933
+ console.log(chalk_1.default.gray('Version history is created when schema is updated.'));
934
+ console.log('');
935
+ return;
936
+ }
937
+ console.log(chalk_1.default.cyan('Available Versions:'));
938
+ console.log('');
939
+ for (const entry of history) {
940
+ const stateIcon = entry.state === 'production' ? chalk_1.default.green('P') : chalk_1.default.yellow('D');
941
+ console.log(` [${stateIcon}] v${entry.version}`);
942
+ console.log(` State: ${entry.state} | Changed: ${entry.changedAt || 'N/A'}`);
943
+ console.log(` By: ${entry.changedBy || 'system'}`);
944
+ if (entry.changeReason) {
945
+ console.log(` Reason: ${entry.changeReason}`);
946
+ }
947
+ console.log('');
948
+ }
949
+ console.log(chalk_1.default.gray(`Legend: [${chalk_1.default.green('P')}]=Production [${chalk_1.default.yellow('D')}]=Development`));
950
+ console.log('');
951
+ console.log(chalk_1.default.gray('To rollback:'));
952
+ console.log(chalk_1.default.gray(` aranea-sdk schema rollback --type ${options.type} --version <version> --endpoint ${env}`));
953
+ console.log('');
954
+ }
955
+ catch (error) {
956
+ spinner.fail('Failed to fetch history');
957
+ console.log(chalk_1.default.red(`\nError: ${error.message}`));
958
+ process.exit(1);
959
+ }
960
+ });
961
+ // schema rollback - rollback to a previous version
962
+ exports.schemaCommand
963
+ .command('rollback')
964
+ .description('Rollback schema to a previous version')
965
+ .requiredOption('-t, --type <type>', 'Type name to rollback')
966
+ .requiredOption('-v, --version <version>', 'Target version number to rollback to')
967
+ .option('--token <token>', 'Firebase Auth ID token')
968
+ .option('-e, --endpoint <env>', 'Environment (staging|production)', 'staging')
969
+ .option('-d, --dry-run', 'Show what would be rolled back without actually doing it')
970
+ .option('-y, --confirm', 'Skip confirmation prompt')
971
+ .option('--force', 'Force operation on production (required for production)')
972
+ .action(async (options) => {
973
+ const env = (0, config_1.resolveEnvironment)(options.endpoint);
974
+ // Check staging availability
975
+ (0, config_1.checkStagingAvailability)(env, 'schema rollback --type <type> --version <v>');
976
+ // Require --force for production
977
+ if (!options.dryRun && !(0, config_1.requireProductionConfirmation)(env, 'schema rollback --type <type> --version <v>', options.force)) {
978
+ process.exit(1);
979
+ }
980
+ const apiBase = getSchemaApiBase(env);
981
+ console.log(chalk_1.default.yellow(`\n⚠️ Schema Rollback (${env})\n`));
982
+ const spinner = (0, ora_1.default)(`Fetching schema info: ${options.type}...`).start();
983
+ try {
984
+ // First, fetch current schema info and history
985
+ const [schemaResult, historyResult] = await Promise.all([
986
+ fetchSchema(apiBase, options.type),
987
+ axios_1.default.get(`${apiBase}`, {
988
+ params: { action: 'history', type: options.type, limit: 20 },
989
+ }),
990
+ ]);
991
+ spinner.stop();
992
+ if (!schemaResult.ok) {
993
+ console.log(chalk_1.default.red(`Schema "${options.type}" not found`));
994
+ process.exit(1);
995
+ }
996
+ const schema = schemaResult.schema;
997
+ const history = historyResult.data.history || [];
998
+ const targetVersion = parseInt(options.version, 10);
999
+ // Find target version in history
1000
+ const targetEntry = history.find((h) => h.version === targetVersion);
1001
+ if (!targetEntry) {
1002
+ console.log(chalk_1.default.red(`Version ${targetVersion} not found in history`));
1003
+ console.log('');
1004
+ console.log(chalk_1.default.yellow('Available versions:'));
1005
+ history.forEach((h) => {
1006
+ console.log(` v${h.version} (${h.state}) - ${h.changedAt || 'N/A'}`);
1007
+ });
1008
+ console.log('');
1009
+ process.exit(1);
1010
+ }
1011
+ // Show rollback info
1012
+ console.log(chalk_1.default.bold('Current Schema:'));
1013
+ console.log(` Type: ${schema.type}`);
1014
+ console.log(` State: ${schema.state === 'production' ? chalk_1.default.green(schema.state) : chalk_1.default.yellow(schema.state)}`);
1015
+ console.log(` Version: ${schema.version || schema.revisionNumber || 'N/A'}`);
1016
+ console.log('');
1017
+ console.log(chalk_1.default.bold('Rollback Target:'));
1018
+ console.log(` Version: v${targetVersion}`);
1019
+ console.log(` State at time: ${targetEntry.state}`);
1020
+ console.log(` Changed: ${targetEntry.changedAt || 'N/A'}`);
1021
+ console.log(` By: ${targetEntry.changedBy || 'system'}`);
1022
+ if (targetEntry.changeReason) {
1023
+ console.log(` Reason: ${targetEntry.changeReason}`);
1024
+ }
1025
+ console.log('');
1026
+ if (options.dryRun) {
1027
+ console.log(chalk_1.default.bold('=== Dry Run: Would Rollback ===\n'));
1028
+ console.log(` From: current (v${schema.version || schema.revisionNumber || '?'})`);
1029
+ console.log(` To: v${targetVersion}`);
1030
+ console.log('');
1031
+ console.log(chalk_1.default.gray('Remove --dry-run to actually rollback'));
1032
+ return;
1033
+ }
1034
+ // Confirmation step
1035
+ if (!options.confirm) {
1036
+ console.log(chalk_1.default.red('This will rollback the schema to a previous version.'));
1037
+ console.log(chalk_1.default.red('The current version will be saved in history.'));
1038
+ console.log('');
1039
+ const confirmed = await promptConfirm('Are you sure you want to proceed?');
1040
+ if (!confirmed) {
1041
+ console.log(chalk_1.default.yellow('\nRollback cancelled.'));
1042
+ return;
1043
+ }
1044
+ }
1045
+ const token = getAuthToken(options);
1046
+ if (!token) {
1047
+ console.log(chalk_1.default.red('\nAuthentication required'));
1048
+ console.log(chalk_1.default.yellow('Provide a token using one of:'));
1049
+ console.log(' --token <TOKEN>');
1050
+ console.log(' export ARANEA_AUTH_TOKEN=<TOKEN>');
1051
+ process.exit(1);
1052
+ }
1053
+ const rollbackSpinner = (0, ora_1.default)(`Rolling back ${options.type} to v${targetVersion}...`).start();
1054
+ // Call the API to rollback
1055
+ const response = await axios_1.default.post(`${apiBase}`, {
1056
+ action: 'rollback',
1057
+ type: options.type,
1058
+ targetVersion: targetVersion,
1059
+ }, {
1060
+ headers: {
1061
+ 'Content-Type': 'application/json',
1062
+ Authorization: `Bearer ${token}`,
1063
+ },
1064
+ });
1065
+ if (response.data.ok) {
1066
+ rollbackSpinner.succeed(`Schema "${options.type}" rolled back to v${targetVersion}`);
1067
+ console.log('');
1068
+ console.log(` New Version: v${response.data.newVersion || 'N/A'}`);
1069
+ if (response.data.warnings) {
1070
+ response.data.warnings.forEach((w) => {
1071
+ console.log(` ${chalk_1.default.yellow(w)}`);
1072
+ });
1073
+ }
1074
+ console.log('');
1075
+ }
1076
+ else {
1077
+ rollbackSpinner.fail(`Rollback failed: ${response.data.error || 'Unknown error'}`);
1078
+ process.exit(1);
1079
+ }
1080
+ }
1081
+ catch (error) {
1082
+ if (error.response?.status === 401) {
1083
+ console.log(chalk_1.default.red('\nAuthentication failed - invalid or expired token'));
1084
+ console.log(chalk_1.default.yellow('Token is valid for 1 hour. Please refresh your token.'));
1085
+ }
1086
+ else if (error.response?.status === 403) {
1087
+ console.log(chalk_1.default.red('\nPermission denied - insufficient privileges'));
1088
+ }
1089
+ else if (error.response?.data?.error) {
1090
+ console.log(chalk_1.default.red(`\nRollback failed: ${error.response.data.error}`));
1091
+ }
1092
+ else {
1093
+ console.log(chalk_1.default.red(`\nRollback failed: ${error.message}`));
1094
+ }
1095
+ process.exit(1);
1096
+ }
1097
+ });
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ const program = new commander_1.Command();
28
28
  program
29
29
  .name('aranea-sdk')
30
30
  .description('AraneaSDK CLI - デバイス開発支援ツール')
31
- .version('0.3.8');
31
+ .version('0.3.10');
32
32
  // test コマンド
33
33
  program.addCommand(test_1.testCommand);
34
34
  // simulate コマンド
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aranea-sdk-cli",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "description": "AraneaSDK CLI - ESP32 IoTデバイス開発支援ツール",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",